Skip to content

Commit 7746874

Browse files
gaborbernatclaude
andcommitted
Rewrite with standalone py_discovery from virtualenv
Copy the self-contained py_discovery package extracted from virtualenv into this repo as its new source. All imports are relative-only with zero virtualenv dependencies. Tests rewritten to import from py_discovery directly. Tooling updated to follow the pytest-env pattern: - hatchling + hatch-vcs build - tox.toml with tox-uv - ruff for format/lint - GitHub Actions with setup-uv - Diataxis docs with furo theme - ReadTheDocs via uv/tox Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 375e3a1 commit 7746874

43 files changed

Lines changed: 4011 additions & 2383 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/check.yaml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: check
2+
on:
3+
workflow_dispatch:
4+
push:
5+
branches: ["main"]
6+
tags-ignore: ["**"]
7+
pull_request:
8+
schedule:
9+
- cron: "0 8 * * *"
10+
11+
concurrency:
12+
group: check-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
test:
17+
runs-on: ubuntu-latest
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
env:
22+
- "3.14"
23+
- "3.13"
24+
- "3.12"
25+
- "3.11"
26+
- "3.10"
27+
- type
28+
- dev
29+
- pkg_meta
30+
steps:
31+
- uses: actions/checkout@v6
32+
with:
33+
fetch-depth: 0
34+
- name: Install the latest version of uv
35+
uses: astral-sh/setup-uv@v7
36+
with:
37+
enable-cache: true
38+
cache-dependency-glob: "pyproject.toml"
39+
github-token: ${{ secrets.GITHUB_TOKEN }}
40+
- name: Install tox
41+
run: uv tool install --python-preference only-managed --python 3.14 tox --with tox-uv
42+
- name: Install Python
43+
if: startsWith(matrix.env, '3.') && matrix.env != '3.14'
44+
run: uv python install --python-preference only-managed ${{ matrix.env }}
45+
- name: Setup test suite
46+
run: tox run -vv --notest --skip-missing-interpreters false -e ${{ matrix.env }}
47+
- name: Run test suite
48+
run: tox run --skip-pkg-install -e ${{ matrix.env }}
49+
env:
50+
PYTEST_ADDOPTS: "-vv --durations=20"
51+
DIFF_AGAINST: HEAD

.github/workflows/check.yml

Lines changed: 0 additions & 91 deletions
This file was deleted.

