#!/usr/bin/env python3 import os import glob import logging class UncommentProcess: comment_state = False code = 'uncomment' def start(self): self.comment_state = False def exec(self, line) -> str: """ :param str line: :return str: """ stripped = line.strip() if self.comment_state is True: if stripped.endswith('*/'): self.comment_state = False return '' else: if stripped.startswith('/*'): self.comment_state = True return '' if stripped.startswith('//'): return '' return line class Combine: params = { 'files_mask': "*.php", 'input_dir': "./", 'processes': ['uncomment'], 'format': 'docx' } files = 0 lines = 0 processes = [] def __init__(self, output_file, params): """ :param str output_file: :param dict params: """ for key, val in params.items(): if key in self.params.keys(): self.params[key] = val self.output_file_path = os.path.abspath(output_file) logging.debug(self.params) for code in self.params['processes']: if code == UncommentProcess.code: self.processes.append(UncommentProcess()) def combine(self): """ :return: """ self.files = 0 with open(self.output_file_path, 'w+') as f: for file_path in self._find_files_in(self.params.get('input_dir'), self.params.get('files_mask')): self.lines = 0 logging.debug(file_path) self._output_text_to_file(f, title=file_path) for line in self._collect_text_from_file(file_path, self.processes): self._output_text_to_file(f, line=line) self.lines += 1 self.files += 1 logging.debug('combined {} lines'.format(self.lines)) logging.info('combined {} files'.format(self.files)) def _find_files_in(self, folder, mask): folder = os.path.abspath(folder) files_paths = glob.glob(os.path.join(folder, '**', mask), recursive=True) logging.info('found {} files with [{}] mask'.format(len(files_paths), mask)) for file_path in files_paths: yield file_path def _collect_text_from_file(self, file_path, processes): """ :param str file_path: :param list processes: :return: """ with open(file_path, 'r') as f: for line in f.readlines(): yield self._processor(line, processes) def _processor(self, line, processes): """ :param str line: :param list processes: :return: """ for process in processes: line = process.exec(line) return line def _output_text_to_file(self, file, line=None, title=None): """ :param file: :param str line: :param str title: :return: """ if title is not None: seps = '-'.rjust(128, '-') file.write("\n{}\n{}\n{}\n".format(seps, title, seps)) elif line is not None: file.write(line) if __name__ == '__main__': import argparse parser = argparse.ArgumentParser() parser.add_argument('output_file', help="файл, в который запишется исходный код", type=str) parser.add_argument('-m', '--files_mask', help="маска для выбора файлов", default=Combine.params['files_mask'], type=str) parser.add_argument('-i', '--input_dir', help="директория, в которой будут взяты все файлы подходящие под маску", default=Combine.params['input_dir']) parser.add_argument('-p', '--processes', help="действия, выполняемые при обработке", type=list, default=Combine.params['processes']) parser.add_argument('-f', '--format', help="формат output_file", default=Combine.params['format']) parser.add_argument('-l', '--log', default='debug') parser.description = """ Взять все файлы в указанной директории, подходящие по маске, и объединить их в один текстовый файл """ args = parser.parse_args() loglevel = getattr(logging, args.log.upper()) logging.basicConfig(format='%(levelname)s:%(message)s', level=loglevel) combiner = Combine(args.output_file, vars(args)) combiner.combine()