Skip to content

Commit e83d007

Browse files
authored
📝 docs(api): add :param: descriptions to all public APIs (#32)
1 parent 20ba4bb commit e83d007

File tree

4 files changed

+113
-16
lines changed

4 files changed

+113
-16
lines changed

src/python_discovery/_cache.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,11 @@ def locked(self) -> Generator[None]:
113113

114114

115115
class DiskCache:
116-
"""File-system based Python interpreter info cache (``<root>/py_info/4/<sha256>.json``)."""
116+
"""
117+
File-system based Python interpreter info cache (``<root>/py_info/4/<sha256>.json``).
118+
119+
:param root: root directory for the on-disk cache.
120+
"""
117121

118122
def __init__(self, root: Path) -> None:
119123
self._root = root

src/python_discovery/_py_info.py

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,11 @@ def _try_posix_fallback_executable(self, base_executable: str) -> str | None:
245245
return None # in this case we just can't tell easily without poking around FS and calling them, bail
246246

247247
def install_path(self, key: str) -> str:
248-
"""Return the relative installation path for a given installation scheme *key*."""
248+
"""
249+
Return the relative installation path for a given installation scheme *key*.
250+
251+
:param key: sysconfig installation scheme key (e.g. ``"scripts"``, ``"purelib"``).
252+
"""
249253
result = self.distutils_install.get(key)
250254
if result is None: # pragma: >=3.11 cover # distutils is empty when "venv" scheme is available
251255
# set prefixes to empty => result is relative from cwd
@@ -308,7 +312,13 @@ def is_venv(self) -> bool:
308312
return self.base_prefix is not None
309313

310314
def sysconfig_path(self, key: str, config_var: dict[str, str] | None = None, sep: str = os.sep) -> str:
311-
"""Return the sysconfig install path for a scheme *key*, optionally substituting config variables."""
315+
"""
316+
Return the sysconfig install path for a scheme *key*, optionally substituting config variables.
317+
318+
:param key: sysconfig path key (e.g. ``"purelib"``, ``"include"``).
319+
:param config_var: replacement mapping for sysconfig variables; when ``None`` uses the interpreter's own values.
320+
:param sep: path separator to use in the result.
321+
"""
312322
pattern = self.sysconfig_paths.get(key)
313323
if pattern is None:
314324
return ""
@@ -406,14 +416,23 @@ def spec(self) -> str:
406416

407417
@classmethod
408418
def clear_cache(cls, cache: PyInfoCache) -> None:
409-
"""Clear all cached interpreter information from *cache*."""
419+
"""
420+
Clear all cached interpreter information from *cache*.
421+
422+
:param cache: the cache store to clear.
423+
"""
410424
from ._cached_py_info import clear # noqa: PLC0415
411425

412426
clear(cache)
413427
cls._cache_exe_discovery.clear()
414428

415429
def satisfies(self, spec: PythonSpec, *, impl_must_match: bool) -> bool: # noqa: PLR0911
416-
"""Check if a given specification can be satisfied by this python interpreter instance."""
430+
"""
431+
Check if a given specification can be satisfied by this python interpreter instance.
432+
433+
:param spec: the specification to check against.
434+
:param impl_must_match: when ``True``, the implementation name must match exactly.
435+
"""
417436
if spec.path and not self._satisfies_path(spec):
418437
return False
419438
if impl_must_match and not self._satisfies_implementation(spec):
@@ -462,7 +481,11 @@ def _satisfies_version_specifier(self, spec: PythonSpec) -> bool:
462481

463482
@classmethod
464483
def current(cls, cache: PyInfoCache | None = None) -> PythonInfo:
465-
"""Locate the current host interpreter information."""
484+
"""
485+
Locate the current host interpreter information.
486+
487+
:param cache: interpreter metadata cache; when ``None`` results are not cached.
488+
"""
466489
if cls._current is None:
467490
result = cls.from_exe(sys.executable, cache, raise_on_error=True, resolve_to_host=False)
468491
if result is None:
@@ -473,7 +496,11 @@ def current(cls, cache: PyInfoCache | None = None) -> PythonInfo:
473496

474497
@classmethod
475498
def current_system(cls, cache: PyInfoCache | None = None) -> PythonInfo:
476-
"""Locate the current system interpreter information, resolving through any virtualenv layers."""
499+
"""
500+
Locate the current system interpreter information, resolving through any virtualenv layers.
501+
502+
:param cache: interpreter metadata cache; when ``None`` results are not cached.
503+
"""
477504
if cls._current_system is None:
478505
result = cls.from_exe(sys.executable, cache, raise_on_error=True, resolve_to_host=True)
479506
if result is None:
@@ -504,7 +531,16 @@ def from_exe( # noqa: PLR0913
504531
resolve_to_host: bool = True,
505532
env: Mapping[str, str] | None = None,
506533
) -> PythonInfo | None:
507-
"""Get the python information for a given executable path."""
534+
"""
535+
Get the python information for a given executable path.
536+
537+
:param exe: path to the Python executable.
538+
:param cache: interpreter metadata cache; when ``None`` results are not cached.
539+
:param raise_on_error: raise on failure instead of returning ``None``.
540+
:param ignore_cache: bypass the cache and re-query the interpreter.
541+
:param resolve_to_host: resolve through virtualenv layers to the system interpreter.
542+
:param env: environment mapping; defaults to :data:`os.environ`.
543+
"""
508544
from ._cached_py_info import from_exe # noqa: PLC0415
509545

510546
env = os.environ if env is None else env
@@ -583,7 +619,14 @@ def discover_exe(
583619
exact: bool = True,
584620
env: Mapping[str, str] | None = None,
585621
) -> PythonInfo:
586-
"""Discover a matching Python executable under a given *prefix* directory."""
622+
"""
623+
Discover a matching Python executable under a given *prefix* directory.
624+
625+
:param cache: interpreter metadata cache.
626+
:param prefix: directory prefix to search under.
627+
:param exact: when ``True``, require an exact version match.
628+
:param env: environment mapping; defaults to :data:`os.environ`.
629+
"""
587630
key = prefix, exact
588631
if key in self._cache_exe_discovery and prefix:
589632
_LOGGER.debug("discover exe from cache %s - exact %s: %r", prefix, exact, self._cache_exe_discovery[key])

src/python_discovery/_py_spec.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,20 @@ def _parse_specifier(string_spec: str) -> PythonSpec | None:
9999

100100

101101
class PythonSpec:
102-
"""Contains specification about a Python Interpreter."""
102+
"""
103+
Contains specification about a Python Interpreter.
104+
105+
:param str_spec: the raw specification string as provided by the caller.
106+
:param implementation: interpreter implementation name (e.g. ``"cpython"``, ``"pypy"``), or ``None`` for any.
107+
:param major: required major version, or ``None`` for any.
108+
:param minor: required minor version, or ``None`` for any.
109+
:param micro: required micro (patch) version, or ``None`` for any.
110+
:param architecture: required pointer-size bitness (``32`` or ``64``), or ``None`` for any.
111+
:param path: filesystem path to a specific interpreter, or ``None``.
112+
:param free_threaded: whether a free-threaded build is required, or ``None`` for any.
113+
:param machine: required ISA (e.g. ``"arm64"``), or ``None`` for any.
114+
:param version_specifier: PEP 440 version constraints, or ``None``.
115+
"""
103116

104117
def __init__( # noqa: PLR0913, PLR0917
105118
self,
@@ -128,7 +141,12 @@ def __init__( # noqa: PLR0913, PLR0917
128141

129142
@classmethod
130143
def from_string_spec(cls, string_spec: str) -> PythonSpec:
131-
"""Parse a string specification into a PythonSpec."""
144+
"""
145+
Parse a string specification into a :class:`PythonSpec`.
146+
147+
:param string_spec: an interpreter spec — an absolute path, a version string, an implementation prefix,
148+
or a PEP 440 specifier.
149+
"""
132150
if pathlib.Path(string_spec).is_absolute():
133151
return cls(string_spec, None, None, None, None, None, string_spec)
134152
if result := _parse_spec_pattern(string_spec):
@@ -138,7 +156,11 @@ def from_string_spec(cls, string_spec: str) -> PythonSpec:
138156
return cls(string_spec, None, None, None, None, None, string_spec)
139157

140158
def generate_re(self, *, windows: bool) -> re.Pattern:
141-
"""Generate a regular expression for matching against a filename."""
159+
"""
160+
Generate a regular expression for matching interpreter filenames.
161+
162+
:param windows: if ``True``, require a ``.exe`` suffix.
163+
"""
142164
version = r"{}(\.{}(\.{})?)?".format(
143165
*(r"\d+" if v is None else v for v in (self.major, self.minor, self.micro)),
144166
)
@@ -189,7 +211,11 @@ def _get_required_precision(item: SimpleSpecifier) -> int | None:
189211
return None
190212

191213
def satisfies(self, spec: PythonSpec) -> bool: # noqa: PLR0911
192-
"""Check if this spec is compatible with the given *spec* (e.g. PEP-514 on Windows)."""
214+
"""
215+
Check if this spec is compatible with the given *spec* (e.g. PEP-514 on Windows).
216+
217+
:param spec: the requirement to check against.
218+
"""
193219
if spec.is_abs and self.is_abs and self.path != spec.path:
194220
return False
195221
if (

src/python_discovery/_specifier.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,17 @@
4040

4141
@dataclass(**_DC_KW)
4242
class SimpleVersion:
43-
"""Simple PEP 440-like version parser using only standard library."""
43+
"""
44+
Simple PEP 440-like version parser using only standard library.
45+
46+
:param version_str: the original version string.
47+
:param major: major version number.
48+
:param minor: minor version number.
49+
:param micro: micro (patch) version number.
50+
:param pre_type: pre-release label (``"a"``, ``"b"``, or ``"rc"``), or ``None``.
51+
:param pre_num: pre-release sequence number, or ``None``.
52+
:param release: the ``(major, minor, micro)`` tuple.
53+
"""
4454

4555
version_str: str
4656
major: int
@@ -117,7 +127,16 @@ def __repr__(self) -> str:
117127

118128
@dataclass(**_DC_KW)
119129
class SimpleSpecifier:
120-
"""Simple PEP 440-like version specifier using only standard library."""
130+
"""
131+
Simple PEP 440-like version specifier using only standard library.
132+
133+
:param spec_str: the original specifier string (e.g. ``>=3.10``).
134+
:param operator: the comparison operator (``==``, ``>=``, ``<``, etc.).
135+
:param version_str: the version portion of the specifier, without the operator.
136+
:param is_wildcard: ``True`` if the specifier uses a wildcard suffix (``.*``).
137+
:param wildcard_precision: number of version components before the wildcard, or ``None``.
138+
:param version: the parsed version, or ``None`` if parsing failed.
139+
"""
121140

122141
spec_str: str
123142
operator: str
@@ -230,7 +249,12 @@ def __repr__(self) -> str:
230249

231250
@dataclass(**_DC_KW)
232251
class SimpleSpecifierSet:
233-
"""Simple PEP 440-like specifier set using only standard library."""
252+
"""
253+
Simple PEP 440-like specifier set using only standard library.
254+
255+
:param specifiers_str: the original comma-separated specifier string.
256+
:param specifiers: the parsed individual specifiers.
257+
"""
234258

235259
specifiers_str: str
236260
specifiers: tuple[SimpleSpecifier, ...]

0 commit comments

Comments
 (0)