Skip to content

♻️ refactor(discovery): extract py_discovery as self-contained package#3070

Merged
gaborbernat merged 6 commits intopypa:mainfrom
gaborbernat:extract-py-discovery
Feb 25, 2026
Merged

♻️ refactor(discovery): extract py_discovery as self-contained package#3070
gaborbernat merged 6 commits intopypa:mainfrom
gaborbernat:extract-py-discovery

Conversation

@gaborbernat
Copy link
Contributor

virtualenv's discovery module is tightly coupled to the rest of the codebase through imports of AppData, subprocess wrappers, and virtualenv.info utilities. This makes it impossible for other tools — tox, pipx, nox — to reuse Python discovery without pulling in all of virtualenv. Today these tools either reimplement discovery poorly (no caching, no shim resolution) or reach into virtualenv internals directly with fragile imports like from virtualenv.discovery.cached_py_info import from_exe.

This PR introduces src/virtualenv/py_discovery/ as a self-contained package with zero imports from the rest of virtualenv. ♻️ It ships its own Protocol-based cache layer (DiskCache/NoOpCache), platform compat utilities, and specifier parsing — all inlined from their original locations. The cache interface uses structural typing so virtualenv's existing AppData passes through without adapters. A resolve_script parameter replaces the zipapp ensure_extracted coupling, keeping that concern in virtualenv's wrapper layer where it belongs.

The existing src/virtualenv/discovery/ becomes thin re-export wrappers that delegate to py_discovery. All external consumers (tox's from virtualenv.discovery import cached_py_info, creator modules importing PythonInfo, etc.) continue working unchanged. The creators() method, which depends on virtualenv's plugin system, is monkey-patched back onto PythonInfo in the wrapper layer rather than living in the extracted package. 🔌 Tools that want to use discovery directly can import from virtualenv.py_discovery with just filelock and platformdirs as dependencies.

Ref: #2074

@gaborbernat gaborbernat force-pushed the extract-py-discovery branch 5 times, most recently from ad61c9e to 08709c4 Compare February 24, 2026 09:26
Move discovery logic into src/virtualenv/py_discovery/ with
underscore-prefixed private modules and minimal public API.
Remove creators() monkey-patch in favor of direct
CreatorSelector.for_interpreter() calls. Auto-detect zipapp
via pkgutil.get_data instead of exposing set_resolve_script.
Thin wrappers in discovery/ provide CLI/argparse integration.
@gaborbernat gaborbernat force-pushed the extract-py-discovery branch 2 times, most recently from b1369d3 to e860fc1 Compare February 25, 2026 17:40
Sync specifier frozen dataclasses, Final annotations, verbose regexes,
and from_string factory methods from the py-discovery standalone repo.

Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
Replace internal py_discovery copy with python-discovery>=1.
Add backward-compatibility re-export shims for py_info,
py_spec, and cached_py_info to avoid breaking tox and other
downstream consumers. Fix system_executable None handling
in creator.py and restore fixture/mock parameter names that
were incorrectly renamed with _ prefix.
Assert system_executable is not None to satisfy ty
type checker. Normalize distribution names in zipapp
build and lookup to handle packages with hyphens like
python-discovery. Add Python 3.14 to zipapp versions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant