diff --git a/.gitignore b/.gitignore index d5e4f15..5ad7957 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -**/__pycache__ \ No newline at end of file +**/__pycache__ +venv +.venv \ No newline at end of file diff --git a/README.md b/README.md index 9d2b02a..40b3645 100644 --- a/README.md +++ b/README.md @@ -50,12 +50,12 @@ The above entries in a `.standardignore` would have the checker skip over the fo Using the `.standardignore` file specified in the section above, specific function and variable names can be skipped over on the check. -The syntax to do so is the use of the `!` before the name of the variable/function to ignore. +The syntax to do so is the use of the `name:` before the name of the variable/function to ignore. For example ```cmd -!sleep_for_retry +name: sleep_for_retry ``` The above example ignores the sleep_for_retry function when applying standards as the name is required as it is an overwrite of an outside modules functionality. diff --git a/StandardCheck.py b/StandardCheck.py index 7bf9cfe..538590c 100644 --- a/StandardCheck.py +++ b/StandardCheck.py @@ -16,7 +16,7 @@ import checkers.complexity as complexity_module -def visit_node(node: ast.AST, file_path: str, ignore_codes: set[str], ignore_names: set[str] = None) -> list[models.StyleError]: +def visit_node(node: ast.AST, file_path: str, ignore_codes: set[str], ignore_names: set[str] = set()) -> list[models.StyleError]: """Visit an AST node and perform checks. Args: @@ -28,7 +28,6 @@ def visit_node(node: ast.AST, file_path: str, ignore_codes: set[str], ignore_nam Returns: list of style errors found """ - ignore_names = ignore_names or set() if isinstance(node, ast.ClassDef): return common_nodes_module.check_class(node, file_path, ignore_codes, ignore_names) @@ -40,7 +39,7 @@ def visit_node(node: ast.AST, file_path: str, ignore_codes: set[str], ignore_nam return [] -def check_file(file_path: Path, ignore_codes: set[str], ignore_names: set[str] = None, config: dict[str, Any] = None) -> list[models.StyleError]: +def check_file(file_path: Path, ignore_codes: set[str], ignore_names: set[str] = set(), config: dict[str, Any] | None = None) -> list[models.StyleError]: """Check a single Python file. Args: @@ -52,9 +51,10 @@ def check_file(file_path: Path, ignore_codes: set[str], ignore_names: set[str] = Returns: list of style errors found """ + if not config: + config = {} + errors = [] - ignore_names = ignore_names or set() - config = config or {} max_complexity = config.get('max_complexity', 15) max_indentation = config.get('max_indentation', 4) diff --git a/checkers/common_nodes.py b/checkers/common_nodes.py index 4416386..df5c5d1 100644 --- a/checkers/common_nodes.py +++ b/checkers/common_nodes.py @@ -6,7 +6,7 @@ import utils.patterns as patterns_module import checkers.error_creation as error_creation_module -def check_variable(node: ast.Name, file_path: str, ignore_codes: set[str], ignore_names: set[str] = None) -> list[models.StyleError]: +def check_variable(node: ast.Name, file_path: str, ignore_codes: set[str], ignore_names: set[str] = set()) -> list[models.StyleError]: """Check variable naming. Args: @@ -18,8 +18,7 @@ def check_variable(node: ast.Name, file_path: str, ignore_codes: set[str], ignor Returns: list of style errors found """ - errors = [] - ignore_names = ignore_names or set() + errors: list[models.StyleError] = [] # Skip if name should be ignored if file_utils_module.should_ignore_name(node.id, ignore_names): @@ -38,7 +37,7 @@ def check_variable(node: ast.Name, file_path: str, ignore_codes: set[str], ignor return errors -def check_class(node: ast.ClassDef, file_path: str, ignore_codes: set[str], ignore_names: set[str] = None) -> list[models.StyleError]: +def check_class(node: ast.ClassDef, file_path: str, ignore_codes: set[str], ignore_names: set[str] = set()) -> list[models.StyleError]: """Check class definition. Args: @@ -50,8 +49,7 @@ def check_class(node: ast.ClassDef, file_path: str, ignore_codes: set[str], igno Returns: list of style errors found """ - errors = [] - ignore_names = ignore_names or set() + errors: list[models.StyleError] = [] # Skip if name should be ignored if file_utils_module.should_ignore_name(node.name, ignore_names): @@ -98,7 +96,7 @@ def _is_valid_class_name(name: str) -> bool: return False -def check_function(node: ast.FunctionDef | ast.AsyncFunctionDef, file_path: str, ignore_codes: set[str], ignore_names: set[str] = None) -> list[models.StyleError]: +def check_function(node: ast.FunctionDef | ast.AsyncFunctionDef, file_path: str, ignore_codes: set[str], ignore_names: set[str] = set()) -> list[models.StyleError]: """Check function definition. Args: @@ -110,8 +108,7 @@ def check_function(node: ast.FunctionDef | ast.AsyncFunctionDef, file_path: str, Returns: list of style errors found """ - errors = [] - ignore_names = ignore_names or set() + errors: list[models.StyleError] = [] is_test_file = 'test' in file_path.lower() if file_utils_module.should_ignore_name(node.name, ignore_names): @@ -199,7 +196,7 @@ def _check_function_docstrings(node: ast.FunctionDef | ast.AsyncFunctionDef, fil Returns: list of style errors related to function docstrings """ - errors = [] + errors: list[models.StyleError] = [] # Skip docstring checks for @overload functions if _has_overload_decorator(node): @@ -230,7 +227,7 @@ def _check_docstring_format(node: ast.FunctionDef | ast.AsyncFunctionDef | ast.C Returns: list of style errors found """ - errors = [] + errors: list[models.StyleError] = [] if not docstring: return errors summary = docstring.split('\n\n')[0].strip() @@ -264,7 +261,7 @@ def _check_function_docstring(node: ast.FunctionDef | ast.AsyncFunctionDef, file Returns: list of style errors found """ - errors = [] + errors: list[models.StyleError] = [] docstring = ast.get_docstring(node) if not docstring: diff --git a/checkers/complexity.py b/checkers/complexity.py index 0c79ffe..3bede76 100644 --- a/checkers/complexity.py +++ b/checkers/complexity.py @@ -3,7 +3,7 @@ import models as models -def check_complexity(tree: ast.Module, content: str, file_path: str, ignore_codes: set[str], max_complexity: int = 15, max_indentation: int = 4) -> list[models.StyleError]: +def check_complexity(tree: ast.AST, content: str, file_path: str, ignore_codes: set[str], max_complexity: int = 15, max_indentation: int = 4) -> list[models.StyleError]: """Check cyclomatic complexity and indentation depth for all functions in a file. Args: diff --git a/checkers/imports.py b/checkers/imports.py index a235921..ca9345e 100644 --- a/checkers/imports.py +++ b/checkers/imports.py @@ -24,7 +24,7 @@ def collect_imports(tree: ast.AST) -> tuple[list[ast.Import | ast.ImportFrom], l return imports + import_froms, import_froms -def check_imports(all_imports: list[ast.AST], import_froms: list[ast.ImportFrom], used_names: set[str], file_path: Path, ignore_codes: set[str]) -> list[models.StyleError]: +def check_imports(all_imports: list[ast.Import | ast.ImportFrom], import_froms: list[ast.ImportFrom], used_names: set[str], file_path: Path, ignore_codes: set[str]) -> list[models.StyleError]: """Run all import-related checks. Args: @@ -56,7 +56,7 @@ def _check_import_order(imports: list[ast.Import | ast.ImportFrom], file_path: s Returns: list of style errors found """ - errors = [] + errors: list[models.StyleError] = [] if not imports: return errors @@ -164,7 +164,7 @@ def _check_unused_imports(imports: list[ast.Import | ast.ImportFrom], names_used try: with open(file_path, 'r', encoding='utf-8') as f: file_content = f.read() - except: + except(Exception): file_content = "" for imp in imports: @@ -217,7 +217,7 @@ def _check_unused_from_import_nodes(imp: ast.ImportFrom, names_used: set[str], f Returns: an unused import error, or None """ - errors = [] + errors: list[models.StyleError] = [] # Never flag __future__ imports as unused if imp.module == '__future__': diff --git a/checkers/security.py b/checkers/security.py index 11990ff..49fc940 100644 --- a/checkers/security.py +++ b/checkers/security.py @@ -115,7 +115,7 @@ def _check_sql_injection_call(node: ast.AST, file_path: str, ignore_codes: set[s Returns: the sql injection errors, if any """ - errors = [] + errors: list[models.StyleError] = [] if not isinstance(node, ast.Call): return errors if not (isinstance(node.func, ast.Attribute) and node.func.attr in ['execute', 'executemany']): @@ -167,7 +167,7 @@ def _check_shell_injection_call(node: ast.AST, file_path: str, ignore_codes: set Returns: the shell injection errors, if any """ - errors = [] + errors: list[models.StyleError] = [] if not isinstance(node, ast.Call): return errors is_bad_attr = isinstance(node.func, ast.Attribute) and node.func.attr in ['system', 'popen', 'spawn', 'exec'] diff --git a/config.py b/config.py index d1a8dcc..d36641b 100644 --- a/config.py +++ b/config.py @@ -48,7 +48,7 @@ def load_ignore_names() -> set[str]: Returns: Set of names to ignore in style checking """ - ignore_names = set() + ignore_names: set = set() ignore_file = Path('.standardignore') if not ignore_file.exists(): diff --git a/requirements.txt b/requirements.txt index 1855cd0..e94e123 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -pathspec==0.12.1 \ No newline at end of file +pathspec ~= 1.1 \ No newline at end of file