diff --git a/CHANGES b/CHANGES index 96f8a681..498f97ea 100644 --- a/CHANGES +++ b/CHANGES @@ -38,6 +38,15 @@ $ uvx --from 'vcspull' --prerelease allow vcspull _Notes on upcoming releases will be added here_ +### Documentation + +#### Class fields describe themselves in the API reference (#567) + +The configuration `TypedDict`s and the sync, status, and search types now +say what each field holds. They previously reached the rendered API +reference as "Alias for field number 0" or as a bare name carrying only its +type. + ### Development #### CI actions updated to current majors diff --git a/src/vcspull/cli/_output.py b/src/vcspull/cli/_output.py index c2add1d2..0567f782 100644 --- a/src/vcspull/cli/_output.py +++ b/src/vcspull/cli/_output.py @@ -29,7 +29,51 @@ class PlanAction(Enum): @dataclass class PlanEntry: - """Represents a single planned action for a repository.""" + """Represents a single planned action for a repository. + + Attributes + ---------- + name : str + Repository name as keyed in the config file. + path : str + Checkout location on disk. Human and JSON output contract the home + directory to ``~``. + workspace_root : str + Workspace root the repository is grouped under; ``""`` when the config + entry carries none, which human output groups as ``(no workspace)``. + action : PlanAction + Action the plan resolved for this repository. + detail : str | None + Short explanation of the action, such as ``"missing"`` or + ``"behind 2"``; ``None`` when no explanation applies. + url : str | None + VCS URL to clone or pull from; ``None`` when the entry carries no URL. + branch : str | None + Branch currently checked out; ``None`` when the checkout is absent or + the branch could not be read. + remote_branch : str | None + Upstream tracking branch, such as ``"origin/main"``; ``None`` when + unknown. + current_rev : str | None + Revision the checkout sits at; ``None`` when unknown. + target_rev : str | None + Revision a sync would move the checkout to; ``None`` when unknown. + ahead : int | None + Commits the local branch holds that the upstream lacks; ``None`` when + the comparison is unavailable, as for a missing or non-git checkout. + behind : int | None + Commits the upstream holds that the local branch lacks; ``None`` when + the comparison is unavailable. + dirty : bool | None + ``True`` when the working tree has uncommitted changes; ``None`` when + cleanliness could not be determined. + error : str | None + Message describing why planning failed for this repository; ``None`` + when planning succeeded. + diagnostics : list[str] + Extra messages carried into the serialised payload; empty when there + are none, and then omitted from the payload. + """ name: str path: str @@ -102,7 +146,26 @@ def to_payload(self) -> dict[str, t.Any]: @dataclass class PlanSummary: - """Aggregate summary for a synchronization plan.""" + """Aggregate summary for a synchronization plan. + + Attributes + ---------- + clone : int + Repositories with no checkout yet, to be cloned. + update : int + Repositories with upstream work to pull. + unchanged : int + Repositories already up to date. + blocked : int + Repositories held back by local state: a dirty working tree, + local-only commits, or divergence from the upstream. + errors : int + Repositories that could not be planned, such as when refreshing + remotes failed. + duration_ms : int | None + Wall-clock time spent building the plan, in milliseconds; ``None`` + when no timing was recorded, and then omitted from the payload. + """ clone: int = 0 update: int = 0 @@ -151,7 +214,26 @@ def to_payload(self) -> dict[str, t.Any]: @dataclass class PlanRenderOptions: - """Rendering options for human plan output.""" + """Rendering options for human plan output. + + Attributes + ---------- + show_unchanged : bool + Keep repositories whose action is ``UNCHANGED`` in the rendered rows + (``--show-unchanged``); they are dropped otherwise. + summary_only : bool + Print the summary line alone and skip per-repository rows + (``--summary-only``). + long : bool + Show the extended block under each row with URL, ahead/behind counts, + and error text (``--long``). + verbosity : int + Repeated ``-v`` count, clamped to 0-2. At 1 or above, rows gain inline + detail extras; at 2 they gain the extended block. + relative_paths : bool + Render paths relative to the workspace root (``--relative-paths``) + instead of contracting the home directory to ``~``. + """ show_unchanged: bool = False summary_only: bool = False @@ -162,7 +244,16 @@ class PlanRenderOptions: @dataclass class PlanResult: - """Container for plan entries and their summary.""" + """Container for plan entries and their summary. + + Attributes + ---------- + entries : list[PlanEntry] + One entry per repository the plan evaluated, in the order evaluation + finished; rendering sorts them by action and name. + summary : PlanSummary + Action counts tallied across ``entries``. + """ entries: list[PlanEntry] summary: PlanSummary diff --git a/src/vcspull/cli/search.py b/src/vcspull/cli/search.py index 8077d6c9..5a95a241 100644 --- a/src/vcspull/cli/search.py +++ b/src/vcspull/cli/search.py @@ -48,7 +48,20 @@ class SearchToken(t.NamedTuple): @dataclass(frozen=True) class SearchPattern: - """Compiled search pattern tied to repository fields.""" + """Compiled search pattern tied to repository fields. + + Attributes + ---------- + fields : tuple[str, ...] + Canonical field names the regex is applied to, carried over from the + token it was compiled from. + raw : str + Pattern text as typed, before ``--fixed-strings`` escaping or + ``--word-regexp`` boundary wrapping. + regex : re.Pattern[str] + Matcher compiled from ``raw``, case-insensitive when ``--ignore-case`` + was given or smart-case resolved that way. + """ fields: tuple[str, ...] raw: str diff --git a/src/vcspull/cli/status.py b/src/vcspull/cli/status.py index 55bf8d32..89e3b7bd 100644 --- a/src/vcspull/cli/status.py +++ b/src/vcspull/cli/status.py @@ -30,7 +30,18 @@ @dataclass class StatusCheckConfig: - """Configuration options for status checking.""" + """Configuration options for status checking. + + Attributes + ---------- + max_concurrent : int + Ceiling on repositories inspected at once (``--max-concurrent``), + bounding the semaphore that guards the async checks. + detailed : bool + Collect the current branch and ahead/behind counts on top of the + existence, VCS, and cleanliness checks (``--detailed``). Each extra + field costs another git invocation per repository. + """ max_concurrent: int detailed: bool diff --git a/src/vcspull/cli/sync.py b/src/vcspull/cli/sync.py index 73ec66ca..00cf774f 100644 --- a/src/vcspull/cli/sync.py +++ b/src/vcspull/cli/sync.py @@ -86,7 +86,18 @@ @dataclass class SyncPlanConfig: - """Configuration options for building sync plans.""" + """Configuration options for building sync plans. + + Attributes + ---------- + fetch : bool + Run ``git fetch --prune`` before reading status (``--fetch``), so + ahead/behind counts reflect current remote refs. Ignored when + ``offline`` is set. + offline : bool + Plan without touching the network (``--offline``). Repositories whose + remote state cannot be compared are planned as updates. + """ fetch: bool offline: bool diff --git a/src/vcspull/types.py b/src/vcspull/types.py index 5b9506ca..210f6feb 100644 --- a/src/vcspull/types.py +++ b/src/vcspull/types.py @@ -257,7 +257,27 @@ class RepoEntryDict(_RepoEntryDictRequired, _RepoEntryDictOptional): class RawConfigDict(t.TypedDict): - """Configuration dictionary without any type marshalling or variable resolution.""" + """Configuration dictionary without any type marshalling or variable resolution. + + Counterpart to :class:`ConfigDict` in the shape a config file supplies: + paths stay as written and shorthand entries are not yet expanded. + + Attributes + ---------- + vcs : VCSLiteral + Version control system backing the repository — ``"git"``, ``"hg"``, + or ``"svn"``. + name : str + Repository name, taken from the key it sits under within its + workspace root. + path : StrPath + Checkout location as written, still a :class:`str` or + :class:`os.PathLike` carrying any ``~`` or environment variable. + url : str + VCS URL in vcspull format, e.g. ``git+git@github.com:user/repo.git``. + remotes : GitSyncRemoteDict + Extra git remotes to keep in sync, keyed by remote name. + """ vcs: VCSLiteral name: str