Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ $ uvx --from 'vcspull' --prerelease allow vcspull

<!-- Maintainers, insert changes / features for the next release here -->

### Documentation

#### Fix Sphinx autodoc indentation errors (#490)

- Configure `sphinx-autodoc-typehints` to prevent RST parsing conflicts with
Napoleon-processed docstrings by disabling type injection into docstring
bodies (`always_document_param_types`, `typehints_document_rtype`).
- Suppress cosmetic forward reference warnings from TYPE_CHECKING imports.

_Upcoming changes will be written here._

## vcspull v1.48.0 (2025-11-30)
Expand Down
2 changes: 1 addition & 1 deletion docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# API Reference

:::{seealso}
For granular control see {ref}`libvcs <libvcs:index>`'s {ref}`Commands <libvcs:cmd>` and {ref}`Projects <libvcs:projects>`.
For granular control see the [libvcs documentation](https://libvcs.git-pull.com/en/latest/)—especially the sections on [commands](https://libvcs.git-pull.com/en/latest/usage/commands.html) and [projects](https://libvcs.git-pull.com/en/latest/usage/projects.html).
:::

## Internals
Expand Down
13 changes: 11 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,18 @@
"member-order": "bysource",
}

# Automatically extract typehints when specified and place them in
# descriptions of the relevant function/method.
autodoc_typehints = "description"
# Don't show class signature with the class' name.
autodoc_class_signature = "separated"

# sphinx-autodoc-typehints
autodoc_typehints = "description" # show type hints in doc body instead of signature
simplify_optional_unions = True
# Suppress warnings for forward references that can't be resolved
# (types in TYPE_CHECKING blocks used for circular import avoidance)
suppress_warnings = [
"sphinx_autodoc_typehints.forward_reference",
]

# sphinx.ext.napoleon
napoleon_google_docstring = True
Expand Down
8 changes: 2 additions & 6 deletions src/vcspull/_internal/config_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@

import yaml

if t.TYPE_CHECKING:
from typing import Literal, TypeAlias

FormatLiteral = Literal["json", "yaml"]

RawConfigData: TypeAlias = dict[t.Any, t.Any]
FormatLiteral = t.Literal["json", "yaml"]
RawConfigData: t.TypeAlias = dict[t.Any, t.Any]


class ConfigReader:
Expand Down
4 changes: 1 addition & 3 deletions src/vcspull/cli/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import argparse
import copy
import logging
import pathlib
Expand All @@ -23,9 +24,6 @@
workspace_root_label,
)

if t.TYPE_CHECKING:
import argparse

log = logging.getLogger(__name__)


Expand Down
4 changes: 1 addition & 3 deletions src/vcspull/cli/discover.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import argparse
import logging
import os
import pathlib
Expand All @@ -23,9 +24,6 @@
workspace_root_label,
)

if t.TYPE_CHECKING:
import argparse

log = logging.getLogger(__name__)

ConfigScope = t.Literal["system", "user", "project", "external"]
Expand Down
4 changes: 1 addition & 3 deletions src/vcspull/cli/fmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import argparse
import copy
import logging
import pathlib
Expand All @@ -20,9 +21,6 @@
save_config_yaml,
)

if t.TYPE_CHECKING:
import argparse

log = logging.getLogger(__name__)


Expand Down
10 changes: 3 additions & 7 deletions src/vcspull/cli/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,18 @@

from __future__ import annotations

import argparse
import logging
import typing as t
import pathlib

from vcspull._internal.private_path import PrivatePath
from vcspull.config import filter_repos, find_config_files, load_configs
from vcspull.types import ConfigDict

from ._colors import Colors, get_color_mode
from ._output import OutputFormatter, get_output_mode
from ._workspaces import filter_by_workspace

if t.TYPE_CHECKING:
import argparse
import pathlib

from vcspull.types import ConfigDict

log = logging.getLogger(__name__)


