diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 43f3f97..b2e2a39 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -32,3 +32,22 @@ jobs: - name: Run tests run: python -m tox -e py -- --verbose + + docs: + # Test documentation builds. + # This environment mirrors the ReadTheDocs build environment. + name: Docs + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v4 + with: + python-version: "3.12" + + - name: Install tox + run: python -m pip install tox + + - name: Run tests + run: python -m tox -e docs diff --git a/.gitignore b/.gitignore index 8fe10f2..61f7a75 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ MANIFEST # Hidden files. .* +!.readthedocs.yaml !.gitignore diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..40aafd3 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,14 @@ +version: 2 + +build: + os: 'ubuntu-22.04' + tools: + python: '3.12' + +sphinx: + configuration: 'doc/source/conf.py' + fail_on_warning: true + +python: + install: + - requirements: 'doc/requirements.txt' diff --git a/doc/requirements.txt b/doc/requirements.txt new file mode 100644 index 0000000..6fc994d --- /dev/null +++ b/doc/requirements.txt @@ -0,0 +1 @@ +Sphinx==7.2.6 diff --git a/doc/source/api.rst b/doc/source/api.rst index 0fb44b8..c62961b 100644 --- a/doc/source/api.rst +++ b/doc/source/api.rst @@ -1,3 +1,4 @@ +:tocdepth: 2 API === diff --git a/doc/source/conf.py b/doc/source/conf.py index e8c0b53..3e5ef46 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -24,15 +24,15 @@ # -- General configuration ------------------------------------------------ -# If your documentation needs a minimal Sphinx version, state it here. -# -needs_sphinx = '1.2' - # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode'] +# The autodoc extension doesn't understand the `Self` typehint. +# To avoid documentation build errors, autodoc typehints must be disabled. +autodoc_typehints = "none" + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -64,7 +64,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -102,7 +102,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +# html_static_path = ['_static'] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -165,4 +165,4 @@ ] # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} +intersphinx_mapping = {'python': ('https://docs.python.org/3', None)} diff --git a/doc/source/index.rst b/doc/source/index.rst index 8437bec..6649eab 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -9,6 +9,7 @@ Welcome to pathspec's documentation! .. toctree:: :caption: Contents: + :maxdepth: 2 readme api diff --git a/pathspec/gitignore.py b/pathspec/gitignore.py index 81bf303..e5f7d48 100644 --- a/pathspec/gitignore.py +++ b/pathspec/gitignore.py @@ -31,14 +31,14 @@ class GitIgnoreSpec(PathSpec): """ - The :class:`GitIgnoreSpec` class extends :class:`PathSpec` to + The :class:`GitIgnoreSpec` class extends :class:`pathspec.pathspec.PathSpec` to replicate *.gitignore* behavior. """ def __eq__(self, other: object) -> bool: """ - Tests the equality of this gitignore-spec with *other* - (:class:`GitIgnoreSpec`) by comparing their :attr:`~PathSpec.patterns` + Tests the equality of this gitignore-spec with *other* (:class:`GitIgnoreSpec`) + by comparing their :attr:`~pathspec.pattern.Pattern` attributes. A non-:class:`GitIgnoreSpec` will not compare equal. """ if isinstance(other, GitIgnoreSpec): @@ -65,7 +65,8 @@ def from_lines( *pattern_factory* can be :data:`None`, the name of a registered pattern factory (:class:`str`), or a :class:`~collections.abc.Callable` used to compile patterns. The callable must accept an uncompiled - pattern (:class:`str`) and return the compiled pattern (:class:`.Pattern`). + pattern (:class:`str`) and return the compiled pattern + (:class:`pathspec.pattern.Pattern`). Default is :data:`None` for :class:`.GitWildMatchPattern`). Returns the :class:`GitIgnoreSpec` instance. diff --git a/pathspec/pathspec.py b/pathspec/pathspec.py index 93f2f60..9153baa 100644 --- a/pathspec/pathspec.py +++ b/pathspec/pathspec.py @@ -137,7 +137,7 @@ def match_entries( """ Matches the entries to this path-spec. - *entries* (:class:`~collections.abc.Iterable` of :class:`~util.TreeEntry`) + *entries* (:class:`~collections.abc.Iterable` of :class:`~pathspec.util.TreeEntry`) contains the entries to be matched against :attr:`self.patterns `. *separators* (:class:`~collections.abc.Collection` of :class:`str`; or @@ -150,7 +150,7 @@ def match_entries( :data:`False`. Returns the matched entries (:class:`~collections.abc.Iterator` of - :class:`~util.TreeEntry`). + :class:`~pathspec.util.TreeEntry`). """ if not _is_iterable(entries): raise TypeError(f"entries:{entries!r} is not an iterable.") @@ -179,7 +179,7 @@ def match_file( """ Matches the file to this path-spec. - *file* (:class:`str` or :class:`os.PathLike[str]`) is the file path to be + *file* (:class:`str` or :class:`os.PathLike`) is the file path to be matched against :attr:`self.patterns `. *separators* (:class:`~collections.abc.Collection` of :class:`str`) @@ -202,7 +202,7 @@ def match_files( Matches the files to this path-spec. *files* (:class:`~collections.abc.Iterable` of :class:`str` or - :class:`os.PathLike[str]`) contains the file paths to be matched against + :class:`os.PathLike`) contains the file paths to be matched against :attr:`self.patterns `. *separators* (:class:`~collections.abc.Collection` of :class:`str`; or @@ -215,7 +215,7 @@ def match_files( :data:`False`. Returns the matched files (:class:`~collections.abc.Iterator` of - :class:`str` or :class:`os.PathLike[str]`). + :class:`str` or :class:`os.PathLike`). """ if not _is_iterable(files): raise TypeError(f"files:{files!r} is not an iterable.") @@ -243,7 +243,7 @@ def match_tree_entries( Walks the specified root path for all files and matches them to this path-spec. - *root* (:class:`str` or :class:`os.PathLike[str]`) is the root directory to + *root* (:class:`str` or :class:`os.PathLike`) is the root directory to search. *on_error* (:class:`~collections.abc.Callable` or :data:`None`) optionally @@ -277,7 +277,7 @@ def match_tree_files( Walks the specified root path for all files and matches them to this path-spec. - *root* (:class:`str` or :class:`os.PathLike[str]`) is the root directory to + *root* (:class:`str` or :class:`os.PathLike`) is the root directory to search for files. *on_error* (:class:`~collections.abc.Callable` or :data:`None`) optionally diff --git a/pathspec/pattern.py b/pathspec/pattern.py index 5222ec0..8f20e73 100644 --- a/pathspec/pattern.py +++ b/pathspec/pattern.py @@ -51,7 +51,7 @@ def match(self, files: Iterable[str]) -> Iterator[str]: *files* (:class:`~collections.abc.Iterable` of :class:`str`) contains each file relative to the root directory (e.g., - :data:`"relative/path/to/file"`). + ``"relative/path/to/file"``). Returns an :class:`~collections.abc.Iterable` yielding each matched file path (:class:`str`). @@ -160,7 +160,7 @@ def match_file(self, file: str) -> Optional['RegexMatchResult']: *file* (:class:`str`) contains each file relative to the root directory (e.g., "relative/path/to/file"). - Returns the match result (:class:`RegexMatchResult`) if *file* + Returns the match result (:class:`.RegexMatchResult`) if *file* matched; otherwise, :data:`None`. """ if self.include is not None: diff --git a/pathspec/util.py b/pathspec/util.py index 969e3bc..9408f25 100644 --- a/pathspec/util.py +++ b/pathspec/util.py @@ -62,7 +62,7 @@ def append_dir_sep(path: pathlib.Path) -> str: files on the file-system by relying on the presence of a trailing path separator. - *path* (:class:`pathlib.path`) is the path to use. + *path* (:class:`pathlib.Path`) is the path to use. Returns the path (:class:`str`). """ @@ -88,7 +88,7 @@ def detailed_match_files( *files* (:class:`~collections.abc.Iterable` of :class:`str`) contains the normalized file paths to be matched against *patterns*. - *all_matches* (:class:`boot` or :data:`None`) is whether to return all + *all_matches* (:class:`bool` or :data:`None`) is whether to return all matches patterns (:data:`True`), or only the last matched pattern (:data:`False`). Default is :data:`None` for :data:`False`. @@ -154,7 +154,7 @@ def iter_tree_entries( """ Walks the specified directory for all files and directories. - *root* (:class:`str` or :class:`os.PathLike[str]`) is the root directory to + *root* (:class:`str` or :class:`os.PathLike`) is the root directory to search. *on_error* (:class:`~collections.abc.Callable` or :data:`None`) @@ -270,7 +270,7 @@ def iter_tree_files( """ Walks the specified directory for all files. - *root* (:class:`str` or :class:`os.PathLike[str]`) is the root directory to + *root* (:class:`str` or :class:`os.PathLike`) is the root directory to search for files. *on_error* (:class:`~collections.abc.Callable` or :data:`None`) @@ -376,16 +376,16 @@ def normalize_file( ) -> str: """ Normalizes the file path to use the POSIX path separator (i.e., - :data:`'/'`), and make the paths relative (remove leading :data:`'/'`). + ``"/"``), and make the paths relative (remove leading ``"/"``). - *file* (:class:`str` or :class:`os.PathLike[str]`) is the file path. + *file* (:class:`str` or :class:`os.PathLike`) is the file path. *separators* (:class:`~collections.abc.Collection` of :class:`str`; or - :data:`None`) optionally contains the path separators to normalize. - This does not need to include the POSIX path separator (:data:`'/'`), - but including it will not affect the results. Default is :data:`None` - for :data:`NORMALIZE_PATH_SEPS`. To prevent normalization, pass an - empty container (e.g., an empty tuple :data:`()`). + ``None``) optionally contains the path separators to normalize. + This does not need to include the POSIX path separator (``"/"``), + but including it will not affect the results. Default is ``None`` + for ``NORMALIZE_PATH_SEPS``. To prevent normalization, pass an + empty container (e.g., an empty tuple ``()``). Returns the normalized file path (:class:`str`). """ @@ -421,7 +421,7 @@ def normalize_files( Normalizes the file paths to use the POSIX path separator. *files* (:class:`~collections.abc.Iterable` of :class:`str` or - :class:`os.PathLike[str]`) contains the file paths to be normalized. + :class:`os.PathLike`) contains the file paths to be normalized. *separators* (:class:`~collections.abc.Collection` of :class:`str`; or :data:`None`) optionally contains the path separators to normalize. @@ -429,7 +429,7 @@ def normalize_files( Returns a :class:`dict` mapping each normalized file path (:class:`str`) to the original file paths (:class:`list` of :class:`str` or - :class:`os.PathLike[str]`). + :class:`os.PathLike`). """ warnings.warn(( "util.normalize_files() is deprecated. Use util.normalize_file() " diff --git a/tox.ini b/tox.ini index 89f20bd..7d7a17c 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,14 @@ [tox] -envlist = py38, py39, py310, py311, py312, pypy3 +envlist = + py{38, 39, 310, 311, 312} + pypy3 + docs isolated_build = True [testenv] commands = python -m unittest {posargs} + +[testenv:docs] +base_path = py312 +deps = -rdoc/requirements.txt +commands = sphinx-build -aWEnqb html doc/source doc/build