From 203d6af483a6110a3fd6a3dbaf673c4da595155d Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Thu, 9 Feb 2023 10:44:59 +0100 Subject: [PATCH 1/6] Supporting glob-style operations --- noxfile.py | 21 ++++++++++++++-- src/sphinx_autobuild/build.py | 4 +++- src/sphinx_autobuild/ignore.py | 23 ++++++++++++++---- tests/test_ignore.py | 24 +++++++++++++++++++ tests/test_ignore_glob/do_ignore/bar.txt | 0 tests/test_ignore_glob/do_ignore/foo.txt | 0 .../test_ignore_glob/do_ignore/nested/foo.txt | 0 .../do_not_ignore/1doignore.txt | 0 .../do_not_ignore/1doignore1.txt | 0 .../do_not_ignore/doignore1.txt | 0 tests/test_ignore_glob/do_not_ignore/foo.txt | 0 11 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 tests/test_ignore_glob/do_ignore/bar.txt create mode 100644 tests/test_ignore_glob/do_ignore/foo.txt create mode 100644 tests/test_ignore_glob/do_ignore/nested/foo.txt create mode 100644 tests/test_ignore_glob/do_not_ignore/1doignore.txt create mode 100644 tests/test_ignore_glob/do_not_ignore/1doignore1.txt create mode 100644 tests/test_ignore_glob/do_not_ignore/doignore1.txt create mode 100644 tests/test_ignore_glob/do_not_ignore/foo.txt diff --git a/noxfile.py b/noxfile.py index c6a0ddb..93311e1 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,4 +1,10 @@ -"""Development automation.""" +"""Development automation. Use this to build the documentation and run tests. + +To install IPython for interactive debugging: + + nox -s -- -i + +""" import nox @@ -18,6 +24,10 @@ def _install_this_editable(session, *, extras=None): silent=True, ) + if "-i" in session.posargs: + session.posargs.pop(session.posargs.index("-i")) + session.install("ipython") + @nox.session(reuse_venv=True) def lint(session): @@ -44,6 +54,13 @@ def docs(session): @nox.session(name="docs-live", reuse_venv=True) def docs_live(session): _install_this_editable(session, extras=["docs"]) + cmd = [ + "sphinx-autobuild", + "-b", "html", + "docs/", "build/docs", + "--port", "0", + "--ignore", "docs/tmp/ignored/foo*", + ] session.run( - "sphinx-autobuild", "-b", "html", "docs/", "build/docs", *session.posargs + *cmd, *session.posargs ) diff --git a/src/sphinx_autobuild/build.py b/src/sphinx_autobuild/build.py index b9ea672..6ff2c70 100644 --- a/src/sphinx_autobuild/build.py +++ b/src/sphinx_autobuild/build.py @@ -6,6 +6,8 @@ from colorama import Fore, Style +# Hard-coded options that we know how to pass-through to Sphinx +# ref: https://www.sphinx-doc.org/en/master/man/sphinx-build.html#cmdoption-sphinx-build-M SPHINX_BUILD_OPTIONS = ( ("b", "builder"), ("a", None), @@ -23,7 +25,7 @@ ("q", None), ("Q", None), ("w", "file"), - ("-keep-going", None), + ("keep_going", None), ("W", None), ("T", None), ("P", None), diff --git a/src/sphinx_autobuild/ignore.py b/src/sphinx_autobuild/ignore.py index 7c65939..93d0195 100644 --- a/src/sphinx_autobuild/ignore.py +++ b/src/sphinx_autobuild/ignore.py @@ -1,7 +1,8 @@ """Logic for ignoring paths.""" import fnmatch -import os import re +from glob import glob +from os.path import abspath def get_ignore(regular, regex_based): @@ -11,11 +12,25 @@ def get_ignore(regular, regex_based): def ignore(path): """Determine if path should be ignored.""" - # Any regular pattern matches. + # Return the full path so we make sure we handle relative paths OK + path = abspath(path) + + # Any regular pattern and glob matches for pattern in regular_patterns: - if fnmatch.fnmatch(path, pattern): + # Expand the pattern into a list of files that match a glob + matched_files = [abspath(ii) for ii in glob(pattern, recursive=True)] + + # If this file matches any of the glob matches, we ignore it + if path in matched_files: return True - if path.startswith(pattern + os.sep): + + # If the parent of this path matches any of the glob matches, ignore it + if any(path.startswith(imatch) for imatch in matched_files): + return True + + # If fnmatch matches, then return True (to preserve old behavior) + # This one doesn't depend on the files actually being present on disk. + if fnmatch.fnmatch(path, pattern): return True # Any regular expression matches. diff --git a/tests/test_ignore.py b/tests/test_ignore.py index fffcf90..c3bb3e2 100644 --- a/tests/test_ignore.py +++ b/tests/test_ignore.py @@ -1,4 +1,6 @@ from sphinx_autobuild.ignore import get_ignore +from pathlib import Path +from glob import glob def test_empty(): @@ -72,3 +74,25 @@ def test_multiple_both(): assert ignored("foo/random.txt") assert ignored("foo/module.pyc") assert ignored("bar/__pycache__/file.pyc") + + +def test_glob_expression(): + ignored = get_ignore( + [ + # Glob for folder + "**/do_ignore", + # Glob for files + "**/*doignore*.*", + ], + [], + ) + # Root folder of our glob test files. Assume tests are run from project root. + for ifile in glob("tests/test_ignore_glob/**/*"): + # Convert to be relative to the tests directory since that mimics + # the user's behavior. + if "do_ignore" in ifile or "doignore" in ifile: + print(f"Should ignore: {ifile})") + assert ignored(ifile) + else: + print(f"Should NOT ignore: {ifile})") + assert not ignored(ifile) diff --git a/tests/test_ignore_glob/do_ignore/bar.txt b/tests/test_ignore_glob/do_ignore/bar.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_ignore/foo.txt b/tests/test_ignore_glob/do_ignore/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_ignore/nested/foo.txt b/tests/test_ignore_glob/do_ignore/nested/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_not_ignore/1doignore.txt b/tests/test_ignore_glob/do_not_ignore/1doignore.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_not_ignore/1doignore1.txt b/tests/test_ignore_glob/do_not_ignore/1doignore1.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_not_ignore/doignore1.txt b/tests/test_ignore_glob/do_not_ignore/doignore1.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_not_ignore/foo.txt b/tests/test_ignore_glob/do_not_ignore/foo.txt new file mode 100644 index 0000000..e69de29 From df904cd630842931fd579c1c9b4995521a0a0fb4 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Thu, 9 Feb 2023 10:57:24 +0100 Subject: [PATCH 2/6] Preserve old behavior --- src/sphinx_autobuild/ignore.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/sphinx_autobuild/ignore.py b/src/sphinx_autobuild/ignore.py index 93d0195..779d6fd 100644 --- a/src/sphinx_autobuild/ignore.py +++ b/src/sphinx_autobuild/ignore.py @@ -2,7 +2,7 @@ import fnmatch import re from glob import glob -from os.path import abspath +from os.path import abspath, sep def get_ignore(regular, regex_based): @@ -13,7 +13,7 @@ def get_ignore(regular, regex_based): def ignore(path): """Determine if path should be ignored.""" # Return the full path so we make sure we handle relative paths OK - path = abspath(path) + path_expanded = abspath(path) # Any regular pattern and glob matches for pattern in regular_patterns: @@ -21,17 +21,20 @@ def ignore(path): matched_files = [abspath(ii) for ii in glob(pattern, recursive=True)] # If this file matches any of the glob matches, we ignore it - if path in matched_files: + if path_expanded in matched_files: return True # If the parent of this path matches any of the glob matches, ignore it - if any(path.startswith(imatch) for imatch in matched_files): + if any(path_expanded.startswith(imatch) for imatch in matched_files): return True - # If fnmatch matches, then return True (to preserve old behavior) - # This one doesn't depend on the files actually being present on disk. + # These two checks are for preserving old behavior. + # They might not be necessary but leaving here just in case. + # Neither depends on the files actually being on disk. if fnmatch.fnmatch(path, pattern): return True + if path.strip(sep).startswith(pattern.strip(sep)): + return True # Any regular expression matches. for regex in regex_based_patterns: From efdf2dae5d11d837396b814310843eb6322f9b3c Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Thu, 9 Feb 2023 11:01:01 +0100 Subject: [PATCH 3/6] Pre-commit updates --- .pre-commit-config.yaml | 10 +++++----- noxfile.py | 14 +++++++------- src/sphinx_autobuild/ignore.py | 2 +- tests/test_ignore.py | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 015e726..82bbfa6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/psf/black - rev: 22.10.0 + rev: 23.1.0 hooks: - id: black args: @@ -11,7 +11,7 @@ repos: - --target-version=py311 - repo: https://github.com/PyCQA/isort - rev: 5.10.1 + rev: 5.12.0 hooks: - id: isort files: \.py$ @@ -23,7 +23,7 @@ repos: - id: flake8 - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.4.0 hooks: - id: check-builtin-literals - id: check-added-large-files @@ -36,13 +36,13 @@ repos: - id: trailing-whitespace - repo: https://github.com/PyCQA/pydocstyle.git - rev: '6.1.1' + rev: '6.3.0' hooks: - id: pydocstyle files: src/.*\.py$ - repo: https://github.com/asottile/blacken-docs - rev: v1.12.1 + rev: 1.13.0 hooks: - id: blacken-docs additional_dependencies: [black==22.10.0] diff --git a/noxfile.py b/noxfile.py index 93311e1..1e67271 100644 --- a/noxfile.py +++ b/noxfile.py @@ -56,11 +56,11 @@ def docs_live(session): _install_this_editable(session, extras=["docs"]) cmd = [ "sphinx-autobuild", - "-b", "html", - "docs/", "build/docs", - "--port", "0", - "--ignore", "docs/tmp/ignored/foo*", + "-b", + "html", + "docs/", + "build/docs", + "--port", + "0", ] - session.run( - *cmd, *session.posargs - ) + session.run(*cmd, *session.posargs) diff --git a/src/sphinx_autobuild/ignore.py b/src/sphinx_autobuild/ignore.py index 779d6fd..e82eddb 100644 --- a/src/sphinx_autobuild/ignore.py +++ b/src/sphinx_autobuild/ignore.py @@ -34,7 +34,7 @@ def ignore(path): if fnmatch.fnmatch(path, pattern): return True if path.strip(sep).startswith(pattern.strip(sep)): - return True + return True # Any regular expression matches. for regex in regex_based_patterns: diff --git a/tests/test_ignore.py b/tests/test_ignore.py index c3bb3e2..5ae0043 100644 --- a/tests/test_ignore.py +++ b/tests/test_ignore.py @@ -1,7 +1,7 @@ -from sphinx_autobuild.ignore import get_ignore -from pathlib import Path from glob import glob +from sphinx_autobuild.ignore import get_ignore + def test_empty(): ignored = get_ignore([], []) From b8f81a43b544f61b9d3b8b9dea07fd5fa10e2402 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Thu, 9 Feb 2023 11:04:16 +0100 Subject: [PATCH 4/6] noqa a long comment --- src/sphinx_autobuild/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sphinx_autobuild/build.py b/src/sphinx_autobuild/build.py index 6ff2c70..90e2288 100644 --- a/src/sphinx_autobuild/build.py +++ b/src/sphinx_autobuild/build.py @@ -7,7 +7,7 @@ from colorama import Fore, Style # Hard-coded options that we know how to pass-through to Sphinx -# ref: https://www.sphinx-doc.org/en/master/man/sphinx-build.html#cmdoption-sphinx-build-M +# ref: https://www.sphinx-doc.org/en/master/man/sphinx-build.html#cmdoption-sphinx-build-M # noqa SPHINX_BUILD_OPTIONS = ( ("b", "builder"), ("a", None), From 0fd443ee2266cf8b50ee659d2495ecb1ebb0f23c Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Thu, 9 Feb 2023 02:55:48 -0800 Subject: [PATCH 5/6] Update noxfile.py Co-authored-by: Erik Sundell --- noxfile.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/noxfile.py b/noxfile.py index 1e67271..2290d80 100644 --- a/noxfile.py +++ b/noxfile.py @@ -56,11 +56,9 @@ def docs_live(session): _install_this_editable(session, extras=["docs"]) cmd = [ "sphinx-autobuild", - "-b", - "html", + "-b=html", + "--port=0", "docs/", "build/docs", - "--port", - "0", ] session.run(*cmd, *session.posargs) From d9ba718a08271d618620aea7b7bff4f8cd080576 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Sat, 23 Dec 2023 09:28:24 -0800 Subject: [PATCH 6/6] Update .pre-commit-config.yaml --- .pre-commit-config.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f2e7fe5..27289e3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,9 +10,6 @@ repos: - id: pyupgrade args: [--py38-plus] - - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.10.1 - - repo: https://github.com/PyCQA/isort rev: 5.12.0 hooks: