Skip to main content

Resolve the documentation URL for any Python module or PyPI distribution name.

Project description

pymanual

Given a Python module name (import name) or a distribution name (the string you'd type in pip install …), deterministically return the best available documentation URL — or a status token explaining why one isn't available.

Install

End users:

pipx install pymanual
# or
uv tool install pymanual

This puts pymanual on your PATH.

Developing on the project itself instead:

git clone https://github.com/gkarpo/pymanual && cd pymanual
uv sync

CLI

pymanual <module> [--no-network] [--no-cache]
pymanual --clear-cache

Exit code is 0 when a URL is returned, 1 when a status token is returned.

$ pymanual json
https://docs.python.org/3/library/json.html

$ pymanual email.mime.text
https://docs.python.org/3/library/email.html

$ pymanual pytest
https://docs.pytest.org/en/latest/

$ pymanual pytest-cov       # distribution name with a dash
https://pytest-cov.readthedocs.io/

$ pymanual python-dateutil  # not installed; PyPI lookup
https://dateutil.readthedocs.io/en/stable/

$ pymanual definitely_no_such_xyz
module_not_found

If you're working inside the project source, prefix every command with uv run (e.g. uv run pymanual json).

Flags

  • --no-network — skip the PyPI HTTP fallback (step 4.ii below for installed third-party modules, and the second half of step 5 for the distribution-name fallback). Resolution stays fully offline.
  • --no-cache — bypass the local cache for that one call (no read, no write).
  • --clear-cache — delete the cache file and exit.

Library

from pymanual import (
    resolve_doc_url,
    STATUS_NOT_FOUND,
    STATUS_UNRESOLVABLE_PATH,
    STATUS_LOCAL,
)

resolve_doc_url("json")                 # 'https://docs.python.org/3/library/json.html'
resolve_doc_url("pytest")               # URL from installed distribution metadata
resolve_doc_url("pytest-cov")           # distribution-name fallback
resolve_doc_url("python-dateutil")      # not installed → PyPI lookup
resolve_doc_url("nope_xyz")             # 'module_not_found'

# Same options as the CLI flags:
resolve_doc_url("pytest", network=False)     # offline-only
resolve_doc_url("json", use_cache=False)     # bypass the on-disk cache

Resolution strategy

Strict order — the first step that yields a result wins.

  1. Import the module with importlib.import_module.
    • On success → continue at step 2.
    • On ImportError/ValueError → try the distribution-name fallback (step 5).
  2. Get the file path with inspect.getfile. If unavailable (e.g. namespace packages with no __file__), return unresolvable_module_path. Builtins (sys, builtins, …) are short-circuited as stdlib before this step.
  3. Classify by file path only (not sys.path):
    • inside sysconfig.get_paths()["stdlib"]stdlib
    • inside site-packages / dist-packages / a venv directory → third_party
    • otherwise → local
  4. Resolve URL by classification:
    • stdlibhttps://docs.python.org/3/library/<top-level>.html
    • third_party:
      1. importlib.metadata.metadata(...) → prefer Project-URL keys matching documentation/docs/doc, then homepage, then Home-page
      2. PyPI JSON (https://pypi.org/pypi/<name>/json) — same key precedence; skipped when network=False
      3. Heuristic last resort: https://pypi.org/project/<name>/
    • locallocal_module_no_external_docs
  5. Distribution-name fallback (when import_module found nothing):
    • Try importlib.metadata.metadata(<input>) — catches cases like pytest-cov, PyYAML, scikit-learn whose import names don't match their distribution names. If installed → return URL from its metadata (falling back to https://pypi.org/project/<input>/).
    • Else, if network=True, query PyPI directly for <input>. If the package exists there → return its documentation URL.
    • Otherwise → module_not_found.

Import-name vs distribution-name mismatches (e.g. yamlPyYAML) from step 4 are handled via importlib.metadata.packages_distributions().

Local cache

Successful URL resolutions are cached at $XDG_CACHE_HOME/pymanual/cache.json (defaults to ~/.cache/pymanual/cache.json). Subsequent lookups for the same input string return instantly without hitting importlib.import_module, importlib.metadata, or PyPI.

  • Status tokens (module_not_found, etc.) are not cached, so installing a previously-missing module just works on the next call.
  • Cache key is the verbatim input string — pytest-cov and pytest_cov are independent entries.
  • LRU-bounded at 100 entries; the oldest entry is evicted when the cap is exceeded.
  • No TTL; entries live until eviction, until you run pymanual --clear-cache, or until you delete the file.
  • Override location for tests/sandboxing via the PYMANUAL_CACHE_DIR env var.

Output contract

A single string — either a URL or one of:

  • module_not_found
  • unresolvable_module_path
  • local_module_no_external_docs

Development

uv run pytest -q                  # run tests
uv run pytest --cov=pymanual      # with coverage

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymanual-1.0.0.tar.gz (9.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymanual-1.0.0-py3-none-any.whl (12.6 kB view details)

Uploaded Python 3

File details

Details for the file pymanual-1.0.0.tar.gz.

File metadata

  • Download URL: pymanual-1.0.0.tar.gz
  • Upload date:
  • Size: 9.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pymanual-1.0.0.tar.gz
Algorithm Hash digest
SHA256 425a659e6ed854dd270747cc076267b62058cf440933f02cdbd6110670167060
MD5 257c5375962d869e7340acd6c750b8c5
BLAKE2b-256 96fb99c51de4ef7cea5346d4247643ec4f5cca8192e94171c021f3cd385ac603

See more details on using hashes here.

File details

Details for the file pymanual-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: pymanual-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 12.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pymanual-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 82b1bde0feb83b316cba3e502999ecca370b0201b12b5a9bc5ff37f0911971c4
MD5 a6790363f3b7ed919ea92fef231079cc
BLAKE2b-256 fe602bf22b2baf0b8091fe22c81f8902bd0e6105b44d0b8f789174ea1d7dc451

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page