def main() -> Optional[int]: has_errors = False for pyfilepath in get_input_files(): ast_tree, file_content = get_ast_tree_with_content(pyfilepath) if ast_tree is None or file_content is None: continue for annotated in itertools.chain( [ n.annotation for n in ast.walk(ast_tree) if isinstance(n, ast.AnnAssign) ], [ n.annotation for n in ast.walk(ast_tree) if isinstance(n, ast.arg) and n.annotation ], [ n.returns for n in ast.walk(ast_tree) if isinstance(n, ast.FunctionDef) and n.returns ], ): if isinstance(annotated, ast.Str): has_errors = True print( # noqa: T001 '{0}:{1} old style annotation'.format( pyfilepath, annotated.lineno, ), ) if has_errors: return 1
def main() -> Optional[int]: max_expression_complexity = 9 ignore_django_orm_queries = True has_errors = False for pyfilepath in get_input_files(): ast_tree_results = get_ast_tree_with_content(pyfilepath) ast_tree, file_content = ast_tree_results if ast_tree is None or file_content is None: continue file_lines = file_content.split('\n') for expression in iterate_over_expressions(ast_tree): if ignore_django_orm_queries and is_django_orm_query(expression): continue complexity = get_expression_complexity(expression) if complexity > max_expression_complexity and '# noqa' not in file_lines[ expression.lineno - 1]: has_errors = True print( # noqa: T001 '{0}:{1} ({2}>{3})'.format( pyfilepath, expression.lineno, complexity, max_expression_complexity, ), ) if has_errors: return 1
def main() -> typing.Optional[int]: settings_files = [ filepath for filepath in get_input_files() if 'settings/' in filepath and not filepath.endswith('/__init__.py') ] straight_assignment_error = False for settings_filepath in settings_files: ast_tree, ast_content = get_ast_tree_with_content(settings_filepath) if ast_tree is None: continue lines_with_noqa = exclude_lines_with_noqa(settings_filepath) lines_with_straight_assignment, lines_with_static_objects = get_line_numbers_of_wrong_assignments( ast_tree, ast_content, ast_tree, 0) lines_with_straight_assignment = lines_with_straight_assignment.difference(lines_with_noqa) lines_with_static_objects = lines_with_static_objects.difference(lines_with_noqa) for line_number in sorted(lines_with_straight_assignment): print(f'{settings_filepath}:{line_number} : straight assignment') # noqa: T001 straight_assignment_error = True for line_number in sorted(lines_with_static_objects): print(f'{settings_filepath}:{line_number} : static object') # noqa: T001 straight_assignment_error = True if straight_assignment_error: return 1
def main() -> typing.Optional[int]: settings_files = [ filepath for filepath in get_input_files() if 'settings/' in filepath and not filepath.endswith('/__init__.py') ] fail = False for settings_filepath in settings_files: ast_tree, ast_content = get_ast_tree_with_content(settings_filepath) if ast_tree is None: continue lines_with_noqa = exclude_lines_with_noqa(settings_filepath) line_errors = [ line_error for line_error in get_line_numbers_of_wrong_assignments( ast_tree, ast_content, ast_tree) if line_error.lineno not in lines_with_noqa ] for line_error in sorted(line_errors, key=lambda le: le.lineno): print(f'{settings_filepath}:{line_error}') fail = True if fail: return 1
def find_too_long_py_files(allowed_amount: int, filenames: List[str]) -> DefaultDict[str, int]: too_long_files: DefaultDict[str, int] = collections.defaultdict(int) for py_file_name in get_input_files(filenames): amount_of_lines = count_amount_of_lines_in_file(filepath=py_file_name) if amount_of_lines <= allowed_amount: continue too_long_files[py_file_name] = amount_of_lines return too_long_files
def main() -> int: has_errors = False for pyfilepath in get_input_files(): for error_message in get_file_errors( pyfilepath, max_expression_complexity=9, ignore_django_orm_queries=True, ): has_errors = True print(error_message) # noqa: T001 return int(has_errors)
def main() -> Optional[int]: forbidden_imports = get_list_param_from_config('setup.cfg', 'project_structure', 'forbidden_imports') if not forbidden_imports: return None errors: List[str] = [] for pyfilepath in get_input_files(): ast_tree: Optional[ast.Module] = get_ast_tree(pyfilepath) if ast_tree is None: continue errors += get_import_errors_in_ast_tree(pyfilepath, ast_tree, forbidden_imports) for error in errors: print(error) # noqa: T001 if errors: return 1
def main() -> Optional[int]: has_errors = False for pyfilepath in get_input_files(): ast_tree_results = get_ast_tree_with_content(pyfilepath) ast_tree, file_content = ast_tree_results if ast_tree is None or file_content is None: continue for assert_node in [ n for n in ast.walk(ast_tree) if isinstance(n, ast.Assert) ]: has_errors = True print( # noqa: T001 '{0}:{1} assert usage detected'.format( pyfilepath, assert_node.lineno, ), ) if has_errors: return 1
def main() -> Optional[int]: has_errors = False for pyfilepath in get_input_files(): ast_tree_results = get_ast_tree_with_content(pyfilepath) ast_tree, file_content = ast_tree_results if ast_tree is None or file_content is None: continue for node in ast.walk(ast_tree): if not is_django_object_type_node(node): continue if are_model_fields_implicitly_exposed(node): print('{0}:{1} "{2}" implicitly exposes all model\'s fields'. format( # noqa: T001 pyfilepath, node.lineno, node.name, # type: ignore )) if has_errors: return 1
def main() -> Optional[int]: exit_zero = True module_validators: List[Callable[[str, str, List[str]], List[str]]] = [ has_only_models_in_models_submodule, all_enums_in_enums_py_module, has_no_submodules_with_blacklisted_suffixes, has_no_empty_py_files, views_py_has_only_class_views, urls_py_has_urlpatterns, no_url_calls, ] errors: List[str] = [] for module_name, module_path, module_files in get_modules_files( get_input_files(dirs_to_exclude=[])): for validator in module_validators: errors += validator(module_name, module_path, module_files) for error in errors: print(error) # noqa: T001 if errors and not exit_zero: return 1
def iterate_api_files() -> typing.Iterator[str]: return (filepath for filepath in get_input_files() if is_api_filepath(filepath) and is_serializer_or_view_filepath(filepath))
def main() -> int: errors = validate(get_input_files()) return 1 if errors else 0
def get_input_models_files( args: typing.List[str] = None, dirs_to_exclude: typing.List[str] = None) -> typing.Iterator[str]: return (filepath for filepath in get_input_files(args, dirs_to_exclude, 'py') if filepath.endswith('/models.py') or '/models/' in filepath)
def main() -> Optional[int]: variable_names_blacklist = { # from https://github.com/wemake-services/wemake-python-styleguide/ 'val', 'vals', 'var', 'vars', 'variable', 'contents', 'handle', 'file', 'objs', 'some', 'do', 'no', 'true', 'false', 'foo', 'bar', 'baz', 'data', 'result', 'results', 'item', 'items', 'value', 'values', 'content', 'obj', 'info', 'handler', } default_max_allowed_complexity = int( get_param_from_config( 'setup.cfg', 'flake8', 'adjustable-default-max-complexity', ) or 8) + 1 per_path_max_complexity = [ (r.split(': ')[0], int(r.split(': ')[1]) + 1) for r in get_list_param_from_config('setup.cfg', 'flake8', 'per-path-max-complexity') ] complexity_penalty = 2 errors = [] for pyfilepath in get_input_files(): ast_tree_results: Tuple[Optional[ast.AST], Optional[str]] = get_ast_tree_with_content( pyfilepath) ast_tree, file_content = ast_tree_results if ast_tree is None or file_content is None: continue file_lines = file_content.split('\n') funcdefs = get_all_funcdefs(ast_tree) for funcdef in funcdefs: vars_in_function = [ v for v in extract_all_variable_names(funcdef) if '# noqa' not in file_lines[v[1].lineno - 1] ] all_vars_in_function = {v[0] for v in vars_in_function} blacklisted_vars_amount = (len( all_vars_in_function.intersection(variable_names_blacklist)) + len([ v for v in all_vars_in_function if len(v) == 1 and v not in ['_'] ])) current_max_complexity = get_max_complexity_for_path( pyfilepath, per_path_max_complexity, default_max_allowed_complexity, ) max_complexity = current_max_complexity - blacklisted_vars_amount * complexity_penalty def_line = file_lines[funcdef.lineno - 1] current_complexity = get_node_mccabe_complexity(funcdef) if current_complexity > max_complexity and '# noqa' not in def_line: errors.append((pyfilepath, funcdef.lineno, funcdef.name, current_complexity, max_complexity), ) if errors: for path, line_no, func_name, comlexity, max_comlexity in errors: print( '{0}:{1} {2} is too complex ({3} > {4})'.format( # noqa: T001 path, line_no, func_name, comlexity, max_comlexity, )) return 1