예제 #1
0
 def check_process_pipes_are_pure(
     cls,
     pipeline_classdef: ast.ClassDef,
     ast_tree: ast.Module,
     pyfilepath: str,
 ) -> Generator[Tuple[int, int, str], None, None]:
     for pipe_funcdef in get_all_pipes_from(pipeline_classdef):
         if not has_any_decorator(pipe_funcdef,
                                  {cls.PROCESS_DECORATOR_NAME}):
             continue
         set_parents(ast_tree)
         is_pure, errors = is_function_pure(
             pipe_funcdef,
             ast_tree,
             pyfilepath=pyfilepath,
             with_errors=True,
             recursive=True,
         )
         if not is_pure:
             yield (
                 pipe_funcdef.lineno,
                 pipe_funcdef.col_offset,
                 (f'SME004 Pipe {pipe_funcdef.name} is of process type and is not '
                  f'pure ({", ".join(errors)})'),
             )
예제 #2
0
def get_not_pure_internal_calls(
    funcdef_node: AnyFuncdef,
    file_ast_tree: ast.Module,
    pyfilepath: str,
) -> List[str]:
    from mr_proper.public_api import is_function_pure

    not_pure_calls: List[str] = []
    for call_node in get_nodes_from_funcdef_body(funcdef_node, [ast.Call]):
        if not isinstance(call_node.func, ast.Name):
            continue  # recursively check only functions calls, not methods/attrs calls
        if (
            call_node.func.id.lower() == call_node.func.id  # check for only snake_case calls
            and call_node.func.id not in BUILTINS_LIST
        ):
            import_info = get_name_import_path(call_node.func, pyfilepath)
            imported_funcdef_node = get_funcdef_by(import_info) if import_info else None
            if imported_funcdef_node and import_info:
                filepath = cast(str, import_info['file_path'])
                is_call_clean: Optional[bool] = is_function_pure(
                    imported_funcdef_node,
                    file_ast_tree=file_ast_tree,
                    recursive=False,
                    pyfilepath=filepath,
                    with_errors=False,
                )
            else:
                is_call_clean = None
            if is_call_clean is False:
                not_pure_calls.append(call_node.func.id)
    return not_pure_calls
예제 #3
0
def test_ok_for_destructive_assignment():
    funcdef = ast.parse("""
def foo(a):
    b, c = a
    return b * c
    """.strip()).body[0]
    assert is_function_pure(funcdef)
예제 #4
0
def check_purity_of_functions(func_def: AnyFuncdef) -> Tuple[int, int, str]:
    if 'pure' in func_def.name.split('_') and not is_function_pure(func_def):
        return (
            func_def.lineno,
            func_def.col_offset,
            f'CFQ003 Function "{func_def.name}" is not pure.',
        )
예제 #5
0
def test_is_function_pure_fail_case_for_recursive():
    test_file_path = os.path.join(os.path.dirname(__file__),
                                  'test_files/test.py')
    ast_tree = get_ast_tree(test_file_path)
    foo_node = ast_tree.body[0]
    assert not is_function_pure(
        foo_node,
        file_ast_tree=ast_tree,
        pyfilepath=test_file_path,
        recursive=True,
    )
예제 #6
0
def check_file(path_to_file: str, recursive: bool) -> None:
    ast_tree = get_ast_tree(path_to_file)
    if not ast_tree:
        sys.stdout.write('Error parsing ast tree\n')
        return
    sys.stdout.write(f'{path_to_file}:\n')
    for funcdef_node in get_all_funcdefs_from(ast_tree):
        function_name = funcdef_node.name
        is_pure, pureness_errors = is_function_pure(
            funcdef_node,
            ast_tree,
            with_errors=True,
            recursive=recursive,
            pyfilepath=path_to_file,
        )
        if is_pure:
            sys.stdout.write(f'{function_name} is pure!\n')
        else:
            sys.stdout.write(f'{function_name} is not pure because of:\n')
            for error in pureness_errors:
                sys.stdout.write(f'\t{error}\n')
예제 #7
0
def test_is_function_pure_fail_case():
    funcdef = ast.parse("""
def foo(a):
    print(a)
    """.strip()).body[0]
    assert not is_function_pure(funcdef)