Expand Down
7 changes: 2 additions & 5 deletions src/vcspull/cli/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import argparse
import asyncio
import logging
import os
Expand All @@ -15,16 +16,12 @@

from vcspull._internal.private_path import PrivatePath
from vcspull.config import filter_repos, find_config_files, load_configs
from vcspull.types import ConfigDict

from ._colors import Colors, get_color_mode
from ._output import OutputFormatter, get_output_mode
from ._workspaces import filter_by_workspace

if t.TYPE_CHECKING:
import argparse

from vcspull.types import ConfigDict

log = logging.getLogger(__name__)

DEFAULT_STATUS_CONCURRENCY = max(1, min(32, (os.cpu_count() or 4) * 2))
Expand Down
12 changes: 4 additions & 8 deletions src/vcspull/cli/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import argparse
import asyncio
import contextlib
import json
Expand All @@ -20,11 +21,14 @@
from time import perf_counter

from libvcs._internal.shortcuts import create_project
from libvcs._internal.types import VCSLiteral
from libvcs.sync.git import GitSync
from libvcs.url import registry as url_tools

from vcspull import exc
from vcspull._internal.private_path import PrivatePath
from vcspull.config import filter_repos, find_config_files, load_configs
from vcspull.types import ConfigDict

from ._colors import Colors, get_color_mode
from ._output import (
Expand All @@ -40,14 +44,6 @@
from ._workspaces import filter_by_workspace
from .status import check_repo_status

if t.TYPE_CHECKING:
import argparse

from libvcs._internal.types import VCSLiteral
from libvcs.sync.git import GitSync

from vcspull.types import ConfigDict

log = logging.getLogger(__name__)

ProgressCallback = Callable[[str, datetime], None]
Expand Down
19 changes: 8 additions & 11 deletions src/vcspull/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,19 @@
import os
import pathlib
import typing as t
from collections.abc import Callable

from libvcs.sync.git import GitRemote

from vcspull.validator import is_valid_config

from . import exc
from ._internal.config_reader import ConfigReader, DuplicateAwareConfigReader
from .types import ConfigDict, RawConfigDict
from .util import get_config_dir, update_dict

log = logging.getLogger(__name__)

if t.TYPE_CHECKING:
from collections.abc import Callable
from typing import TypeGuard

from .types import ConfigDict, RawConfigDict


def expand_dir(
dir_: pathlib.Path,
Expand All @@ -34,14 +30,15 @@ def expand_dir(

Parameters
----------
_dir : pathlib.Path
dir_ : pathlib.Path
Directory path to expand
cwd : pathlib.Path, optional
current working dir (for deciphering relative _dir paths), defaults to
:py:meth:`os.getcwd()`
Current working dir (used to resolve relative paths). Defaults to
:py:meth:`pathlib.Path.cwd`.

Returns
-------
pathlib.Path :
pathlib.Path
Absolute directory path
"""
dir_ = pathlib.Path(os.path.expandvars(str(dir_))).expanduser()
Expand Down Expand Up @@ -136,7 +133,7 @@ def extract_repos(
**url,
)

def is_valid_config_dict(val: t.Any) -> TypeGuard[ConfigDict]:
def is_valid_config_dict(val: t.Any) -> t.TypeGuard[ConfigDict]:
assert isinstance(val, dict)
return True

Expand Down
7 changes: 2 additions & 5 deletions src/vcspull/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@
import pathlib
import typing as t

if t.TYPE_CHECKING:
from typing import TypeGuard
from vcspull.types import RawConfigDict

from vcspull.types import RawConfigDict


def is_valid_config(config: dict[str, t.Any]) -> TypeGuard[RawConfigDict]:
def is_valid_config(config: dict[str, t.Any]) -> t.TypeGuard[RawConfigDict]:
"""Return true and upcast if vcspull configuration file is valid."""
if not isinstance(config, dict):
return False
Expand Down