diff --git a/wpiformat/wpiformat/__init__.py b/wpiformat/wpiformat/__init__.py index a80367d..5cd3a71 100644 --- a/wpiformat/wpiformat/__init__.py +++ b/wpiformat/wpiformat/__init__.py @@ -23,7 +23,7 @@ from wpiformat.lint import Lint from wpiformat.pyformat import PyFormat from wpiformat.stdlib import Stdlib -from wpiformat.task import Task +from wpiformat.task import BatchTask, PipelineTask, StandaloneTask, Task from wpiformat.usingdeclaration import UsingDeclaration from wpiformat.usingnamespacestd import UsingNamespaceStd from wpiformat.whitespace import Whitespace @@ -212,6 +212,16 @@ def run_pipeline(task_pipeline, args, files): """ init_args = (task_pipeline, args.verbose1, args.verbose2) + # Check tasks are all pipeline tasks + invalid_tasks = [ + type(task).__name__ + for task in task_pipeline + if not issubclass(type(task), PipelineTask) + ] + if invalid_tasks: + print(f"error: the following pipeline tasks are invalid: {invalid_tasks}") + sys.exit(1) + with mp.Pool(args.jobs, proc_init, init_args) as pool: # Start worker processes for task pipeline results = pool.map(proc_pipeline, files) @@ -220,40 +230,61 @@ def run_pipeline(task_pipeline, args, files): sys.exit(1) -def run_standalone(task_pipeline, args, files): - """Spawns process pool for proc_standalone(). +def run_batch(task_pipeline, args, file_batches): + """Spawns process pool for proc_batch(). Keyword arguments: task_pipeline -- task pipeline args -- command line arguments from argparse - files -- list of file names to process + file_batches -- list of file names to process Calls sys.exit(1) if any task fails. """ init_args = (task_pipeline, args.verbose1, args.verbose2) + # Check tasks are all batch tasks + invalid_tasks = [ + type(task).__name__ + for task in task_pipeline + if not issubclass(type(task), BatchTask) + ] + if invalid_tasks: + print(f"error: the following batch tasks are invalid: {invalid_tasks}") + sys.exit(1) + with mp.Pool(args.jobs, proc_init, init_args) as pool: - # Start worker processes for task pipeline - results = pool.map(proc_standalone, files) + # Start worker processes for batch tasks + results = pool.map(proc_batch, file_batches) if not all(results): sys.exit(1) -def run_batch(task_pipeline, args, file_batches): - """Spawns process pool for proc_batch(). +def run_standalone(task_pipeline, args, files): + """Spawns process pool for proc_standalone(). Keyword arguments: task_pipeline -- task pipeline args -- command line arguments from argparse - file_batches -- list of file names to process + files -- list of file names to process + Calls sys.exit(1) if any task fails. """ init_args = (task_pipeline, args.verbose1, args.verbose2) + # Check tasks are all standalone tasks + invalid_tasks = [ + type(task).__name__ + for task in task_pipeline + if not issubclass(type(task), StandaloneTask) + ] + if invalid_tasks: + print(f"error: the following standalone tasks are invalid: {invalid_tasks}") + sys.exit(1) + with mp.Pool(args.jobs, proc_init, init_args) as pool: - # Start worker processes for batch tasks - results = pool.map(proc_batch, file_batches) + # Start worker processes for task pipeline + results = pool.map(proc_standalone, files) if not all(results): sys.exit(1) @@ -497,18 +528,6 @@ def main(): ClangFormat(args.clang_version), Jni(), # Fixes clang-format formatting ] - - # Check tasks are all pipeline tasks - invalid_tasks = [ - type(task).__name__ - for task in task_pipeline - # Pipeline tasks must override run_pipeline - if Task.run_pipeline == type(task).run_pipeline - ] - if invalid_tasks: - print(f"error: the following pipeline tasks are invalid: {invalid_tasks}") - return False - run_pipeline(task_pipeline, args, files) # Lint is run last since previous tasks can affect its output. @@ -519,17 +538,6 @@ def main(): else: task_pipeline = [CMakeFormat(), PyFormat(), Lint()] - # Check tasks are all batch tasks - invalid_tasks = [ - type(task).__name__ - for task in task_pipeline - # Batch tasks must override run_batch - if Task.run_batch == type(task).run_batch - ] - if invalid_tasks: - print(f"error: the following batch tasks are invalid: {invalid_tasks}") - return False - run_batch(task_pipeline, args, file_batches) # ClangTidy is run last of all; it needs the actual files diff --git a/wpiformat/wpiformat/bracecomment.py b/wpiformat/wpiformat/bracecomment.py index dd70ba0..ad41596 100644 --- a/wpiformat/wpiformat/bracecomment.py +++ b/wpiformat/wpiformat/bracecomment.py @@ -4,10 +4,10 @@ import regex -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class BraceComment(Task): +class BraceComment(PipelineTask): @staticmethod def should_process_file(config_file, name): return config_file.is_c_file(name) or config_file.is_cpp_file(name) diff --git a/wpiformat/wpiformat/cidentlist.py b/wpiformat/wpiformat/cidentlist.py index 62ead08..8557b42 100644 --- a/wpiformat/wpiformat/cidentlist.py +++ b/wpiformat/wpiformat/cidentlist.py @@ -2,10 +2,10 @@ import regex -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class CIdentList(Task): +class CIdentList(PipelineTask): @staticmethod def __print_failure(name): print( diff --git a/wpiformat/wpiformat/clangformat.py b/wpiformat/wpiformat/clangformat.py index c023dd0..985bb0d 100644 --- a/wpiformat/wpiformat/clangformat.py +++ b/wpiformat/wpiformat/clangformat.py @@ -5,10 +5,10 @@ import clang_format -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class ClangFormat(Task): +class ClangFormat(PipelineTask): def __init__(self, clang_version): """Constructor for ClangFormat task. diff --git a/wpiformat/wpiformat/clangtidy.py b/wpiformat/wpiformat/clangtidy.py index 905dc23..676a2de 100644 --- a/wpiformat/wpiformat/clangtidy.py +++ b/wpiformat/wpiformat/clangtidy.py @@ -5,10 +5,10 @@ import clang_tidy -from wpiformat.task import Task +from wpiformat.task import StandaloneTask -class ClangTidy(Task): +class ClangTidy(StandaloneTask): def __init__(self, clang_version, compile_commands, extra_args): """Constructor for ClangTidy task. diff --git a/wpiformat/wpiformat/cmakeformat.py b/wpiformat/wpiformat/cmakeformat.py index a8e2507..692e2cb 100644 --- a/wpiformat/wpiformat/cmakeformat.py +++ b/wpiformat/wpiformat/cmakeformat.py @@ -3,10 +3,10 @@ import subprocess import sys -from wpiformat.task import Task +from wpiformat.task import BatchTask -class CMakeFormat(Task): +class CMakeFormat(BatchTask): @staticmethod def should_process_file(config_file, name): return name.endswith("CMakeLists.txt") or name.endswith(".cmake") diff --git a/wpiformat/wpiformat/eofnewline.py b/wpiformat/wpiformat/eofnewline.py index 40ec1d6..06bdb6d 100644 --- a/wpiformat/wpiformat/eofnewline.py +++ b/wpiformat/wpiformat/eofnewline.py @@ -1,8 +1,8 @@ """This task ensures that the file has exactly one EOF newline.""" -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class EofNewline(Task): +class EofNewline(PipelineTask): def run_pipeline(self, config_file, name, lines): return lines.rstrip() + super().get_linesep(lines), True diff --git a/wpiformat/wpiformat/gtestname.py b/wpiformat/wpiformat/gtestname.py index a6858ec..dd47a6c 100644 --- a/wpiformat/wpiformat/gtestname.py +++ b/wpiformat/wpiformat/gtestname.py @@ -4,10 +4,10 @@ import regex -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class GTestName(Task): +class GTestName(PipelineTask): @staticmethod def should_process_file(config_file, name): return config_file.is_cpp_file(name) diff --git a/wpiformat/wpiformat/includeguard.py b/wpiformat/wpiformat/includeguard.py index 8f1ad3f..0851ad3 100644 --- a/wpiformat/wpiformat/includeguard.py +++ b/wpiformat/wpiformat/includeguard.py @@ -6,7 +6,7 @@ import regex from enum import Enum -from wpiformat.task import Task +from wpiformat.task import PipelineTask class State(Enum): @@ -15,7 +15,7 @@ class State(Enum): DONE = 3 -class IncludeGuard(Task): +class IncludeGuard(PipelineTask): @staticmethod def should_process_file(config_file, name): return config_file.is_header_file(name) diff --git a/wpiformat/wpiformat/includeorder.py b/wpiformat/wpiformat/includeorder.py index fb84fb4..4f2af6b 100644 --- a/wpiformat/wpiformat/includeorder.py +++ b/wpiformat/wpiformat/includeorder.py @@ -3,10 +3,10 @@ import os import regex -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class IncludeOrder(Task): +class IncludeOrder(PipelineTask): def __init__(self): super().__init__() diff --git a/wpiformat/wpiformat/javaclass.py b/wpiformat/wpiformat/javaclass.py index a83899f..5107815 100644 --- a/wpiformat/wpiformat/javaclass.py +++ b/wpiformat/wpiformat/javaclass.py @@ -2,10 +2,10 @@ import regex -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class JavaClass(Task): +class JavaClass(PipelineTask): @staticmethod def should_process_file(config_file, name): return name.endswith(".java") diff --git a/wpiformat/wpiformat/jni.py b/wpiformat/wpiformat/jni.py index 890f0a6..5f8b4d2 100644 --- a/wpiformat/wpiformat/jni.py +++ b/wpiformat/wpiformat/jni.py @@ -21,10 +21,10 @@ import regex -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class Jni(Task): +class Jni(PipelineTask): @staticmethod def should_process_file(config_file, name): return config_file.is_cpp_src_file(name) diff --git a/wpiformat/wpiformat/licenseupdate.py b/wpiformat/wpiformat/licenseupdate.py index 81bcbd6..724a1a1 100644 --- a/wpiformat/wpiformat/licenseupdate.py +++ b/wpiformat/wpiformat/licenseupdate.py @@ -7,10 +7,10 @@ import sys from wpiformat.config import Config -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class LicenseUpdate(Task): +class LicenseUpdate(PipelineTask): @staticmethod def should_process_file(config_file, name): license_regex = config_file.regex("licenseUpdateExclude") diff --git a/wpiformat/wpiformat/lint.py b/wpiformat/wpiformat/lint.py index c203796..8b12f68 100644 --- a/wpiformat/wpiformat/lint.py +++ b/wpiformat/wpiformat/lint.py @@ -12,10 +12,10 @@ import sys from wpiformat import cpplint -from wpiformat.task import Task +from wpiformat.task import BatchTask -class Lint(Task): +class Lint(BatchTask): @staticmethod def should_process_file(config_file, name): return config_file.is_cpp_file(name) diff --git a/wpiformat/wpiformat/pyformat.py b/wpiformat/wpiformat/pyformat.py index ba4b2ee..9e6cbeb 100644 --- a/wpiformat/wpiformat/pyformat.py +++ b/wpiformat/wpiformat/pyformat.py @@ -4,10 +4,10 @@ import subprocess import sys -from wpiformat.task import Task +from wpiformat.task import BatchTask -class PyFormat(Task): +class PyFormat(BatchTask): @staticmethod def should_process_file(config_file, name): return name.endswith(".py") diff --git a/wpiformat/wpiformat/stdlib.py b/wpiformat/wpiformat/stdlib.py index abd3fbd..ac3472a 100644 --- a/wpiformat/wpiformat/stdlib.py +++ b/wpiformat/wpiformat/stdlib.py @@ -4,7 +4,7 @@ import regex -from wpiformat.task import Task +from wpiformat.task import PipelineTask class Header: @@ -70,7 +70,7 @@ def __init__(self, name, func_names=None, type_regexes=None, add_prefix=True): self.type_regex = None -class Stdlib(Task): +class Stdlib(PipelineTask): def __init__(self): super().__init__() diff --git a/wpiformat/wpiformat/task.py b/wpiformat/wpiformat/task.py index b1819b2..ad8008a 100644 --- a/wpiformat/wpiformat/task.py +++ b/wpiformat/wpiformat/task.py @@ -1,17 +1,10 @@ -"""Provides a task base class for use by format.py. +"""Task base classes for wpiformat.""" -format.py excludes matches for the "modifiable" regex before checking for -modifications to generated files because some of the regexes from each group -overlap. -""" - -from abc import * +from abc import ABCMeta, abstractmethod import os -class Task: - __metaclass__ = ABCMeta - +class Task(metaclass=ABCMeta): @staticmethod def get_linesep(lines): """Returns string containing autodetected line separator for file. @@ -44,7 +37,6 @@ def get_repo_root(): return "" @staticmethod - @abstractmethod def should_process_file(config_file, name): """Returns true if file should be processed by this task. @@ -56,6 +48,8 @@ def should_process_file(config_file, name): """ return True + +class PipelineTask(Task): @abstractmethod def run_pipeline(self, config_file, name, lines): """Performs task on file with given lines. @@ -72,6 +66,8 @@ def run_pipeline(self, config_file, name, lines): """ return ("", True) + +class BatchTask(Task): @staticmethod @abstractmethod def run_batch(config_file, names): @@ -84,6 +80,22 @@ def run_batch(config_file, names): config_file -- Config object names -- list of file name strings - Returns True if task succeeded in formatting the files. + Returns True if task succeeded in processing the files. + """ + return True + + +class StandaloneTask(Task): + @abstractmethod + def run_standalone(self, config_file, name): + """Performs task on a file. + + This function is for processing the file on its own. + + Keyword arguments: + config_file -- Config object + name -- file name string + + Returns True if task succeeded in processing the file. """ return True diff --git a/wpiformat/wpiformat/usingdeclaration.py b/wpiformat/wpiformat/usingdeclaration.py index d20ef36..f2e19a0 100644 --- a/wpiformat/wpiformat/usingdeclaration.py +++ b/wpiformat/wpiformat/usingdeclaration.py @@ -2,10 +2,10 @@ import regex -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class UsingDeclaration(Task): +class UsingDeclaration(PipelineTask): @staticmethod def should_process_file(config_file, name): return config_file.is_cpp_header_file(name) diff --git a/wpiformat/wpiformat/usingnamespacestd.py b/wpiformat/wpiformat/usingnamespacestd.py index 3c1f736..f649a19 100644 --- a/wpiformat/wpiformat/usingnamespacestd.py +++ b/wpiformat/wpiformat/usingnamespacestd.py @@ -2,10 +2,10 @@ import regex -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class UsingNamespaceStd(Task): +class UsingNamespaceStd(PipelineTask): @staticmethod def should_process_file(config_file, name): return config_file.is_cpp_file(name) diff --git a/wpiformat/wpiformat/whitespace.py b/wpiformat/wpiformat/whitespace.py index a35794a..276ee76 100644 --- a/wpiformat/wpiformat/whitespace.py +++ b/wpiformat/wpiformat/whitespace.py @@ -2,10 +2,10 @@ import os -from wpiformat.task import Task +from wpiformat.task import PipelineTask -class Whitespace(Task): +class Whitespace(PipelineTask): def run_pipeline(self, config_file, name, lines): linesep = super().get_linesep(lines)