Beispiel #1
0
def nayvy_list_tested_and_untested_functions(
) -> Optional[Tuple[List[str], List[str]]]:
    """ Vim interface for listing up
    - Already tested function
    - Non-tested function
    """
    filepath = vim.eval('expand("%")')
    if basename(filepath).startswith('test_'):
        error('You are already in test script.')
        return None
    lines = vim.current.buffer[:]
    loader = SyntacticModuleLoader()
    auto_generator = AutoGenerator(loader)
    test_path = auto_generator.touch_test_file(filepath)
    if test_path is None:
        error('Please check if your python project is created correcty')
        return ([], [])

    impl_mod = loader.load_module_from_lines(lines)
    test_mod = loader.load_module_from_path(test_path)
    if impl_mod is None or test_mod is None:
        error('Loading python scripts failed.')
        return ([], [])
    intersection = impl_mod.to_test().intersect(test_mod)
    subtraction = impl_mod.to_test().sub(test_mod)
    return (
        intersection.to_func_list_lines(),
        subtraction.to_func_list_lines(),
    )
Beispiel #2
0
def nayvy_list_tested_and_untested_functions(
) -> Optional[Tuple[List[str], List[str]]]:
    """ Vim interface for listing up
    - Already tested function
    - Non-tested function
    """
    filepath = vim.eval('expand("%")')
    loader = SyntacticModuleLoader()
    impl_test_paths = get_impl_and_test_paths(filepath)
    if impl_test_paths is None:
        error('Please check if your python project is created correcty')
        return ([], [])

    impl_path, test_path = impl_test_paths
    # get lines
    impl_module_lines = get_latest_lines(impl_path)
    test_module_lines = get_latest_lines(test_path)

    # create module objects
    impl_mod = loader.load_module_from_lines(impl_module_lines)
    test_mod = loader.load_module_from_lines(test_module_lines)
    if impl_mod is None or test_mod is None:
        error('Loading python scripts failed.')
        return ([], [])
    intersection = impl_mod.to_test().intersect(test_mod)
    subtraction = impl_mod.to_test().sub(test_mod)
    return (
        intersection.to_func_list_lines(),
        subtraction.to_func_list_lines(),
    )
Beispiel #3
0
 def test_of_filepath(self) -> None:
     given = str(self.sample_project_path /
                 'package/subpackage/sub_main.py')
     actual = ModulePath.of_filepath(
         SyntacticModuleLoader(),
         given,
     )
     assert actual is not None
     assert actual.mod_path == 'package.subpackage.sub_main'
     return
Beispiel #4
0
 def setUp(self) -> None:
     loader = SyntacticModuleLoader()
     self.target = AutoGenerator(loader, ['setup.py', 'pyproject.toml'])
     self.work_dir = f'{dirname(__file__)}/test_workdir'
     Path(self.work_dir).mkdir(parents=True, exist_ok=True)
     self.__generate_files([
         'setup.py',
         'package/a.py',
         'package/sub_package/b.py',
         'package/sub_package/sub_sub_package/c.py',
     ])
     return
Beispiel #5
0
def nayvy_auto_touch_test() -> None:
    """ Vim interface for touch unittest script.
    """
    filepath = vim.eval('expand("%")')
    if basename(filepath).startswith('test_'):
        error('You are already in test script.')
        return
    auto_generator = AutoGenerator(SyntacticModuleLoader())
    test_path = auto_generator.touch_test_file(filepath)
    if test_path is None:
        error('Please check if your python project is created correcty')
        return
    vim.command(f'vs {test_path}')
    return
Beispiel #6
0
    def test___getitem__(self) -> None:
        actual = ProjectImportHelper.of_filepath(
            SyntacticModuleLoader(),
            str(self.sample_project_path / 'package' / 'main.py'))
        assert actual is not None
        # Can access to subpackage's function
        assert actual['sub_top_level_function1'] == SingleImport(
            'sub_top_level_function1',
            'from .subpackage.sub_main import sub_top_level_function1',
            2,
        )

        # Cannot access to function defined in self
        assert actual['top_level_function1'] is None
        return
Beispiel #7
0
    def test___getitem__(self) -> None:

        builder = ProjectImportHelperBuilder(
            str(
                self.sample_project_path /
                'package' /
                'main.py'
            ),
            SyntacticModuleLoader(),
            ImportPathFormat.ALL_RELATIVE,
            ['setup.py', 'pyproject.toml'],
            False,
        )
        actual = builder.build()
        assert actual is not None
        # Can access to subpackage's function
        assert actual['sub_top_level_function1'] == SingleImport(
            name='sub_top_level_function1',
            statement='from .subpackage.sub_main import sub_top_level_function1',
            level=2,
            func=Function(
                name='sub_top_level_function1',
                docstring='Top level function.\nsignature is multilined.\n',
                line_begin=2,
                line_end=11,
                func_decl_type=FuncDeclType.TOP_LEVEL,
                signature_lines=[
                    'def sub_top_level_function1(',
                    '    hoge: int,',
                    '    fuga: str,',
                    ') -> None:',
                    '    """ Top level function.',
                    '',
                    '    signature is multilined.',
                    '    """',
                ],
            ),
            klass=None,
        )

        # Cannot access to function defined in self
        assert actual['top_level_function1'] is None
        return
Beispiel #8
0
def init_import_stmt_map(filepath: str) -> Optional[ImportStatementMap]:
    config = ImportConfig.init()
    if config is None:
        error('Cannot load nayvy config file')
        return None
    project_import_helper = ProjectImportHelper.of_filepath(
        SyntacticModuleLoader(),
        filepath,
    )
    if project_import_helper is None:
        warning(
            'cannot load project. '
            '(check if the current buffer is saved correctly, '
            'or you are working in a Python project)'
        )
        return config
    return IntegratedMap(
        config,
        project_import_helper,
    )
Beispiel #9
0
def init_import_stmt_map(filepath: str) -> Optional[ImportStatementMap]:
    config = ImportConfig.init(CONFIG.import_config_path)
    if config is None:
        error('Cannot load nayvy config file')
        return None
    project_import_helper = ProjectImportHelperBuilder(
        current_filepath=filepath,
        loader=SyntacticModuleLoader(),
        import_path_format=CONFIG.import_path_format,
        pyproject_root_markers=CONFIG.pyproject_root_markers,
        requires_in_pyproject=False,
    ).build()
    if project_import_helper is None:
        warning('cannot load project. '
                '(check if the current buffer is saved correctly, '
                'or you are working in a Python project)')
        return config
    return IntegratedMap(
        config,
        project_import_helper,
    )
Beispiel #10
0
def nayvy_test_generate(func_names: List[str] = []) -> None:
    """ Vim interface for jumping or generating unittest.
    """
    loader = SyntacticModuleLoader()
    auto_generator = AutoGenerator(
        loader,
        CONFIG.pyproject_root_markers,
    )
    filepath = vim.eval('expand("%")')
    if not func_names and is_test_path(filepath):
        # Nothing should be done when already in a test buffer
        # and function names were not provided.
        error('You are already in test script.')
        return
    impl_test_paths = get_impl_and_test_paths(filepath)
    if impl_test_paths is None:
        error('Please check if your python project is created correcty')
        return

    impl_path, test_path = impl_test_paths
    auto_generator.touch_test_file(impl_path)
    impl_module_lines = get_latest_lines(impl_path)
    test_module_lines = get_latest_lines(test_path)

    if func_names == []:
        impl_mod = loader.load_module_from_lines(impl_module_lines)
        if impl_mod is None:
            error('Please check the current buffer is valid')
            return
        # if `func_names` is not given, infer it as nearest function
        func = impl_mod.get_nearest_function(vim.current.window.cursor[0] - 1)
        if func is None:
            error('The cursor is probably outside the function.')
            return
        func_names = [func.name]

    updated_test_module_lines = test_module_lines
    for func_name in func_names:
        may_updated_test_module_lines = auto_generator.get_added_test_lines(
            func_name,
            impl_module_lines,
            updated_test_module_lines,
        )
        if may_updated_test_module_lines:
            updated_test_module_lines = may_updated_test_module_lines

    test_win = VimWin.find_win(test_path)
    # open test script
    if not test_win:
        vim.command(f'vs {test_path}')
    else:
        vim.command('{} tabnext'.format(test_win.tabnr))
        vim.command('{} wincmd w'.format(test_win.winnr))

    if updated_test_module_lines is not None:
        # change lines
        vim.current.buffer[:] = updated_test_module_lines
    else:
        info('Test function already exists')

    # search lines
    row: int
    column: int
    for i, line in enumerate(test_module_lines):
        needle = f'def test_{func_name}'
        if needle in line:
            vim.current.window.cursor = (
                i + 1,
                line.index(needle),
            )
    return
