diff --git a/changelog/392.fix.md b/changelog/392.fix.md new file mode 100644 index 000000000..9338e5881 --- /dev/null +++ b/changelog/392.fix.md @@ -0,0 +1 @@ +handle directory patterns \ No newline at end of file diff --git a/docsig/_core.py b/docsig/_core.py index 433eed666..87eeef758 100644 --- a/docsig/_core.py +++ b/docsig/_core.py @@ -26,20 +26,20 @@ _DEFAULT_EXCLUDES = """\ (?x)^( - |\\.?venv - |\\.git - |\\.hg - |\\.idea - |\\.mypy_cache - |\\.nox - |\\.pytest_cache - |\\.svn - |\\.tox - |\\.vscode - |_?build - |__pycache__ - |dist - |node_modules + |\\.?venv[\\\\/].* + |\\.git[\\\\/].* + |\\.hg[\\\\/].* + |\\.idea[\\\\/].* + |\\.mypy_cache[\\\\/].* + |\\.nox[\\\\/].* + |\\.pytest_cache[\\\\/].* + |\\.svn[\\\\/].* + |\\.tox[\\\\/].* + |\\.vscode[\\\\/].* + |_?build[\\\\/].* + |__pycache__[\\\\/].* + |dist[\\\\/].* + |node_modules[\\\\/].* )$ """ diff --git a/docsig/_files.py b/docsig/_files.py index 3f75e911f..26719889f 100644 --- a/docsig/_files.py +++ b/docsig/_files.py @@ -88,21 +88,24 @@ def __init__( # pylint: disable=too-many-arguments for path in paths: self._populate(path) + for path in list(self): + if str(path) != "." and any( + _re.match(i, str(path)) for i in self._excludes + ): + _vprint( + FILE_INFO.format( + path=path, msg="in exclude list, skipping" + ), + self._verbose, + ) + self.remove(path) + self.sort() def _populate(self, root: _Path) -> None: if not root.exists(): raise FileNotFoundError(root) - if str(root) != "." and any( - _re.match(i, root.name) for i in self._excludes - ): - _vprint( - FILE_INFO.format(path=root, msg="in exclude list, skipping"), - self._verbose, - ) - return - if not self._include_ignored and self._gitignore.match_file(root): _vprint( FILE_INFO.format(path=root, msg="in gitignore, skipping"), diff --git a/tests/exclude_test.py b/tests/exclude_test.py index 96feb2d44..444cd2e27 100644 --- a/tests/exclude_test.py +++ b/tests/exclude_test.py @@ -1460,9 +1460,7 @@ def test_exclude_defaults( f"{Path('CODE_OF_CONDUCT.md')}: Parsing Python code failed", f"{Path('.pylintrc')}: Parsing Python code failed", f"{Path('LICENSE')}: Parsing Python code failed", - f"{Path('.pytest_cache')}: in exclude list, skipping", f"{Path('CHANGELOG.md')}: Parsing Python code failed", - f"{Path('dist')}: in exclude list, skipping", f"{Path('.pre-commit-config.yaml')}: Parsing Python code failed", f"{Path('.coverage')}: Parsing Python code failed", f"{Path('Makefile')}: Parsing Python code failed", @@ -1470,12 +1468,10 @@ def test_exclude_defaults( f"{Path('.pre-commit-hooks.yaml')}: Parsing Python code failed", f"{Path('pyproject.toml')}: Parsing Python code successful", f"{Path('.bumpversion.cfg')}: Parsing Python code failed", - f"{Path('node_modules')}: in exclude list, skipping", f"{Path('tests/misc_test.py')}: Parsing Python code successful", f"{Path('tests/conftest.py')}: Parsing Python code successful", f"{Path('tests/disable_test.py')}: Parsing Python code successful", f"{Path('tests/__init__.py')}: Parsing Python code successful", - f"{Path('tests/__pycache__')}: in exclude list, skipping", f"{Path('tests/TESTS.md')}: Parsing Python code failed", f"{Path('tests/git_test.py')}: Parsing Python code successful", f"{Path('tests/_test.py')}: Parsing Python code successful", @@ -1498,7 +1494,6 @@ def test_exclude_defaults( f"{Path('docsig/__init__.py')}: Parsing Python code successful", f"{Path('docsig/_display.py')}: Parsing Python code successful", f"{Path('docsig/_hooks.py')}: Parsing Python code successful", - f"{Path('docsig/__pycache__')}: in exclude list, skipping", f"{Path('docsig/_message.py')}: Parsing Python code successful", f"{Path('docsig/_core.py')}: Parsing Python code successful", f"{Path('docsig/_decorators.py')}: Parsing Python code successful", @@ -1508,7 +1503,6 @@ def test_exclude_defaults( f"{Path('docsig/__main__.py')}: Parsing Python code successful", f"{Path('docsig/_utils.py')}: Parsing Python code successful", f"{Path('docsig/_directives.py')}: Parsing Python code successful", - f"{Path('.mypy_cache')}: in exclude list, skipping", f"{Path('.gitignore')}: Parsing Python code failed", f"{Path('package-lock.json')}: Parsing Python code failed", f"{Path('package.json')}: Parsing Python code failed", @@ -1520,8 +1514,6 @@ def test_exclude_defaults( f"{Path('coverage.xml')}: Parsing Python code failed", f"{Path('poetry.lock')}: Parsing Python code failed", f"{Path('README.rst')}: Parsing Python code failed", - f"{Path('.git')}: in exclude list, skipping", - f"{Path('.idea')}: in exclude list, skipping", ] assert all(i in std.out for i in expected) @@ -1555,7 +1547,9 @@ def test_exclude_argument( new-ssl "${@}" """ init_file(template) - assert main(".", long.exclude, "file.py", test_flake8=False) == 0 + assert ( + main(".", long.exclude, r"module[\\/]file.py", test_flake8=False) == 0 + ) def test_gitignore( @@ -1738,9 +1732,7 @@ def test_exclude_defaults_and_gitignore( f"{Path('CODE_OF_CONDUCT.md')}: Parsing Python code failed", f"{Path('.pylintrc')}: Parsing Python code failed", f"{Path('LICENSE')}: Parsing Python code failed", - f"{Path('.pytest_cache')}: in exclude list, skipping", f"{Path('CHANGELOG.md')}: Parsing Python code failed", - f"{Path('dist')}: in exclude list, skipping", f"{Path('.pre-commit-config.yaml')}: Parsing Python code failed", f"{Path('.coverage')}: in gitignore, skipping", f"{Path('Makefile')}: Parsing Python code failed", @@ -1748,12 +1740,10 @@ def test_exclude_defaults_and_gitignore( f"{Path('.pre-commit-hooks.yaml')}: Parsing Python code failed", f"{Path('pyproject.toml')}: Parsing Python code successful", f"{Path('.bumpversion.cfg')}: Parsing Python code failed", - f"{Path('node_modules')}: in exclude list, skipping", f"{Path('tests/misc_test.py')}: Parsing Python code successful", f"{Path('tests/conftest.py')}: Parsing Python code successful", f"{Path('tests/disable_test.py')}: Parsing Python code successful", f"{Path('tests/__init__.py')}: Parsing Python code successful", - f"{Path('tests/__pycache__')}: in exclude list, skipping", f"{Path('tests/TESTS.md')}: Parsing Python code failed", f"{Path('tests/git_test.py')}: Parsing Python code successful", f"{Path('tests/_test.py')}: Parsing Python code successful", @@ -1776,7 +1766,6 @@ def test_exclude_defaults_and_gitignore( f"{Path('docsig/__init__.py')}: Parsing Python code successful", f"{Path('docsig/_display.py')}: Parsing Python code successful", f"{Path('docsig/_hooks.py')}: Parsing Python code successful", - f"{Path('docsig/__pycache__')}: in exclude list, skipping", f"{Path('docsig/_message.py')}: Parsing Python code successful", f"{Path('docsig/_core.py')}: Parsing Python code successful", f"{Path('docsig/_decorators.py')}: Parsing Python code successful", @@ -1786,7 +1775,6 @@ def test_exclude_defaults_and_gitignore( f"{Path('docsig/__main__.py')}: Parsing Python code successful", f"{Path('docsig/_utils.py')}: Parsing Python code successful", f"{Path('docsig/_directives.py')}: Parsing Python code successful", - f"{Path('.mypy_cache')}: in exclude list, skipping", f"{Path('.gitignore')}: Parsing Python code failed", f"{Path('package-lock.json')}: Parsing Python code failed", f"{Path('package.json')}: Parsing Python code failed", @@ -1798,8 +1786,6 @@ def test_exclude_defaults_and_gitignore( f"{Path('coverage.xml')}: in gitignore, skipping", f"{Path('poetry.lock')}: Parsing Python code failed", f"{Path('README.rst')}: Parsing Python code failed", - f"{Path('.git')}: in exclude list, skipping", - f"{Path('.idea')}: in exclude list, skipping", ] assert all(i in std.out for i in expected) diff --git a/tests/fix_test.py b/tests/fix_test.py index 0b4e2bdb6..dbf4bb27c 100644 --- a/tests/fix_test.py +++ b/tests/fix_test.py @@ -3,12 +3,16 @@ ================== """ +# pylint: disable=protected-access + import pickle from pathlib import Path import pytest -from . import InitFileFixtureType, MockMainType +import docsig + +from . import FixtureMakeTree, InitFileFixtureType, MockMainType def test_fix_optional_return_statements_with_overload_func_sig502( @@ -74,3 +78,48 @@ def test_no_fail_on_unicode_decode_error_384( pickle.dump(serialize, fout) assert main(pkl, test_flake8=False) == 0 + + +def test_exclude_dirs_392( + monkeypatch: pytest.MonkeyPatch, + main: MockMainType, + make_tree: FixtureMakeTree, +) -> None: + """Test dir regexes are correctly excluded. + + :param monkeypatch: Mock patch environment and attributes. + :param main: Patch package entry point. + :param make_tree: Create directory tree from dict mapping. + """ + pyproject_toml = Path.cwd() / "pyproject.toml" + pyproject_toml.write_text( + r""" +[tool.docsig] +exclude = '''.*src[\\/]design[\\/].*''' +""", + encoding="utf-8", + ) + path_obj = docsig._core._Paths # define to avoid recursion + paths_list = [] + + def _paths(*args, **kwargs) -> docsig._core._Paths: + paths = path_obj(*args, **kwargs) + paths_list.append(paths) + return paths + + monkeypatch.setattr("docsig._core._Paths", _paths) + make_tree( + Path.cwd(), + { + "src": {"design": {"file1.py": []}}, + "ssrc": {"design": {"file2.py": []}}, + "parent": {"src": {"design": {"file3.py": []}}}, + }, + ) + main(".", test_flake8=False) + paths = [ + Path("src") / "design" / "file1.py", + Path("ssrc") / "design" / "file2.py", + Path("parent") / "src" / "design" / "file3.py", + ] + assert not any(i in paths_list[0] for i in paths)