docs: fix autorefs by using fully qualified path

This commit is contained in:
2026-04-11 23:09:33 -04:00
parent fe1b5d88da
commit db3326aace
4 changed files with 77 additions and 68 deletions
+31 -22
View File
@@ -1,36 +1,45 @@
"""Generate the code reference pages."""
"""Generate code reference pages for mkdocstrings.
This script is executed by the mkdocs-gen-files plugin during the MkDocs build
process. It walks the source package, creates a corresponding Markdown stub for
each public module, and builds a nav.yml file so that the API reference section
is generated automatically.
"""
import os
from pathlib import Path
import mkdocs_gen_files
import yaml
SRC_DIR = "pcdigitizer"
WRITE_DIR = "api"
SRC_DIR = Path("pcdigitizer")
DOC_DIR = Path("api")
SKIP_MODULES = {"__main__", "__init__"}
SKIP_PREFIXES = ("_",)
for path in sorted(Path(SRC_DIR).rglob("*.py")): #
module_path = path.relative_to(SRC_DIR).with_suffix("") #
nav_items: list[dict[str, str] | dict[str, list]] = []
doc_path = path.relative_to(SRC_DIR).with_suffix(".md") #
for path in sorted(SRC_DIR.rglob("*.py")):
module_path = path.relative_to(SRC_DIR).with_suffix("")
doc_path = path.relative_to(SRC_DIR).with_suffix(".md")
full_doc_path = DOC_DIR / doc_path
if not os.path.exists(Path(WRITE_DIR)):
os.mkdir(Path(WRITE_DIR))
parts = tuple(module_path.parts)
full_doc_path = Path(WRITE_DIR, doc_path) #
parts = list(module_path.parts)
if parts[-1] == "__init__": #
parts = parts[:-1]
elif parts[-1] == "__main__":
if not parts:
continue
if parts[-1] in SKIP_MODULES:
continue
if any(part.startswith(prefix) for part in parts for prefix in SKIP_PREFIXES):
continue
if len(parts) == 0:
continue
qualified_name = ".".join((SRC_DIR.name, *parts))
with mkdocs_gen_files.open(full_doc_path, "w") as fd: #
identifier = ".".join(parts) #
nav_items.append({qualified_name: doc_path.as_posix()})
print("::: " + identifier, file=fd) #
with mkdocs_gen_files.open(full_doc_path, "w") as fd:
fd.write(f"::: {qualified_name}\n")
mkdocs_gen_files.set_edit_path(full_doc_path, path) #
mkdocs_gen_files.set_edit_path(full_doc_path, path)
with mkdocs_gen_files.open(DOC_DIR / "nav.yml", "w") as nav_fd:
yaml.dump(nav_items, nav_fd, default_flow_style=False, sort_keys=False)
+23 -23
View File
@@ -73,16 +73,16 @@ class FlatPKaRecord(TypedDict):
"""
pka_label: str | None
"""See [`ParsedPKa`][data.dissociation_constant.ParsedPKa.pka_label]."""
"""See [`ParsedPKa`][pcdigitizer.data.dissociation_constant.ParsedPKa.pka_label]."""
pka_value: float
"""See [`ParsedPKa`][data.dissociation_constant.ParsedPKa.pka_value]."""
"""See [`ParsedPKa`][pcdigitizer.data.dissociation_constant.ParsedPKa.pka_value]."""
temperature_C: float | None
"""See [`ParsedPKa`][data.dissociation_constant.ParsedPKa.temperature_C]."""
"""See [`ParsedPKa`][pcdigitizer.data.dissociation_constant.ParsedPKa.temperature_C]."""
comment: str | None
"""See [`ParsedPKa`][data.dissociation_constant.ParsedPKa.comment]."""
"""See [`ParsedPKa`][pcdigitizer.data.dissociation_constant.ParsedPKa.comment]."""
_OUTPUT_SCHEMA: dict[str, type[pl.DataType]] = {
@@ -101,27 +101,27 @@ class DissociationConstantData(AnnotationProcessor):
"""Parse and assemble PubChem dissociation constant annotation data.
All methods are static or class methods. The primary public interface is
[`from_page`][data.dissociation_constant.DissociationConstantData.from_page],
[`from_page`][pcdigitizer.data.dissociation_constant.DissociationConstantData.from_page],
which converts a raw list of PubChem annotation
entries into a tidy polars DataFrame.
The parsing pipeline for free-text pKa strings is the following.
1. [`parse_value`][data.dissociation_constant.DissociationConstantData.parse_value]
1. [`parse_value`][pcdigitizer.data.dissociation_constant.DissociationConstantData.parse_value]
is the top-level dispatcher. It first checks for
the "pKa values are X, Y, and Z" sentence form via
[`_parse_multi_value_sentence`][data.dissociation_constant.DissociationConstantData._parse_multi_value_sentence].
[`_parse_multi_value_sentence`][pcdigitizer.data.dissociation_constant.DissociationConstantData._parse_multi_value_sentence].
If that does not match it splits the input on semicolons and delegates each
segment to
[`_parse_part`][data.dissociation_constant.DissociationConstantData._parse_part].
[`_parse_part`][pcdigitizer.data.dissociation_constant.DissociationConstantData._parse_part].
2. [`_parse_part`][data.dissociation_constant.DissociationConstantData._parse_part]
2. [`_parse_part`][pcdigitizer.data.dissociation_constant.DissociationConstantData._parse_part]
tries each compiled pattern in
[`_PATTERNS`][data.dissociation_constant.DissociationConstantData._PATTERNS]
[`_PATTERNS`][pcdigitizer.data.dissociation_constant.DissociationConstantData._PATTERNS]
in priority order via
[`_try_patterns`][data.dissociation_constant.DissociationConstantData._try_patterns],
[`_try_patterns`][pcdigitizer.data.dissociation_constant.DissociationConstantData._try_patterns],
returning the first successful
[`ParsedPKa`][data.dissociation_constant.ParsedPKa] or `None`.
[`ParsedPKa`][pcdigitizer.data.dissociation_constant.ParsedPKa] or `None`.
3. Patterns are compiled once at class definition time and reused across all calls.
@@ -197,7 +197,7 @@ class DissociationConstantData(AnnotationProcessor):
Only used when a label group is present from one of the above patterns;
this pattern has no label group intentionally, so bare numbers without
any pK context are always rejected (see
[`_parse_part`][data.dissociation_constant.DissociationConstantData._parse_part]
[`_parse_part`][pcdigitizer.data.dissociation_constant.DissociationConstantData._parse_part]
for the label guard).
"""
@@ -226,7 +226,7 @@ class DissociationConstantData(AnnotationProcessor):
line: The raw input string to test.
Returns:
A list of [`ParsedPKa`][data.dissociation_constant.ParsedPKa] records,
A list of [`ParsedPKa`][pcdigitizer.data.dissociation_constant.ParsedPKa] records,
one per numeric value found in the sentence, or `None` if this
sentence form is not present in `line`.
"""
@@ -262,7 +262,7 @@ class DissociationConstantData(AnnotationProcessor):
semicolons).
Returns:
A [`ParsedPKa`][data.dissociation_constant.ParsedPKa] record if a pattern
A [`ParsedPKa`][pcdigitizer.data.dissociation_constant.ParsedPKa] record if a pattern
matches and a label is present, or `None` if no pattern yields
a valid match.
"""
@@ -302,20 +302,20 @@ class DissociationConstantData(AnnotationProcessor):
"""Parse a single semicolon-split segment of a pKa string.
Delegates to
[`_try_patterns`][data.dissociation_constant.DissociationConstantData._try_patterns]
[`_try_patterns`][pcdigitizer.data.dissociation_constant.DissociationConstantData._try_patterns]
and logs a warning when no pattern matches, so that
[`parse_value`][data.dissociation_constant.DissociationConstantData.parse_value]
[`parse_value`][pcdigitizer.data.dissociation_constant.DissociationConstantData.parse_value]
stays free of logging concerns.
Args:
part: A single segment, already stripped of leading/trailing
whitespace and surrounding quotes.
original_line: The full original input line, passed through to
[`_try_patterns`][data.dissociation_constant.DissociationConstantData._try_patterns]
[`_try_patterns`][pcdigitizer.data.dissociation_constant.DissociationConstantData._try_patterns]
for provenance.
Returns:
A [`ParsedPKa`][data.dissociation_constant.ParsedPKa] record, or
A [`ParsedPKa`][pcdigitizer.data.dissociation_constant.ParsedPKa] record, or
`None` if the segment could not be matched to any known pKa format.
"""
result = cls._try_patterns(part, original_line)
@@ -389,7 +389,7 @@ class DissociationConstantData(AnnotationProcessor):
The input may contain one or more pKa values separated by
semicolons, or a prose sentence listing multiple values. Each
recognized value is returned as a
[`ParsedPKa`][data.dissociation_constant.ParsedPKa]
[`ParsedPKa`][pcdigitizer.data.dissociation_constant.ParsedPKa]
record. Segments that cannot be matched to any known format are logged at
WARNING level and excluded from the output.
@@ -404,7 +404,7 @@ class DissociationConstantData(AnnotationProcessor):
- `"pKa = 20"`
Returns:
A list of [`ParsedPKa`][data.dissociation_constant.ParsedPKa] records,
A list of [`ParsedPKa`][pcdigitizer.data.dissociation_constant.ParsedPKa] records,
one per recognized pKa value. Returns an empty list if no values
could be parsed.
"""
@@ -438,9 +438,9 @@ class DissociationConstantData(AnnotationProcessor):
Args:
annotation_data: A list of annotation entry dicts as returned by
[`get_data`][pubchem.PubChemAPI.get_data] for
[`get_data`][pcdigitizer.pubchem.PubChemAPI.get_data] for
the `"Dissociation Constants"` heading. Each entry is
expected to conform to [`AnnotationEntry`][responses.AnnotationEntry].
expected to conform to [`AnnotationEntry`][pcdigitizer.responses.AnnotationEntry].
Returns:
A polars DataFrame with one row per parsed pKa value
+17 -17
View File
@@ -20,7 +20,7 @@ class PubChemAPI:
All methods are class methods or static methods; no instance state is
required. Network access is centralized in
[`make_request`][pubchem.PubChemAPI.make_request] so that it can
[`make_request`][pcdigitizer.pubchem.PubChemAPI.make_request] so that it can
be replaced with a mock session during testing.
"""
@@ -82,7 +82,7 @@ class PubChemAPI:
Args:
url: The fully constructed PubChem REST URL to fetch.
session: An optional [`Session`][requests.Session] forwarded to
[`make_request`][pubchem.PubChemAPI.make_request].
[`make_request`][pcdigitizer.pubchem.PubChemAPI.make_request].
See that method for details.
Returns:
@@ -90,7 +90,7 @@ class PubChemAPI:
Raises:
RuntimeError: If the HTTP request fails (propagated from
[`make_request`][pubchem.PubChemAPI.make_request]).
[`make_request`][pcdigitizer.pubchem.PubChemAPI.make_request]).
json.JSONDecodeError: If the response body is not valid JSON.
"""
text = cls.make_request(url, session=session)
@@ -139,7 +139,7 @@ class PubChemAPI:
Raises:
ValueError: If `domain` is not in
[`ALLOWED_NAMESPACES`][pubchem.PubChemAPI.ALLOWED_NAMESPACES].
[`ALLOWED_NAMESPACES`][pcdigitizer.pubchem.PubChemAPI.ALLOWED_NAMESPACES].
ValueError: If the namespace key is not valid for the given domain.
ValueError: If `identifiers` is empty for a domain that requires it.
ValueError: If `identifiers` contains characters outside the
@@ -244,7 +244,7 @@ class PubChemAPI:
Args:
domain: The PubChem domain to query (e.g. `"compound"`,
`"annotations"`). Must be a key in
[`ALLOWED_NAMESPACES`][pubchem.PubChemAPI.ALLOWED_NAMESPACES].
[`ALLOWED_NAMESPACES`][pcdigitizer.pubchem.PubChemAPI.ALLOWED_NAMESPACES].
namespace: The namespace within the domain, optionally with a
`/`-separated value (e.g. `"name"`, `"sourcename/ChEBI"`).
pug: The PUG endpoint variant to use. Must be one of `"pug"`,
@@ -262,15 +262,15 @@ class PubChemAPI:
Returns:
A fully constructed, validated HTTPS URL string ready to pass to
[`make_request`][pubchem.PubChemAPI.make_request].
[`make_request`][pcdigitizer.pubchem.PubChemAPI.make_request].
Raises:
ValueError: If `pug` is not a recognized endpoint variant.
ValueError: If `domain`, `namespace`, or `identifiers` fail
validation (propagated from
[`_validate_components`][pubchem.PubChemAPI._validate_components]).
[`_validate_components`][pcdigitizer.pubchem.PubChemAPI._validate_components]).
ValueError: If the resulting URL fails the safety check
(propagated from [`_validate_url`][pubchem.PubChemAPI._validate_url]).
(propagated from [`_validate_url`][pcdigitizer.pubchem.PubChemAPI._validate_url]).
"""
if pug not in cls._VALID_PUG_ENDPOINTS:
raise ValueError(
@@ -313,7 +313,7 @@ class PubChemAPI:
Args:
session: An optional [`Session`][requests.Session] forwarded to
[`make_request`][pubchem.PubChemAPI.make_request]. Pass a mock during
[`make_request`][pcdigitizer.pubchem.PubChemAPI.make_request]. Pass a mock during
testing to avoid live network calls.
Returns:
@@ -357,21 +357,21 @@ class PubChemAPI:
Retrieves annotations from the `annotations/sourcename/<source>`
endpoint and groups them by type via
[`_process_annotations`][pubchem.PubChemAPI._process_annotations].
[`_process_annotations`][pcdigitizer.pubchem.PubChemAPI._process_annotations].
Note:
`output_format` is not exposed as a parameter here because
[`make_json`][pubchem.PubChemAPI.make_json] always expects a JSON response.
[`make_json`][pcdigitizer.pubchem.PubChemAPI.make_json] always expects a JSON response.
To retrieve raw non-JSON data from this endpoint, use
[`build_url`][pubchem.PubChemAPI.build_url] and
[`make_request`][pubchem.PubChemAPI.make_request] directly.
[`build_url`][pcdigitizer.pubchem.PubChemAPI.build_url] and
[`make_request`][pcdigitizer.pubchem.PubChemAPI.make_request] directly.
Args:
source_name: The PubChem depositor source name to query
(e.g. `"ChEBI"`). Forward slashes are replaced with
periods as required by the PubChem API.
session: An optional [`Session`][requests.Session] forwarded to
[`make_request`][pubchem.PubChemAPI.make_request]. Pass a mock during
[`make_request`][pcdigitizer.pubchem.PubChemAPI.make_request]. Pass a mock during
testing to avoid live network calls.
Returns:
@@ -412,7 +412,7 @@ class PubChemAPI:
Args:
session: An optional [`Session`][requests.Session] forwarded to
[`make_request`][pubchem.PubChemAPI.make_request]. Pass a mock during
[`make_request`][pcdigitizer.pubchem.PubChemAPI.make_request]. Pass a mock during
testing to avoid live network calls.
Returns:
@@ -457,11 +457,11 @@ class PubChemAPI:
Must be a positive integer. If `None`, all results are
returned.
session: An optional [`Session`][requests.Session]Session` forwarded to
[`make_request`][pubchem.PubChemAPI.make_request]. Pass a mock during
[`make_request`][pcdigitizer.pubchem.PubChemAPI.make_request]. Pass a mock during
testing to avoid live network calls.
Returns:
A list of [`AnnotationEntry`][responses.AnnotationEntry] dicts for the
A list of [`AnnotationEntry`][pcdigitizer.responses.AnnotationEntry] dicts for the
requested data, in the order returned by the API.
Raises:
+6 -6
View File
@@ -31,9 +31,9 @@ PubChem responses follow two broad envelope shapes depending on the endpoint:
```
Within both envelopes each `Annotation` element is an
[`AnnotationEntry`][responses.AnnotationEntry]. When the entry was fetched via
[`AnnotationEntry`][pcdigitizer.responses.AnnotationEntry]. When the entry was fetched via
PUG-View (i.e. a specific heading), it additionally carries a `Data` list whose
elements are [`PubChemDatum`][responses.PubChemDatum] records containing the
elements are [`PubChemDatum`][pcdigitizer.responses.PubChemDatum] records containing the
deposited values.
## Hierarchy
@@ -61,7 +61,7 @@ from typing import TypedDict
class MatchedRecord(TypedDict, total=False):
"""The `Matched` sub-object within an
[`ExtendedReference`][responses.ExtendedReference] entry.
[`ExtendedReference`][pcdigitizer.responses.ExtendedReference] entry.
Carries identifiers that link a specific deposited value to its
corresponding record in PubChem's live data system.
@@ -103,7 +103,7 @@ class DatumValue(TypedDict, total=False):
"""The `Value` object on a single data point within an annotation.
PubChem data points can carry several value types (numeric, boolean, binary).
This class models only the [`StringWithMarkup`][responses.StringWithMarkup]
This class models only the [`StringWithMarkup`][pcdigitizer.responses.StringWithMarkup]
variant, which is the form used for textual property data such as pKa strings.
"""
@@ -117,14 +117,14 @@ class DatumValue(TypedDict, total=False):
class PubChemDatum(TypedDict, total=False):
"""A single data point within a PubChem PUG-View annotation entry.
Each [`AnnotationEntry`][responses.AnnotationEntry] fetched from a specific heading
Each [`AnnotationEntry`][pcdigitizer.responses.AnnotationEntry] fetched from a specific heading
contains a `Data` list whose elements are `PubChemDatum` records. Each datum
represents one deposited measurement or value from a single source.
"""
Value: DatumValue
"""
The deposited value, in [`StringWithMarkup`][responses.StringWithMarkup]
The deposited value, in [`StringWithMarkup`][pcdigitizer.responses.StringWithMarkup]
form for textual properties.
"""