.github/workflows/release.yaml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Release to PyPI
2+
on:
3+
push:
4+
tags: ["*"]
5+
6+
env:
7+
dists-artifact-name: python-package-distributions
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v6
14+
with:
15+
fetch-depth: 0
16+
- name: Install the latest version of uv
17+
uses: astral-sh/setup-uv@v7
18+
with:
19+
enable-cache: true
20+
cache-dependency-glob: "pyproject.toml"
21+
github-token: ${{ secrets.GITHUB_TOKEN }}
22+
- name: Build package
23+
run: uv build --python 3.14 --python-preference only-managed --sdist --wheel . --out-dir dist
24+
- name: Store the distribution packages
25+
uses: actions/upload-artifact@v6
26+
with:
27+
name: ${{ env.dists-artifact-name }}
28+
path: dist/*
29+
30+
release:
31+
needs:
32+
- build
33+
runs-on: ubuntu-latest
34+
environment:
35+
name: release
36+
url: https://pypi.org/project/py-discovery/${{ github.ref_name }}
37+
permissions:
38+
id-token: write
39+
steps:
40+
- name: Download all the dists
41+
uses: actions/download-artifact@v7
42+
with:
43+
name: ${{ env.dists-artifact-name }}
44+
path: dist/
45+
- name: Publish to PyPI
46+
uses: pypa/gh-action-pypi-publish@v1.13.0
47+
with:
48+
attestations: true

.github/workflows/release.yml

Lines changed: 0 additions & 27 deletions
This file was deleted.

.gitignore

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
*.py[cod]
2-
*.swp
3-
__pycache__
4-
/src/py_discovery/_version.py
5-
build
6-
dist
1+
*.pyc
72
*.egg-info
8-
.tox
9-
/.*_cache
3+
dist/
4+
.tox/
5+
/src/py_discovery/_version.py

.pre-commit-config.yaml

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.6.0
3+
rev: v6.0.0
44
hooks:
55
- id: end-of-file-fixer
66
- id: trailing-whitespace
7+
- repo: https://github.com/python-jsonschema/check-jsonschema
8+
rev: 0.36.1
9+
hooks:
10+
- id: check-github-workflows
11+
args: ["--verbose"]
712
- repo: https://github.com/codespell-project/codespell
8-
rev: v2.3.0
13+
rev: v2.4.1
914
hooks:
1015
- id: codespell
11-
args: ["--write-changes"]
12-
- repo: https://github.com/tox-dev/tox-ini-fmt
13-
rev: "1.3.1"
14-
hooks:
15-
- id: tox-ini-fmt
16-
args: ["-p", "fix"]
16+
additional_dependencies: ["tomli>=2.2.1"]
1717
- repo: https://github.com/tox-dev/pyproject-fmt
18-
rev: "2.2.1"
18+
rev: "v2.11.1"
1919
hooks:
2020
- id: pyproject-fmt
2121
- repo: https://github.com/astral-sh/ruff-pre-commit
22-
rev: "v0.6.3"
22+
rev: "v0.14.14"
2323
hooks:
2424
- id: ruff-format
2525
- id: ruff
2626
args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"]
27+
- repo: https://github.com/rbubley/mirrors-prettier
28+
rev: "v3.8.1"
29+
hooks:
30+
- id: prettier
31+
additional_dependencies:
32+
- prettier@3.6.2
33+
- "@prettier/plugin-xml@3.4.2"
2734
- repo: meta
2835
hooks:
2936
- id: check-hooks-apply

.readthedocs.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
version: 2
2+
build:
3+
os: ubuntu-lts-latest
4+
tools: {}
5+
commands:
6+
- curl -LsSf https://astral.sh/uv/install.sh | sh
7+
- ~/.local/bin/uv tool install tox --with tox-uv -p 3.14 --managed-python
8+
- ~/.local/bin/tox run -e docs --

docs/conf.py

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,38 @@
1-
# noqa: D100
21
from __future__ import annotations
32

3+
from datetime import datetime, timezone
4+
45
from py_discovery import __version__
56

6-
project = name = "py_discovery"
77
company = "tox-dev"
8-
copyright = f"{company}" # noqa: A001
9-
version, release = __version__, __version__.split("+")[0]
8+
name = "py-discovery"
9+
version = ".".join(__version__.split(".")[:2])
10+
release = __version__
11+
copyright = f"2024-{datetime.now(tz=timezone.utc).year}, {company}" # noqa: A001
1012

1113
extensions = [
14+
"sphinx.ext.autodoc",
1215
"sphinx.ext.autosectionlabel",
1316
"sphinx.ext.extlinks",
14-
"sphinx.ext.autodoc",
15-
"sphinx_autodoc_typehints",
16-
"sphinx.ext.viewcode",
1717
"sphinx.ext.intersphinx",
18+
"sphinx_autodoc_typehints",
1819
]
19-
master_doc, source_suffix = "index", ".rst"
20-
21-
html_theme = "furo"
22-
html_title, html_last_updated_fmt = "py-discovery docs", "%Y-%m-%dT%H:%M:%S"
23-
pygments_style, pygments_dark_style = "sphinx", "monokai"
24-
25-
autoclass_content, autodoc_typehints = "both", "none"
26-
autodoc_default_options = {"members": True, "member-order": "bysource", "undoc-members": True, "show-inheritance": True}
27-
inheritance_alias = {}
2820

29-
extlinks = {
30-
"issue": ("https://github.com/tox-dev/py-discovery/issues/%s", "#%s"),
31-
"pull": ("https://github.com/tox-dev/py-discovery/pull/%s", "PR #%s"),
32-
"user": ("https://github.com/%s", "@%s"),
33-
}
3421
intersphinx_mapping = {
3522
"python": ("https://docs.python.org/3", None),
36-
"packaging": ("https://packaging.pypa.io/en/latest", None),
3723
}
3824

39-
nitpicky = True
40-
nitpick_ignore = []
25+
templates_path = []
26+
source_suffix = ".rst"
27+
exclude_patterns = ["_build"]
28+
29+
main_doc = "index"
30+
pygments_style = "default"
31+
always_document_param_types = True
32+
project = name
33+
34+
html_theme = "furo"
35+
html_title = project
36+
html_last_updated_fmt = datetime.now(tz=timezone.utc).isoformat()
37+
pygments_dark_style = "monokai"
38+
html_show_sourcelink = False

docs/explanation.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
How py-discovery works
2+
=====================
3+
4+
Discovery strategy
5+
------------------
6+
7+
The :class:`~py_discovery.Builtin` discover searches for Python interpreters in the following order:
8+
9+
1. **Absolute paths** -- if the spec is an absolute path, try it directly.
10+
2. **``try_first_with``** -- explicit paths to try before anything else.
11+
3. **Relative paths** -- resolve relative to the current directory.
12+
4. **Current interpreter** -- the running Python itself.
13+
5. **Windows registry** (PEP 514) -- on Windows, enumerate registered interpreters.
14+
6. **PATH search** -- walk ``$PATH`` entries, matching filenames against the spec pattern.
15+
7. **Version-manager shims** -- resolve pyenv, mise, and asdf shims to real binaries.
16+
8. **uv-managed Pythons** -- check ``UV_PYTHON_INSTALL_DIR``, ``XDG_DATA_HOME/uv/python``, or the platform default.
17+
18+
Cache sharing
19+
-------------
20+
21+
``py-discovery`` uses the same on-disk cache layout as virtualenv (``py_info/4/<sha256>.json``), so they share
22+
cached interpreter metadata. The :class:`~py_discovery.DiskCache` stores results under a configurable root directory
23+
with file locking via ``filelock``.
24+
25+
Protocol design
26+
---------------
27+
28+
The cache layer is defined as a :class:`typing.Protocol` (:class:`~py_discovery.PyInfoCache`), allowing custom
29+
backends without inheriting from any base class. The built-in :class:`~py_discovery.DiskCache` implements this protocol
30+
using JSON files and ``filelock``.

0 commit comments

Comments
 (0)