コード例 #1
0
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
コード例 #4
0
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
コード例 #5
0
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
コード例 #6
0
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
コード例 #7
0
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