From adc8f6eef61ba1d91789a323bd36f36ce7bf7595 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:16:33 -0600 Subject: [PATCH 01/12] types(doc): Expose aliases at runtime for autodoc why: sphinx-autodoc-typehints emitted forward reference warnings for aliases only defined under TYPE_CHECKING. what: - provide fallback DataclassInstance, move TypeAlias imports out of TYPE_CHECKING, and import StrPath/TypeGuard at runtime - ensure sync/url/registry modules import shared aliases directly to make type hints resolvable during docs build - tidy _internal types docstring wording to drop glossary term that caused warnings --- src/libvcs/_internal/dataclasses.py | 2 ++ src/libvcs/_internal/shortcuts.py | 9 +++------ src/libvcs/_internal/types.py | 4 ++-- src/libvcs/pytest_plugin.py | 7 +------ src/libvcs/sync/base.py | 4 +--- src/libvcs/sync/git.py | 4 +--- src/libvcs/sync/hg.py | 4 +--- src/libvcs/sync/svn.py | 4 +--- src/libvcs/url/base.py | 8 +++----- src/libvcs/url/registry.py | 11 ++++------- 10 files changed, 19 insertions(+), 38 deletions(-) diff --git a/src/libvcs/_internal/dataclasses.py b/src/libvcs/_internal/dataclasses.py index 19b4a2d5..01526d32 100644 --- a/src/libvcs/_internal/dataclasses.py +++ b/src/libvcs/_internal/dataclasses.py @@ -13,6 +13,8 @@ if t.TYPE_CHECKING: from _typeshed import DataclassInstance +else: + DataclassInstance = object class SkipDefaultFieldsReprMixin: diff --git a/src/libvcs/_internal/shortcuts.py b/src/libvcs/_internal/shortcuts.py index d6699929..07840570 100644 --- a/src/libvcs/_internal/shortcuts.py +++ b/src/libvcs/_internal/shortcuts.py @@ -8,17 +8,14 @@ from __future__ import annotations import typing as t +from typing import TypeGuard from libvcs import GitSync, HgSync, SvnSync, exc +from libvcs._internal.run import ProgressCallbackProtocol +from libvcs._internal.types import StrPath, VCSLiteral from libvcs.exc import InvalidVCS from libvcs.url import registry as url_tools -if t.TYPE_CHECKING: - from typing import TypeGuard - - from libvcs._internal.run import ProgressCallbackProtocol - from libvcs._internal.types import StrPath, VCSLiteral - class VCSNoMatchFoundForUrl(exc.LibVCSException): def __init__(self, url: str, *args: object) -> None: diff --git a/src/libvcs/_internal/types.py b/src/libvcs/_internal/types.py index f8ffb870..8c1ca129 100644 --- a/src/libvcs/_internal/types.py +++ b/src/libvcs/_internal/types.py @@ -1,4 +1,4 @@ -"""Internal :term:`type annotations `. +"""Internal type annotations. Notes ----- @@ -19,7 +19,7 @@ """:class:`os.PathLike` or :class:`str`""" StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes] -""":class:`os.PathLike`, :class:`str` or :term:`bytes-like object`""" +""":class:`os.PathLike`, :class:`str` or bytes-like object""" VCSLiteral = t.Literal["git", "svn", "hg"] diff --git a/src/libvcs/pytest_plugin.py b/src/libvcs/pytest_plugin.py index 3ade539c..7530757b 100644 --- a/src/libvcs/pytest_plugin.py +++ b/src/libvcs/pytest_plugin.py @@ -13,16 +13,11 @@ import pytest from libvcs import exc -from libvcs._internal.run import run +from libvcs._internal.run import _ENV, run from libvcs.sync.git import GitRemote, GitSync from libvcs.sync.hg import HgSync from libvcs.sync.svn import SvnSync -if t.TYPE_CHECKING: - from typing import TypeAlias - - from libvcs._internal.run import _ENV - class MaxUniqueRepoAttemptsExceeded(exc.LibVCSException): """Raised when exceeded threshold of attempts to find a unique repo destination.""" diff --git a/src/libvcs/sync/base.py b/src/libvcs/sync/base.py index 73991822..c026ad5d 100644 --- a/src/libvcs/sync/base.py +++ b/src/libvcs/sync/base.py @@ -9,9 +9,7 @@ from urllib import parse as urlparse from libvcs._internal.run import _CMD, CmdLoggingAdapter, ProgressCallbackProtocol, run - -if t.TYPE_CHECKING: - from libvcs._internal.types import StrPath +from libvcs._internal.types import StrPath logger = logging.getLogger(__name__) diff --git a/src/libvcs/sync/git.py b/src/libvcs/sync/git.py index 3ad33ffe..200cfabf 100644 --- a/src/libvcs/sync/git.py +++ b/src/libvcs/sync/git.py @@ -31,9 +31,7 @@ VCSLocation, convert_pip_url as base_convert_pip_url, ) - -if t.TYPE_CHECKING: - from libvcs._internal.types import StrPath +from libvcs._internal.types import StrPath logger = logging.getLogger(__name__) diff --git a/src/libvcs/sync/hg.py b/src/libvcs/sync/hg.py index 27587bd2..0085fb48 100644 --- a/src/libvcs/sync/hg.py +++ b/src/libvcs/sync/hg.py @@ -15,13 +15,11 @@ import pathlib import typing as t +from libvcs._internal.types import StrPath from libvcs.cmd.hg import Hg from .base import BaseSync -if t.TYPE_CHECKING: - from libvcs._internal.types import StrPath - logger = logging.getLogger(__name__) diff --git a/src/libvcs/sync/svn.py b/src/libvcs/sync/svn.py index f380bce2..12c39371 100644 --- a/src/libvcs/sync/svn.py +++ b/src/libvcs/sync/svn.py @@ -21,13 +21,11 @@ import re import typing as t +from libvcs._internal.types import StrPath from libvcs.cmd.svn import Svn from .base import BaseSync -if t.TYPE_CHECKING: - from libvcs._internal.types import StrPath - logger = logging.getLogger(__name__) diff --git a/src/libvcs/url/base.py b/src/libvcs/url/base.py index 7d4508eb..e3a68c0b 100644 --- a/src/libvcs/url/base.py +++ b/src/libvcs/url/base.py @@ -4,14 +4,12 @@ import dataclasses import typing as t +from _collections_abc import dict_values +from collections.abc import Iterator +from re import Pattern from libvcs._internal.dataclasses import SkipDefaultFieldsReprMixin -if t.TYPE_CHECKING: - from _collections_abc import dict_values - from collections.abc import Iterator - from re import Pattern - class URLProtocol(t.Protocol): """Common interface for VCS URL Parsers.""" diff --git a/src/libvcs/url/registry.py b/src/libvcs/url/registry.py index a9910602..8b0ccae5 100644 --- a/src/libvcs/url/registry.py +++ b/src/libvcs/url/registry.py @@ -3,16 +3,13 @@ from __future__ import annotations import typing as t +from typing import TypeAlias from libvcs._internal.module_loading import import_string +from .base import URLProtocol -if t.TYPE_CHECKING: - from typing import TypeAlias - - from .base import URLProtocol - - ParserLazyMap: TypeAlias = dict[str, type[URLProtocol] | str] - ParserMap: TypeAlias = dict[str, type[URLProtocol]] +ParserLazyMap: TypeAlias = dict[str, type[URLProtocol] | str] +ParserMap: TypeAlias = dict[str, type[URLProtocol]] DEFAULT_PARSERS: ParserLazyMap = { "git": "libvcs.url.git.GitURL", From 6dad237c295cbc2b3a031ab09497d40b19ee9617 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:16:57 -0600 Subject: [PATCH 02/12] docs(url): Drop duplicate autodoc targets why: Sphinx reported duplicate object descriptions for SubprocessCommand fields and URL rule attributes. what: - remove redundant attribute lists that created duplicate targets in subprocess and URL base docs --- src/libvcs/_internal/subprocess.py | 73 ------------------------------ src/libvcs/url/git.py | 5 -- src/libvcs/url/hg.py | 5 -- src/libvcs/url/svn.py | 5 -- 4 files changed, 88 deletions(-) diff --git a/src/libvcs/_internal/subprocess.py b/src/libvcs/_internal/subprocess.py index 5135ecbf..ce998257 100644 --- a/src/libvcs/_internal/subprocess.py +++ b/src/libvcs/_internal/subprocess.py @@ -77,79 +77,6 @@ def __init__(self, output: str, *args: object) -> None: class SubprocessCommand(SkipDefaultFieldsReprMixin): """Wraps a :mod:`subprocess` request. Inspect, mutate, control before invocation. - Attributes - ---------- - args : _CMD - A string, or a sequence of program arguments. - - bufsize : int - supplied as the buffering argument to the open() function when creating the - stdin/stdout/stderr pipe file objects - - executable : Optional[StrOrBytesPath] - A replacement program to execute. - - stdin : _FILE - standard output for executed program - - stdout : - standard output for executed program - - stderr : - standard output for executed program - - close_fds : Controls closing or inheriting of file descriptors. - - shell : If true, the command will be executed through the shell. - - cwd : Sets the current directory before the child is executed. - - env : Defines the environment variables for the new process. - - text : - If ``True``, decode stdin, stdout and stderr using the given encoding (if set) - or the system default otherwise. - - universal_newlines : - Alias of text, provided for backwards compatibility. - - startupinfo : - Windows only - - creationflags : - Windows only - - preexec_fn : - (POSIX only) An object to be called in the child process just before the child - is executed. - - restore_signals : - POSIX only - - start_new_session : - POSIX only - - group : - POSIX only - - extra_groups : - POSIX only - - user : - POSIX only - - umask : - POSIX only - - pass_fds : - POSIX only - - encoding : - Text mode encoding to use for file objects stdin, stdout and stderr. - - errors : - Text mode error handling to use for file objects stdin, stdout and stderr. - Examples -------- >>> cmd = SubprocessCommand("ls") diff --git a/src/libvcs/url/git.py b/src/libvcs/url/git.py index 89a9efea..ac2cb038 100644 --- a/src/libvcs/url/git.py +++ b/src/libvcs/url/git.py @@ -322,11 +322,6 @@ class GitBaseURL( - Compatibility checking: :meth:`GitBaseURL.is_valid()` - URLs compatible with ``git(1)``: :meth:`GitBaseURL.to_url()` - - Attributes - ---------- - rule : str - name of the :class:`~libvcs.url.base.Rule` """ url: str diff --git a/src/libvcs/url/hg.py b/src/libvcs/url/hg.py index 51a96525..d65262bc 100644 --- a/src/libvcs/url/hg.py +++ b/src/libvcs/url/hg.py @@ -155,11 +155,6 @@ class HgBaseURL( ): """Mercurial repository location. Parses URLs on initialization. - Attributes - ---------- - rule : str - name of the :class:`~libvcs.url.base.Rule` - Examples -------- >>> HgBaseURL(url='https://hg.mozilla.org/mozilla-central/') diff --git a/src/libvcs/url/svn.py b/src/libvcs/url/svn.py index f85b7f21..7e1edbed 100644 --- a/src/libvcs/url/svn.py +++ b/src/libvcs/url/svn.py @@ -174,11 +174,6 @@ class SvnBaseURL( - Compatibility checking: :meth:`SvnBaseURL.is_valid()` - URLs compatible with ``svn(1)``: :meth:`SvnBaseURL.to_url()` - - Attributes - ---------- - rule : str - name of the :class:`~libvcs.url.base.Rule` """ url: str From eb2ea5def9bfd999148f23a22bcd6ae38bd12abb Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:17:14 -0600 Subject: [PATCH 03/12] docs(hg): Fix pull docstring link why: Sphinx warned about duplicate explicit target name "hg update" in Hg.pull docstring. what: - reference hg pull manpage instead of update to avoid conflicting target --- src/libvcs/cmd/hg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvcs/cmd/hg.py b/src/libvcs/cmd/hg.py index bae90fc6..4e0f7c89 100644 --- a/src/libvcs/cmd/hg.py +++ b/src/libvcs/cmd/hg.py @@ -308,7 +308,7 @@ def pull( ) -> str: """Update working directory. - Wraps `hg update `_. + Wraps `hg pull `_. Examples -------- From 9f771ca78fb089c8647a5aef98509a2bf5f21e09 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:47:52 -0600 Subject: [PATCH 04/12] types(shortcuts): Use t.TypeGuard namespace import why: project style prefers namespaced typing usage (47188b8ae44459314458100382a21b28b38562d8). what: - drop direct TypeGuard import and annotate helper using t.TypeGuard --- src/libvcs/_internal/shortcuts.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libvcs/_internal/shortcuts.py b/src/libvcs/_internal/shortcuts.py index 07840570..a3e401d3 100644 --- a/src/libvcs/_internal/shortcuts.py +++ b/src/libvcs/_internal/shortcuts.py @@ -8,7 +8,6 @@ from __future__ import annotations import typing as t -from typing import TypeGuard from libvcs import GitSync, HgSync, SvnSync, exc from libvcs._internal.run import ProgressCallbackProtocol @@ -128,7 +127,7 @@ def create_project( assert vcs_matches[0].vcs is not None - def is_vcs(val: t.Any) -> TypeGuard[VCSLiteral]: + def is_vcs(val: t.Any) -> t.TypeGuard[VCSLiteral]: return isinstance(val, str) and val in {"git", "hg", "svn"} if is_vcs(vcs_matches[0].vcs): From cb3517d528f753e38577f269a408dc5a554163cd Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:52:00 -0600 Subject: [PATCH 05/12] types: Prefer namespaced TypeAlias usage why: Style avoids direct imports from typing; stay consistent with commit 47188b8ae44459314458100382a21b28b38562d8. what: - switch runtime aliases to t.TypeAlias across registry, _internal types/run/subprocess, and tests - remove direct TypeAlias imports --- src/libvcs/_internal/run.py | 7 +++---- src/libvcs/_internal/subprocess.py | 13 +++++-------- src/libvcs/_internal/types.py | 7 ++----- src/libvcs/url/registry.py | 5 ++--- tests/url/test_registry.py | 5 ++--- 5 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/libvcs/_internal/run.py b/src/libvcs/_internal/run.py index 71fa99a6..c532ff63 100644 --- a/src/libvcs/_internal/run.py +++ b/src/libvcs/_internal/run.py @@ -37,7 +37,6 @@ def console_to_str(s: bytes) -> str: if t.TYPE_CHECKING: _LoggerAdapter = logging.LoggerAdapter[logging.Logger] - from typing import TypeAlias else: _LoggerAdapter = logging.LoggerAdapter @@ -96,12 +95,12 @@ def __call__(self, output: str, timestamp: datetime.datetime) -> None: if sys.platform == "win32": - _ENV: TypeAlias = Mapping[str, str] + _ENV: t.TypeAlias = Mapping[str, str] else: - _ENV: TypeAlias = Mapping[bytes, StrPath] | Mapping[str, StrPath] + _ENV: t.TypeAlias = Mapping[bytes, StrPath] | Mapping[str, StrPath] _CMD = StrPath | Sequence[StrPath] -_FILE: TypeAlias = int | t.IO[t.Any] | None +_FILE: t.TypeAlias = int | t.IO[t.Any] | None def run( diff --git a/src/libvcs/_internal/subprocess.py b/src/libvcs/_internal/subprocess.py index ce998257..4103cbb1 100644 --- a/src/libvcs/_internal/subprocess.py +++ b/src/libvcs/_internal/subprocess.py @@ -51,9 +51,6 @@ from .dataclasses import SkipDefaultFieldsReprMixin -if t.TYPE_CHECKING: - from typing import TypeAlias - F = t.TypeVar("F", bound=t.Callable[..., t.Any]) @@ -64,13 +61,13 @@ def __init__(self, output: str, *args: object) -> None: if sys.platform == "win32": - _ENV: TypeAlias = Mapping[str, str] + _ENV: t.TypeAlias = Mapping[str, str] else: - _ENV: TypeAlias = Mapping[bytes, StrOrBytesPath] | Mapping[str, StrOrBytesPath] -_FILE: TypeAlias = None | int | t.IO[t.Any] -_TXT: TypeAlias = bytes | str + _ENV: t.TypeAlias = Mapping[bytes, StrOrBytesPath] | Mapping[str, StrOrBytesPath] +_FILE: t.TypeAlias = None | int | t.IO[t.Any] +_TXT: t.TypeAlias = bytes | str #: Command -_CMD: TypeAlias = StrOrBytesPath | Sequence[StrOrBytesPath] +_CMD: t.TypeAlias = StrOrBytesPath | Sequence[StrOrBytesPath] @dataclasses.dataclass(repr=False) diff --git a/src/libvcs/_internal/types.py b/src/libvcs/_internal/types.py index 8c1ca129..bb8909f7 100644 --- a/src/libvcs/_internal/types.py +++ b/src/libvcs/_internal/types.py @@ -12,13 +12,10 @@ import typing as t from os import PathLike -if t.TYPE_CHECKING: - from typing import TypeAlias - -StrPath: TypeAlias = str | PathLike[str] # stable +StrPath: t.TypeAlias = str | PathLike[str] # stable """:class:`os.PathLike` or :class:`str`""" -StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes] +StrOrBytesPath: t.TypeAlias = str | bytes | PathLike[str] | PathLike[bytes] """:class:`os.PathLike`, :class:`str` or bytes-like object""" diff --git a/src/libvcs/url/registry.py b/src/libvcs/url/registry.py index 8b0ccae5..4687446a 100644 --- a/src/libvcs/url/registry.py +++ b/src/libvcs/url/registry.py @@ -3,13 +3,12 @@ from __future__ import annotations import typing as t -from typing import TypeAlias from libvcs._internal.module_loading import import_string from .base import URLProtocol -ParserLazyMap: TypeAlias = dict[str, type[URLProtocol] | str] -ParserMap: TypeAlias = dict[str, type[URLProtocol]] +ParserLazyMap: t.TypeAlias = dict[str, type[URLProtocol] | str] +ParserMap: t.TypeAlias = dict[str, type[URLProtocol]] DEFAULT_PARSERS: ParserLazyMap = { "git": "libvcs.url.git.GitURL", diff --git a/tests/url/test_registry.py b/tests/url/test_registry.py index 0c83d32f..fda8c2a5 100644 --- a/tests/url/test_registry.py +++ b/tests/url/test_registry.py @@ -13,10 +13,9 @@ if t.TYPE_CHECKING: from collections.abc import Callable - from typing import TypeAlias - ParserMatchLazy: TypeAlias = Callable[[str], registry.ParserMatch] - DetectVCSFixtureExpectedMatch: TypeAlias = registry.ParserMatch | ParserMatchLazy + ParserMatchLazy: t.TypeAlias = Callable[[str], registry.ParserMatch] + DetectVCSFixtureExpectedMatch: t.TypeAlias = registry.ParserMatch | ParserMatchLazy class DetectVCSFixture(t.NamedTuple): From 364ee213649b0ad8474d60d3abe3319f15d86164 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 06:59:43 -0600 Subject: [PATCH 06/12] docs(run): Fix inline literal markers why: docutils warned about unmatched interpreted text delimiters in run() docstring. what: - wrap command error and callback examples in double backticks - simplify future change note to avoid backtick imbalance --- src/libvcs/_internal/run.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libvcs/_internal/run.py b/src/libvcs/_internal/run.py index c532ff63..a6c9b351 100644 --- a/src/libvcs/_internal/run.py +++ b/src/libvcs/_internal/run.py @@ -157,12 +157,12 @@ def run( subprocess in real time instead of when the process finishes. check_returncode : bool - Indicate whether a `libvcs.exc.CommandError` should be raised if return code is + Indicate whether a ``libvcs.exc.CommandError`` should be raised if return code is different from 0. callback : ProgressCallbackProtocol callback to return output as a command executes, accepts a function signature - of `(output, timestamp)`. Example usage:: + of ``(output, timestamp)``. Example usage:: def progress_cb(output, timestamp): sys.stdout.write(output) @@ -171,7 +171,7 @@ def progress_cb(output, timestamp): Upcoming changes ---------------- - When minimum python >= 3.10, `pipesize: int = -1` will be added after `umask`. + When minimum python >= 3.10, pipesize: int = -1 will be added after umask. """ proc = subprocess.Popen( args, From ed24bb2dfd92be24f80dbae5d8b0b2a474276832 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 07:00:00 -0600 Subject: [PATCH 07/12] docs(migration): Fix heading levels why: myst header lints flagged non-consecutive levels (H2->H4). what: - promote fixture and commands subsections to H3 --- MIGRATION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MIGRATION b/MIGRATION index 99a841ba..219c8472 100644 --- a/MIGRATION +++ b/MIGRATION @@ -24,11 +24,11 @@ _Notes on the upcoming release will be added here_ -#### pytest fixtures: `git_local_clone` renamed to `example_git_repo` (#468) +### pytest fixtures: `git_local_clone` renamed to `example_git_repo` (#468) - pytest: `git_local_clone` renamed to `example_git_repo` -#### Commands: Listing method renamed (#466) +### Commands: Listing method renamed (#466) - `libvcs.cmd.git.GitCmd._list()` -> `libvcs.cmd.git.Git.ls()` - `libvcs.cmd.svn.Svn._list()` -> `libvcs.cmd.svn.Svn.ls()` From 292254cec0970a5c0216a73c0a22ae5942d30be8 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 07:00:15 -0600 Subject: [PATCH 08/12] docs: Remove broken refs and duplicate module directive why: Sphinx warned about undefined labels and duplicate module objects. what: - replace pytest fixture ref with direct link and drop redundant {module} directive in pytest-plugin - switch vcspull ref to external link and remove unused footnote in url guide --- docs/pytest-plugin.md | 6 +----- docs/url/index.md | 9 +++------ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/docs/pytest-plugin.md b/docs/pytest-plugin.md index 22aeb435..0a69035e 100644 --- a/docs/pytest-plugin.md +++ b/docs/pytest-plugin.md @@ -11,10 +11,6 @@ Looking for more flexibility, correctness, or power? Need different defaults? [C [connect with us]: https://github.com/vcs-python/libvcs/discussions ``` -```{module} libvcs.pytest_plugin - -``` - [pytest]: https://docs.pytest.org/ ## Usage @@ -29,7 +25,7 @@ Pytest will automatically detect the plugin, and its fixtures will be available. ## Fixtures -This pytest plugin works by providing {ref}`pytest fixtures `. The plugin's fixtures ensure that a fresh Git, Subversion, or Mercurial repository is available for each test. It utilizes [session-scoped fixtures] to cache initial repositories, improving performance across tests. +This pytest plugin works by providing [pytest fixtures](https://docs.pytest.org/en/stable/how-to/fixtures.html). The plugin's fixtures ensure that a fresh Git, Subversion, or Mercurial repository is available for each test. It utilizes [session-scoped fixtures] to cache initial repositories, improving performance across tests. [session-scoped fixtures]: https://docs.pytest.org/en/8.3.x/how-to/fixtures.html#fixture-scopes diff --git a/docs/url/index.md b/docs/url/index.md index a5edcbe8..e7fdd291 100644 --- a/docs/url/index.md +++ b/docs/url/index.md @@ -243,8 +243,9 @@ in {mod}`urlparse` (undocumented). From there, `GitURL` can be used downstream directly by other projects. -In our case, `libvcs`s' own {ref}`cmd` and {ref}`projects`, as well as a {ref}`vcspull:index` -configuration, will be able to detect and accept various URL patterns. +In our case, `libvcs`s' own {ref}`cmd` and {ref}`projects`, as well as a +[vcspull configuration](https://vcspull.git-pull.com/), will be able to detect and accept various +URL patterns. ### Matchers: Defaults @@ -255,10 +256,6 @@ When a match occurs, its `defaults` will fill in non-matched groups. When registering new matchers, higher `weight`s are checked first. If it's a valid regex grouping, it will be picked. -[^api-unstable]: Provisional API only - - It's not determined if Location will be mutable or if modifications will return a new object. - ## Explore ```{toctree} From b81336aba28e49624e77e7e26a0d8dbfbc847aed Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 07:00:27 -0600 Subject: [PATCH 09/12] docs(conf): Tolerate offline intersphinx why: avoid noisy intersphinx fetch warnings when inventories are unreachable. what: - add short timeout and suppress intersphinx warnings --- docs/conf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index 19b5dc08..f811176e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -151,6 +151,10 @@ "gp-libs": ("https://gp-libs.git-pull.com/", None), } +# Keep network lookups fast and quiet when inventories are slow or unreachable. +intersphinx_timeout = 1 +suppress_warnings = ["intersphinx", "intersphinx.inventory"] + def linkcode_resolve(domain: str, info: dict[str, str]) -> None | str: """ From 2472a95dee3b722e0979354679de0f6ba3434945 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 07:15:34 -0600 Subject: [PATCH 10/12] style: Ruff autofix post-rebase why: enforce project import/type alias style after rebase. what: - reflow long docstring line - apply sorted imports - switch InitCmdArgs to t.TypeAlias --- src/libvcs/_internal/run.py | 4 ++-- src/libvcs/_internal/subprocess.py | 1 - src/libvcs/pytest_plugin.py | 2 +- src/libvcs/sync/git.py | 2 +- src/libvcs/url/registry.py | 1 + 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libvcs/_internal/run.py b/src/libvcs/_internal/run.py index a6c9b351..8b586ba8 100644 --- a/src/libvcs/_internal/run.py +++ b/src/libvcs/_internal/run.py @@ -157,8 +157,8 @@ def run( subprocess in real time instead of when the process finishes. check_returncode : bool - Indicate whether a ``libvcs.exc.CommandError`` should be raised if return code is - different from 0. + Indicate whether a ``libvcs.exc.CommandError`` should be raised if return + code is different from 0. callback : ProgressCallbackProtocol callback to return output as a command executes, accepts a function signature diff --git a/src/libvcs/_internal/subprocess.py b/src/libvcs/_internal/subprocess.py index 4103cbb1..003de28f 100644 --- a/src/libvcs/_internal/subprocess.py +++ b/src/libvcs/_internal/subprocess.py @@ -51,7 +51,6 @@ from .dataclasses import SkipDefaultFieldsReprMixin - F = t.TypeVar("F", bound=t.Callable[..., t.Any]) diff --git a/src/libvcs/pytest_plugin.py b/src/libvcs/pytest_plugin.py index 7530757b..cbaeeb51 100644 --- a/src/libvcs/pytest_plugin.py +++ b/src/libvcs/pytest_plugin.py @@ -265,7 +265,7 @@ def unique_repo_name(remote_repos_path: pathlib.Path, max_retries: int = 15) -> return remote_repo_name -InitCmdArgs: TypeAlias = list[str] | None +InitCmdArgs: t.TypeAlias = list[str] | None class CreateRepoPostInitFn(t.Protocol): diff --git a/src/libvcs/sync/git.py b/src/libvcs/sync/git.py index 200cfabf..4916c6bf 100644 --- a/src/libvcs/sync/git.py +++ b/src/libvcs/sync/git.py @@ -25,13 +25,13 @@ from urllib import parse as urlparse from libvcs import exc +from libvcs._internal.types import StrPath from libvcs.cmd.git import Git from libvcs.sync.base import ( BaseSync, VCSLocation, convert_pip_url as base_convert_pip_url, ) -from libvcs._internal.types import StrPath logger = logging.getLogger(__name__) diff --git a/src/libvcs/url/registry.py b/src/libvcs/url/registry.py index 4687446a..0438fcc3 100644 --- a/src/libvcs/url/registry.py +++ b/src/libvcs/url/registry.py @@ -5,6 +5,7 @@ import typing as t from libvcs._internal.module_loading import import_string + from .base import URLProtocol ParserLazyMap: t.TypeAlias = dict[str, type[URLProtocol] | str] From a0291ee419b666815347b6a92157819ef0f7440e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 10:23:49 -0600 Subject: [PATCH 11/12] docs(conf) Suppress forward reference warnings from sphinx-autodoc-typehints why: Types in TYPE_CHECKING blocks (used for circular import avoidance) cause sphinx-autodoc-typehints to emit warnings about unresolvable forward references. These warnings are expected and safe to suppress. what: - Add suppress_warnings config for sphinx_autodoc_typehints.forward_reference --- docs/conf.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index f811176e..06892795 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -110,6 +110,8 @@ # sphinx.ext.autodoc autoclass_content = "both" autodoc_member_order = "bysource" +# Don't show class signature with the class' name. +autodoc_class_signature = "separated" toc_object_entries_show_parents = "hide" autodoc_default_options = { "undoc-members": True, @@ -120,7 +122,9 @@ } # sphinx-autodoc-typehints -autodoc_typehints = "description" # show type hints in doc body instead of signature +# Automatically extract typehints when specified and place them in +# descriptions of the relevant function/method. +autodoc_typehints = "description" simplify_optional_unions = True # sphinx.ext.napoleon @@ -153,7 +157,15 @@ # Keep network lookups fast and quiet when inventories are slow or unreachable. intersphinx_timeout = 1 -suppress_warnings = ["intersphinx", "intersphinx.inventory"] + +# sphinx-autodoc-typehints +# Suppress warnings for forward references that can't be resolved +# (types in TYPE_CHECKING blocks used for circular import avoidance) +suppress_warnings = [ + "intersphinx", + "intersphinx.inventory", + "sphinx_autodoc_typehints.forward_reference", +] def linkcode_resolve(domain: str, info: dict[str, str]) -> None | str: From 3fae5fad7f609d80b7d5c9c072aed3941dcfa44e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 6 Dec 2025 07:58:00 -0600 Subject: [PATCH 12/12] docs(CHANGES) Note doc warning fixes why: document recent doc cleanup work without moving upcoming placeholder. what: - add changelog entry under unreleased section for doc warning / reference fixes --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index ef3c08ef..4afa2576 100644 --- a/CHANGES +++ b/CHANGES @@ -20,6 +20,10 @@ $ uv add libvcs --prerelease allow _Upcoming changes will be written here._ +### Documentation (#498) + +Fix doctree warnings and broken references + ## libvcs 0.38.0 (2025-11-30) ### New features