Beispiel #11
0
    def test_add_func(self) -> None:
        loader = SyntacticModuleLoader()

        # --------------------------------------------
        # Test for adding function to already defined class
        # --------------------------------------------
        given = [
            'class TestClass1(unittest.TestCase):',
            '',
            '    def test_method1(self) -> None:',
            '        return',
            '',
            '    def test_method2(self) -> None:',
            '        return',
            '',
            '',
            'class TestClass2(unittest.TestCase):',
            '',
            '    def test_method1(cls) -> None:',
            '        return',
            '',
            '    def test_method2(self) -> None:',
            '        return',
        ]

        react_mod = ReactiveTestModule.of(
            loader,
            given,
        )
        assert react_mod is not None

        react_mod.add_func(
            'TestClass2',
            'added_func',
        )

        actual = react_mod.lines
        # assert that existing lines are unchanged
        assert actual[:len(given)] == given
        # assert added lines
        assert actual[len(given):] == [
            '',
            '    def added_func(self) -> None:',
            '        return',
        ]

        # --------------------------------------------
        # Test for adding function to new class
        # --------------------------------------------
        react_mod = ReactiveTestModule.of(
            loader,
            given,
        )
        assert react_mod is not None

        react_mod.add_func(
            'TopLevelClass3',
            'added_func',
        )
        # assert that existing lines are unchanged
        assert actual[:len(given)] == given
        # assert added lines
        assert react_mod.lines[len(given):] == [
            '',
            '',
            'class TopLevelClass3(unittest.TestCase):',
            '',
            '    def added_func(self) -> None:',
            '        return',
        ]
Beispiel #12
0
def nayvy_test_generate(func_names: List[str] = []) -> None:
    """ Vim interface for jump of generate unittest.
    """
    filepath = vim.eval('expand("%")')
    # check if alredy in test file
    if basename(filepath).startswith('test_'):
        error('You are already in test script.')
        return
    loader = SyntacticModuleLoader()
    auto_generator = AutoGenerator(loader)
    test_path = auto_generator.touch_test_file(filepath)
    if test_path is None:
        error('Please check if your python project is created correcty')
        return

    impl_module_lines = vim.current.buffer[:]
    impl_mod = loader.load_module_from_lines(impl_module_lines)
    if impl_mod is None:
        error('Please check the current buffer is valid')
        return

    if func_names == []:
        func_name = impl_mod.get_function(vim.current.window.cursor[0] - 1)
        if func_name is None:
            warning('The cursor is probably outside the function.')
            vim.command(f'vs {test_path}')
            return
        func_names = [func_name]

    # load test file lines.
    with open(test_path) as f:
        test_module_lines = [line.strip('\n') for line in f.readlines()]

    for func_name in func_names:
        tmp = auto_generator.get_added_test_lines(
            func_name,
            impl_module_lines,
            test_module_lines,
        )
        if tmp is not None:
            test_module_lines = tmp

    # open test in split buffer
    vim.command(f'vs {test_path}')

    if test_module_lines is not None:
        # change lines
        vim.current.buffer[:] = test_module_lines
    else:
        print('Test function already exists')

    # search lines
    row: int
    column: int
    for i, line in enumerate(test_module_lines):
        needle = f'def test_{func_name}'
        if needle in line:
            vim.current.window.cursor = (
                i + 1,
                line.index(needle),
            )
    return
Beispiel #13
0
    def test_load_module_from_path(self) -> None:
        # -------------------------------------
        # Simple file loading
        # -------------------------------------
        module_path = (
            self.sample_project_path /
            'package/main.py'
        )
        loader = SyntacticModuleLoader()
        module = loader.load_module_from_path(str(module_path))

        assert module is not None

        # Assertion of top level functions
        assert (
            module.function_map['top_level_function1'] ==
            Function(
                'top_level_function1',
                1,
                3,
                FuncDeclType.TOP_LEVEL,
            )
        )

        # Assertion of class methods
        assert (
            vars(module.class_map['TopLevelClass1']) ==
            vars(Class(
                'TopLevelClass1',
                5,
                19,
                {
                    'instance_method1': Function(
                        'instance_method1',
                        10,
                        12,
                        FuncDeclType.INSTANCE,
                    ),
                    'class_method1': Function(
                        'class_method1',
                        14,
                        16,
                        FuncDeclType.CLASS,
                    ),
                    'instance_method2': Function(
                        'instance_method2',
                        17,
                        19,
                        FuncDeclType.INSTANCE,
                    ),
                },
            ))
        )

        assert (
            module.class_map['TopLevelClass2'] ==
            Class(
                'TopLevelClass2',
                25,
                39,
                {
                    'instance_method3': Function(
                        'instance_method3',
                        30,
                        32,
                        FuncDeclType.INSTANCE,
                    ),
                    'class_method2': Function(
                        'class_method2',
                        34,
                        36,
                        FuncDeclType.CLASS,
                    ),
                    'instance_method4': Function(
                        'instance_method4',
                        37,
                        39,
                        FuncDeclType.INSTANCE,
                    ),
                },
            )
        )

        # -------------------------------------
        # Complex file loading
        # -------------------------------------
        module_path = (
            self.sample_project_path /
            'package/subpackage/sub_main.py'
        )
        loader = SyntacticModuleLoader()
        module = loader.load_module_from_path(str(module_path))

        assert module is not None

        print(module.to_json())

        # Assertion of top level functions
        assert (
            module.function_map['sub_top_level_function1'] ==
            Function(
                'sub_top_level_function1',
                2,
                11,
                FuncDeclType.TOP_LEVEL,
            )
        )

        # Assertion of class methods
        assert (
            vars(module.class_map['SubTopLevelClass1']) ==
            vars(Class(
                'SubTopLevelClass1',
                13,
                32,
                {
                    'instance_method1': Function(
                        'instance_method1',
                        24,
                        32,
                        FuncDeclType.INSTANCE,
                    ),
                },
            ))
        )
        return
Beispiel #14
0
    def test_load_module_from_path(self) -> None:
        # -------------------------------------
        # Simple file loading
        # -------------------------------------
        module_path = (self.sample_project_path / 'package/main.py')
        loader = SyntacticModuleLoader()
        module = loader.load_module_from_path(str(module_path))

        assert module is not None

        # Assertion of top level functions
        assert (module.function_map['top_level_function1'] == Function(
            'top_level_function1',
            '',
            1,
            3,
            FuncDeclType.TOP_LEVEL,
            [
                'def top_level_function1() -> None:',
            ],
        ))

        # Assertion of class methods
        assert (vars(module.class_map['TopLevelClass1']) == vars(
            Class(
                'TopLevelClass1', 5, 19, {
                    'instance_method1':
                    Function(
                        'instance_method1',
                        '',
                        10,
                        12,
                        FuncDeclType.INSTANCE,
                        [
                            'def instance_method1(self) -> None:',
                        ],
                    ),
                    'class_method1':
                    Function(
                        'class_method1',
                        '',
                        14,
                        16,
                        FuncDeclType.CLASS,
                        [
                            'def class_method1(cls) -> None:',
                        ],
                    ),
                    'instance_method2':
                    Function(
                        'instance_method2',
                        '',
                        17,
                        19,
                        FuncDeclType.INSTANCE,
                        [
                            'def instance_method2(self) -> None:',
                        ],
                    ),
                }, [
                    'class TopLevelClass1:',
                ])))

        assert (module.class_map['TopLevelClass2'] == Class(
            'TopLevelClass2', 25, 39, {
                'instance_method3':
                Function(
                    'instance_method3',
                    '',
                    30,
                    32,
                    FuncDeclType.INSTANCE,
                    [
                        'def instance_method3(self) -> None:',
                    ],
                ),
                'class_method2':
                Function(
                    'class_method2',
                    '',
                    34,
                    36,
                    FuncDeclType.CLASS,
                    [
                        'def class_method2(cls) -> None:',
                    ],
                ),
                'instance_method4':
                Function(
                    'instance_method4',
                    '',
                    37,
                    39,
                    FuncDeclType.INSTANCE,
                    [
                        'def instance_method4(self) -> None:',
                    ],
                ),
            }, [
                'class TopLevelClass2:',
            ]))

        # -------------------------------------
        # Complex file loading
        # -------------------------------------
        module_path = (self.sample_project_path /
                       'package/subpackage/sub_main.py')
        loader = SyntacticModuleLoader()
        module = loader.load_module_from_path(str(module_path))

        assert module is not None

        # Assertion of top level functions
        assert (module.function_map['sub_top_level_function1'] == Function(
            'sub_top_level_function1',
            'Top level function.\nsignature is multilined.\n', 2, 11,
            FuncDeclType.TOP_LEVEL, [
                'def sub_top_level_function1(',
                '    hoge: int,',
                '    fuga: str,',
                ') -> None:',
                '    """ Top level function.',
                '',
                '    signature is multilined.',
                '    """',
            ]))

        # Assertion of class methods
        assert (vars(module.class_map['SubTopLevelClass1']) == vars(
            Class(
                'SubTopLevelClass1', 13, 32, {
                    'instance_method1':
                    Function(
                        'instance_method1',
                        'Instance method.\nsignature is multilined.\n',
                        24,
                        32,
                        FuncDeclType.INSTANCE,
                        [
                            'def instance_method1(',
                            '    self, hoge: int,',
                            ') -> None:',
                            '    """ Instance method.',
                            '',
                            '    signature is multilined.',
                            '    """',
                        ],
                    ),
                }, ['class SubTopLevelClass1:'])))

        # Assertion of class with docstring
        assert (vars(module.class_map['SubTopLevelClass2']) == vars(
            Class(
                'SubTopLevelClass2',
                34,
                41,
                {},
                [
                    'class SubTopLevelClass2:',
                    '    """',
                    '    Multiline docstring top level class.',
                    '',
                    '    This should be captured.',
                    '    """',
                ],
            )))
        return