def views_py_has_only_class_views(module_name: str, module_path: str, module_files: List[str]) -> List[str]: views_py_filename = 'views.py' logger_object_name = 'logger' allowed_ast_nodes = { ast.Import, ast.ImportFrom, ast.If, ast.ClassDef, ast.Assign, } conditionals_ast_nodes = logger_ast_nodes_conditional(logger_object_name) errors: List[str] = [] for filepath in module_files: filename = os.path.basename(filepath) if views_py_filename != filename: continue ast_tree = get_ast_tree(filepath) if ast_tree is None: continue functions = get_not_ok_base_nodes_from(ast_tree, allowed_ast_nodes, conditionals_ast_nodes) errors.extend([ f'{filepath}:{func.lineno} Only class views allowed in {views_py_filename}' for func in functions ]) return errors
def validate(filepaths: Iterable[str]) -> List[Error]: errors = [] for models_filepath in filter(is_models_filepath, filepaths): module = get_ast_tree(models_filepath) if not module: continue for assign in iterate_module_classdef_assigns(module): error = check_assign(assign, models_filepath) if error: errors.append(error) print(error) # noqa: T001 return 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 has_only_models_in_models_submodule(module_name: str, module_path: str, module_files: List[str]) -> List[str]: logger_object_name = 'logger' allowed_ast_nodes = { ast.Import, ast.ImportFrom, ast.If, } conditionals_ast_nodes = logger_ast_nodes_conditional(logger_object_name) conditionals_ast_nodes.extend([ ( # определения моделей ast.ClassDef, is_django_model_definition, ), ( # пропуск определений классов по декоратору ast.ClassDef, get_check_decorators_includes( {'pass_check_is_django_model_definition'}), ), ( # определения депрекейтед функций ast.FunctionDef, get_check_decorators_includes({'deprecated'}), ), ]) errors: List[str] = [] for filepath in module_files: if not is_django_model_file(filepath): continue ast_tree = get_ast_tree(filepath) if ast_tree is None: continue for bad_node in get_not_ok_base_nodes_from(ast_tree, allowed_ast_nodes, conditionals_ast_nodes): errors.append( f'{filepath}:{bad_node.lineno} Wrong instruction for models ' f'submodule (models should contains only models)', ) return errors
def all_enums_in_enums_py_module(module_name: str, module_path: str, module_files: List[str]) -> List[str]: allowed_enums_filename = 'enums.py' errors = [] for filepath in module_files: filename = os.path.basename(filepath) if filename == allowed_enums_filename: continue ast_tree = get_ast_tree(filepath) if ast_tree is None: continue for classdef in [ n for n in ast_tree.body if isinstance(n, ast.ClassDef) ]: if is_enum_definition(classdef): errors.append( f'{filepath}:{classdef.lineno} Enums should live in {allowed_enums_filename}' ) return errors
def no_url_calls(module_name: str, module_path: str, module_files: List[str]) -> List[str]: errors: List[str] = [] for filepath in module_files: ast_tree = get_ast_tree(filepath) if ast_tree is None: continue if has_import_of_function_from_package(ast_tree, 'django.conf.urls', 'url'): url_calls = [ ast_node for ast_node in ast.walk(ast_tree) if (isinstance(ast_node, ast.Call) and isinstance( ast_node.func, ast.Name) and ast_node.func.id == 'url') ] for url_call in url_calls: errors.append( f'{filepath}:{url_call.lineno} url() call is deprecated, use path() instead' ) return errors
def urls_py_has_urlpatterns(module_name: str, module_path: str, module_files: List[str]) -> List[str]: urls_py_filename = 'urls.py' target_assignment_name = 'urlpatterns' errors: List[str] = [] for filepath in module_files: filename = os.path.basename(filepath) if urls_py_filename != filename or os.path.relpath( filepath, module_path).startswith('tests/'): continue ast_tree = get_ast_tree(filepath) if ast_tree is None: continue if not get_assignments_to(ast_tree, target_assignment_name): errors.append( f'{filepath} does not contain "{target_assignment_name}" assignment' ) return errors