python-discovery 1.4.4__tar.gz → 1.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_discovery-1.4.4 → python_discovery-1.5.0}/.github/workflows/check.yaml +3 -4
- {python_discovery-1.4.4 → python_discovery-1.5.0}/.github/workflows/prepare-release.yaml +1 -10
- {python_discovery-1.4.4 → python_discovery-1.5.0}/.github/workflows/release.yaml +1 -5
- {python_discovery-1.4.4 → python_discovery-1.5.0}/.pre-commit-config.yaml +16 -9
- {python_discovery-1.4.4 → python_discovery-1.5.0}/PKG-INFO +2 -14
- {python_discovery-1.4.4 → python_discovery-1.5.0}/docs/changelog.rst +8 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/docs/conf.py +1 -1
- {python_discovery-1.4.4 → python_discovery-1.5.0}/pyproject.toml +17 -16
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/_cache.py +5 -5
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/_cached_py_info.py +4 -4
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/_discovery.py +2 -2
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/_py_info.py +17 -14
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/_py_spec.py +3 -3
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/_specifier.py +2 -2
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/_windows/_pep514.py +11 -11
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tasks/release.py +35 -35
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/test_discovery.py +2 -1
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/test_py_info_extra.py +4 -1
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/test_specifier.py +5 -5
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/windows/conftest.py +1 -1
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tox.toml +4 -4
- {python_discovery-1.4.4 → python_discovery-1.5.0}/.github/FUNDING.yaml +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/.github/SECURITY.md +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/.github/dependabot.yaml +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/.github/release.yaml +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/.gitignore +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/.readthedocs.yaml +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/.readthedocs.yml +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/CODE_OF_CONDUCT.md +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/LICENSE +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/README.md +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/docs/_static/custom.css +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/docs/_static/logo.svg +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/docs/changelog/template.jinja2 +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/docs/explanation.rst +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/docs/how-to/standalone-usage.rst +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/docs/index.rst +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/docs/reference/api.rst +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/docs/reference/environment-variables.rst +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/docs/tutorial/getting-started.rst +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/__init__.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/_compat.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/_windows/__init__.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/_windows/_propose.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/src/python_discovery/py.typed +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/conftest.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/py_info/test_py_info.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/py_info/test_py_info_exe_based_of.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/test_cache.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/test_cached_py_info.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/test_discovery_extra.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/test_iter_interpreters.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/test_py_spec.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/test_py_spec_extra.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/windows/test_windows.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/windows/test_windows_pep514.py +0 -0
- {python_discovery-1.4.4 → python_discovery-1.5.0}/tests/windows/winreg_mock_values.py +0 -0
|
@@ -7,14 +7,11 @@ on:
|
|
|
7
7
|
pull_request:
|
|
8
8
|
schedule:
|
|
9
9
|
- cron: "0 8 * * *"
|
|
10
|
-
|
|
11
10
|
concurrency:
|
|
12
11
|
group: check-${{ github.ref }}
|
|
13
12
|
cancel-in-progress: true
|
|
14
|
-
|
|
15
13
|
permissions:
|
|
16
14
|
contents: read
|
|
17
|
-
|
|
18
15
|
jobs:
|
|
19
16
|
test:
|
|
20
17
|
runs-on: ubuntu-latest
|
|
@@ -22,6 +19,8 @@ jobs:
|
|
|
22
19
|
fail-fast: false
|
|
23
20
|
matrix:
|
|
24
21
|
env:
|
|
22
|
+
- "3.15"
|
|
23
|
+
- "3.15t"
|
|
25
24
|
- "3.14"
|
|
26
25
|
- "3.13"
|
|
27
26
|
- "3.12"
|
|
@@ -39,7 +38,7 @@ jobs:
|
|
|
39
38
|
fetch-depth: 0
|
|
40
39
|
persist-credentials: false
|
|
41
40
|
- name: Install the latest version of uv
|
|
42
|
-
uses: astral-sh/setup-uv@
|
|
41
|
+
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
43
42
|
with:
|
|
44
43
|
enable-cache: false
|
|
45
44
|
cache-dependency-glob: "pyproject.toml"
|
|
@@ -12,13 +12,10 @@ on:
|
|
|
12
12
|
- minor
|
|
13
13
|
- patch
|
|
14
14
|
default: auto
|
|
15
|
-
|
|
16
15
|
permissions:
|
|
17
16
|
contents: read
|
|
18
|
-
|
|
19
17
|
env:
|
|
20
18
|
FORCE_COLOR: 1
|
|
21
|
-
|
|
22
19
|
jobs:
|
|
23
20
|
prepare-release:
|
|
24
21
|
runs-on: ubuntu-24.04
|
|
@@ -31,19 +28,16 @@ jobs:
|
|
|
31
28
|
fetch-depth: 0
|
|
32
29
|
token: ${{ secrets.RELEASE_PAT }}
|
|
33
30
|
persist-credentials: true
|
|
34
|
-
|
|
35
31
|
- name: Install the latest version of uv
|
|
36
|
-
uses: astral-sh/setup-uv@
|
|
32
|
+
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
37
33
|
with:
|
|
38
34
|
enable-cache: true
|
|
39
35
|
cache-dependency-glob: "pyproject.toml"
|
|
40
36
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
41
|
-
|
|
42
37
|
- name: Configure git
|
|
43
38
|
run: |
|
|
44
39
|
git config user.name "${GITHUB_ACTOR}"
|
|
45
40
|
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
|
|
46
|
-
|
|
47
41
|
- name: Calculate next version
|
|
48
42
|
id: version
|
|
49
43
|
env:
|
|
@@ -84,16 +78,13 @@ jobs:
|
|
|
84
78
|
|
|
85
79
|
echo "Next version: $next"
|
|
86
80
|
echo "version=$next" >> $GITHUB_OUTPUT
|
|
87
|
-
|
|
88
81
|
- name: Install tox
|
|
89
82
|
run: uv tool install --python-preference only-managed --python 3.14 tox@latest --with tox-uv
|
|
90
|
-
|
|
91
83
|
- name: Run release process
|
|
92
84
|
run: tox run -e release -- ${STEPS_VERSION_OUTPUTS_VERSION}
|
|
93
85
|
env:
|
|
94
86
|
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
|
|
95
87
|
STEPS_VERSION_OUTPUTS_VERSION: ${{ steps.version.outputs.version }}
|
|
96
|
-
|
|
97
88
|
- name: Display completion message
|
|
98
89
|
run: echo "Release ${STEPS_VERSION_OUTPUTS_VERSION} prepared and pushed successfully!"
|
|
99
90
|
env:
|
|
@@ -2,13 +2,10 @@ name: Release to PyPI
|
|
|
2
2
|
on:
|
|
3
3
|
push:
|
|
4
4
|
tags: ["*"]
|
|
5
|
-
|
|
6
5
|
permissions:
|
|
7
6
|
contents: read
|
|
8
|
-
|
|
9
7
|
env:
|
|
10
8
|
dists-artifact-name: python-package-distributions
|
|
11
|
-
|
|
12
9
|
jobs:
|
|
13
10
|
build:
|
|
14
11
|
runs-on: ubuntu-latest
|
|
@@ -18,7 +15,7 @@ jobs:
|
|
|
18
15
|
fetch-depth: 0
|
|
19
16
|
persist-credentials: false
|
|
20
17
|
- name: Install the latest version of uv
|
|
21
|
-
uses: astral-sh/setup-uv@
|
|
18
|
+
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
22
19
|
with:
|
|
23
20
|
enable-cache: false
|
|
24
21
|
cache-dependency-glob: "pyproject.toml"
|
|
@@ -30,7 +27,6 @@ jobs:
|
|
|
30
27
|
with:
|
|
31
28
|
name: ${{ env.dists-artifact-name }}
|
|
32
29
|
path: dist/*
|
|
33
|
-
|
|
34
30
|
release:
|
|
35
31
|
needs:
|
|
36
32
|
- build
|
|
@@ -10,29 +10,36 @@ repos:
|
|
|
10
10
|
- id: check-github-workflows
|
|
11
11
|
args: ["--verbose"]
|
|
12
12
|
- repo: https://github.com/codespell-project/codespell
|
|
13
|
-
rev: v2.4.
|
|
13
|
+
rev: v2.4.3
|
|
14
14
|
hooks:
|
|
15
15
|
- id: codespell
|
|
16
16
|
additional_dependencies: ["tomli>=2.4"]
|
|
17
17
|
- repo: https://github.com/tox-dev/pyproject-fmt
|
|
18
|
-
rev: "v2.25.
|
|
18
|
+
rev: "v2.25.3"
|
|
19
19
|
hooks:
|
|
20
20
|
- id: pyproject-fmt
|
|
21
21
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
22
|
-
rev: "v0.15.
|
|
22
|
+
rev: "v0.15.22"
|
|
23
23
|
hooks:
|
|
24
24
|
- id: ruff-format
|
|
25
25
|
- id: ruff
|
|
26
26
|
args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"]
|
|
27
|
-
- repo: https://github.com/
|
|
28
|
-
rev: "
|
|
27
|
+
- repo: https://github.com/google/yamlfmt
|
|
28
|
+
rev: "v0.21.0"
|
|
29
29
|
hooks:
|
|
30
|
-
- id:
|
|
30
|
+
- id: yamlfmt
|
|
31
|
+
- repo: local
|
|
32
|
+
hooks:
|
|
33
|
+
- id: mdformat
|
|
34
|
+
name: mdformat
|
|
35
|
+
entry: mdformat --wrap 120
|
|
36
|
+
language: python
|
|
37
|
+
types: [markdown]
|
|
31
38
|
additional_dependencies:
|
|
32
|
-
-
|
|
33
|
-
-
|
|
39
|
+
- mdformat-gfm>=1
|
|
40
|
+
- mdformat-ruff>=0.1.3
|
|
34
41
|
- repo: https://github.com/zizmorcore/zizmor-pre-commit
|
|
35
|
-
rev: v1.
|
|
42
|
+
rev: v1.27.0
|
|
36
43
|
hooks:
|
|
37
44
|
- id: zizmor
|
|
38
45
|
- repo: meta
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-discovery
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: Python interpreter discovery
|
|
5
5
|
Project-URL: Changelog, https://github.com/tox-dev/python-discovery/releases
|
|
6
6
|
Project-URL: Documentation, https://python-discovery.readthedocs.io
|
|
@@ -42,25 +42,13 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
42
42
|
Classifier: Programming Language :: Python :: 3.12
|
|
43
43
|
Classifier: Programming Language :: Python :: 3.13
|
|
44
44
|
Classifier: Programming Language :: Python :: 3.14
|
|
45
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
45
46
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
46
47
|
Classifier: Topic :: Software Development :: Libraries
|
|
47
48
|
Classifier: Topic :: Utilities
|
|
48
49
|
Requires-Python: >=3.8
|
|
49
50
|
Requires-Dist: filelock>=3.15.4
|
|
50
51
|
Requires-Dist: platformdirs<5,>=4.3.6
|
|
51
|
-
Provides-Extra: docs
|
|
52
|
-
Requires-Dist: furo>=2025.12.19; extra == 'docs'
|
|
53
|
-
Requires-Dist: sphinx-autodoc-typehints>=3.6.3; extra == 'docs'
|
|
54
|
-
Requires-Dist: sphinx>=9.1; extra == 'docs'
|
|
55
|
-
Requires-Dist: sphinxcontrib-mermaid>=2; extra == 'docs'
|
|
56
|
-
Requires-Dist: sphinxcontrib-towncrier>=0.4; extra == 'docs'
|
|
57
|
-
Requires-Dist: towncrier>=25.8; extra == 'docs'
|
|
58
|
-
Provides-Extra: testing
|
|
59
|
-
Requires-Dist: covdefaults>=2.3; extra == 'testing'
|
|
60
|
-
Requires-Dist: coverage>=7.5.4; extra == 'testing'
|
|
61
|
-
Requires-Dist: pytest-mock>=3.14; extra == 'testing'
|
|
62
|
-
Requires-Dist: pytest>=8.3.5; extra == 'testing'
|
|
63
|
-
Requires-Dist: setuptools>=75.1; extra == 'testing'
|
|
64
52
|
Description-Content-Type: text/markdown
|
|
65
53
|
|
|
66
54
|
# [`python-discovery`](https://python-discovery.readthedocs.io/en/latest/)
|
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
.. towncrier release notes start
|
|
8
8
|
|
|
9
|
+
********************
|
|
10
|
+
v1.5.0 (2026-07-21)
|
|
11
|
+
********************
|
|
12
|
+
|
|
13
|
+
Packaging updates and notes for downstreams - 1.5.0
|
|
14
|
+
===================================================
|
|
15
|
+
- Declare support for Python 3.15 and run the test suite against it, currently in beta. (:issue:`104`)
|
|
16
|
+
|
|
9
17
|
********************
|
|
10
18
|
v1.4.4 (2026-07-08)
|
|
11
19
|
********************
|
|
@@ -11,7 +11,7 @@ company = "tox-dev"
|
|
|
11
11
|
name = "python-discovery"
|
|
12
12
|
version = ".".join(__version__.split(".")[:2])
|
|
13
13
|
release = __version__
|
|
14
|
-
copyright = f"2026-{datetime.now(tz=timezone.utc).year}, {company}" #
|
|
14
|
+
copyright = f"2026-{datetime.now(tz=timezone.utc).year}, {company}" # ruff:ignore[builtin-variable-shadowing]
|
|
15
15
|
|
|
16
16
|
extensions = [
|
|
17
17
|
"sphinx.ext.autodoc",
|
|
@@ -35,6 +35,7 @@ classifiers = [
|
|
|
35
35
|
"Programming Language :: Python :: 3.12",
|
|
36
36
|
"Programming Language :: Python :: 3.13",
|
|
37
37
|
"Programming Language :: Python :: 3.14",
|
|
38
|
+
"Programming Language :: Python :: 3.15",
|
|
38
39
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
39
40
|
"Topic :: Software Development :: Libraries",
|
|
40
41
|
"Topic :: Utilities",
|
|
@@ -46,21 +47,6 @@ dependencies = [
|
|
|
46
47
|
"filelock>=3.15.4",
|
|
47
48
|
"platformdirs<5,>=4.3.6",
|
|
48
49
|
]
|
|
49
|
-
optional-dependencies.docs = [
|
|
50
|
-
"furo>=2025.12.19",
|
|
51
|
-
"sphinx>=9.1",
|
|
52
|
-
"sphinx-autodoc-typehints>=3.6.3",
|
|
53
|
-
"sphinxcontrib-mermaid>=2",
|
|
54
|
-
"sphinxcontrib-towncrier>=0.4",
|
|
55
|
-
"towncrier>=25.8",
|
|
56
|
-
]
|
|
57
|
-
optional-dependencies.testing = [
|
|
58
|
-
"covdefaults>=2.3",
|
|
59
|
-
"coverage>=7.5.4",
|
|
60
|
-
"pytest>=8.3.5",
|
|
61
|
-
"pytest-mock>=3.14",
|
|
62
|
-
"setuptools>=75.1",
|
|
63
|
-
]
|
|
64
50
|
urls.Changelog = "https://github.com/tox-dev/python-discovery/releases"
|
|
65
51
|
urls.Documentation = "https://python-discovery.readthedocs.io"
|
|
66
52
|
urls.Homepage = "https://github.com/tox-dev/python-discovery"
|
|
@@ -68,6 +54,21 @@ urls.Source = "https://github.com/tox-dev/python-discovery"
|
|
|
68
54
|
urls.Tracker = "https://github.com/tox-dev/python-discovery/issues"
|
|
69
55
|
|
|
70
56
|
[dependency-groups]
|
|
57
|
+
test = [
|
|
58
|
+
"covdefaults>=2.3",
|
|
59
|
+
"coverage>=7.5.4",
|
|
60
|
+
"pytest>=8.3.5",
|
|
61
|
+
"pytest-mock>=3.14",
|
|
62
|
+
"setuptools>=75.1",
|
|
63
|
+
]
|
|
64
|
+
docs = [
|
|
65
|
+
"furo>=2025.12.19",
|
|
66
|
+
"sphinx>=9.1",
|
|
67
|
+
"sphinx-autodoc-typehints>=3.6.3",
|
|
68
|
+
"sphinxcontrib-mermaid>=2",
|
|
69
|
+
"sphinxcontrib-towncrier>=0.4",
|
|
70
|
+
"towncrier>=25.8",
|
|
71
|
+
]
|
|
71
72
|
release = [
|
|
72
73
|
"gitpython>=3.1.46",
|
|
73
74
|
"packaging>=26",
|
|
@@ -145,7 +146,7 @@ write-changes = true
|
|
|
145
146
|
count = true
|
|
146
147
|
|
|
147
148
|
[tool.pyproject-fmt]
|
|
148
|
-
max_supported_python = "3.
|
|
149
|
+
max_supported_python = "3.15"
|
|
149
150
|
|
|
150
151
|
[tool.ty]
|
|
151
152
|
src.exclude = [ "tests/windows/winreg_mock_values.py" ]
|
|
@@ -104,7 +104,7 @@ class DiskContentStore:
|
|
|
104
104
|
|
|
105
105
|
@contextmanager
|
|
106
106
|
def locked(self) -> Generator[None]:
|
|
107
|
-
from filelock import FileLock #
|
|
107
|
+
from filelock import FileLock # ruff:ignore[import-outside-top-level]
|
|
108
108
|
|
|
109
109
|
lock_path = self._folder / f"{self._key}.lock"
|
|
110
110
|
lock_path.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -148,10 +148,10 @@ class DiskCache:
|
|
|
148
148
|
class NoOpContentStore(ContentStore):
|
|
149
149
|
"""Content store that does nothing -- implements ContentStore protocol."""
|
|
150
150
|
|
|
151
|
-
def exists(self) -> bool: #
|
|
151
|
+
def exists(self) -> bool: # ruff:ignore[no-self-use]
|
|
152
152
|
return False
|
|
153
153
|
|
|
154
|
-
def read(self) -> dict | None: #
|
|
154
|
+
def read(self) -> dict | None: # ruff:ignore[no-self-use]
|
|
155
155
|
return None
|
|
156
156
|
|
|
157
157
|
def write(self, content: dict) -> None:
|
|
@@ -161,14 +161,14 @@ class NoOpContentStore(ContentStore):
|
|
|
161
161
|
pass
|
|
162
162
|
|
|
163
163
|
@contextmanager
|
|
164
|
-
def locked(self) -> Generator[None]: #
|
|
164
|
+
def locked(self) -> Generator[None]: # ruff:ignore[no-self-use]
|
|
165
165
|
yield
|
|
166
166
|
|
|
167
167
|
|
|
168
168
|
class NoOpCache(PyInfoCache):
|
|
169
169
|
"""Cache that does nothing -- implements PyInfoCache protocol."""
|
|
170
170
|
|
|
171
|
-
def py_info(self, path: Path) -> NoOpContentStore: #
|
|
171
|
+
def py_info(self, path: Path) -> NoOpContentStore: # ruff:ignore[unused-method-argument, no-self-use]
|
|
172
172
|
return NoOpContentStore()
|
|
173
173
|
|
|
174
174
|
def py_info_clear(self) -> None:
|
|
@@ -8,14 +8,14 @@ import logging
|
|
|
8
8
|
import os
|
|
9
9
|
import pkgutil
|
|
10
10
|
import secrets
|
|
11
|
-
import subprocess #
|
|
11
|
+
import subprocess # ruff:ignore[suspicious-subprocess-import]
|
|
12
12
|
import sys
|
|
13
13
|
import tempfile
|
|
14
14
|
from collections import OrderedDict
|
|
15
15
|
from contextlib import contextmanager
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
from shlex import quote
|
|
18
|
-
from subprocess import Popen, TimeoutExpired #
|
|
18
|
+
from subprocess import Popen, TimeoutExpired # ruff:ignore[suspicious-subprocess-import]
|
|
19
19
|
from typing import TYPE_CHECKING, Final
|
|
20
20
|
|
|
21
21
|
from ._cache import NoOpCache
|
|
@@ -32,7 +32,7 @@ _CACHE[Path(sys.executable)] = PythonInfo()
|
|
|
32
32
|
_LOGGER: Final[logging.Logger] = logging.getLogger(__name__)
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def from_exe( #
|
|
35
|
+
def from_exe( # ruff:ignore[too-many-arguments]
|
|
36
36
|
cls: type[PythonInfo],
|
|
37
37
|
cache: PyInfoCache | None,
|
|
38
38
|
exe: str,
|
|
@@ -197,7 +197,7 @@ def _run_subprocess(
|
|
|
197
197
|
env["PYTHONUTF8"] = "1"
|
|
198
198
|
_LOGGER.debug("get interpreter info via cmd: %s", LogCmd(cmd))
|
|
199
199
|
try:
|
|
200
|
-
process = Popen( #
|
|
200
|
+
process = Popen( # ruff:ignore[subprocess-without-shell-equals-true]
|
|
201
201
|
cmd,
|
|
202
202
|
universal_newlines=True,
|
|
203
203
|
stdin=subprocess.PIPE,
|
|
@@ -89,7 +89,7 @@ def iter_interpreters(
|
|
|
89
89
|
yield from _iter_for_spec(spec_str, first_with, cache, env_map, predicate, seen)
|
|
90
90
|
|
|
91
91
|
|
|
92
|
-
def _iter_for_spec( #
|
|
92
|
+
def _iter_for_spec( # ruff:ignore[too-many-arguments, too-many-positional-arguments]
|
|
93
93
|
spec_str: str | None,
|
|
94
94
|
try_first_with: tuple[str, ...],
|
|
95
95
|
cache: PyInfoCache | None,
|
|
@@ -231,7 +231,7 @@ def _propose_current_and_windows(
|
|
|
231
231
|
yield current_python, True
|
|
232
232
|
|
|
233
233
|
if IS_WIN: # pragma: win32 cover
|
|
234
|
-
from ._windows import propose_interpreters as win_propose #
|
|
234
|
+
from ._windows import propose_interpreters as win_propose # ruff:ignore[import-outside-top-level]
|
|
235
235
|
|
|
236
236
|
for interpreter in win_propose(spec, cache, env):
|
|
237
237
|
if _is_new_exe(str(interpreter.executable), tested_exes):
|
|
@@ -49,7 +49,7 @@ _CONF_VAR_RE: Final[re.Pattern[str]] = re.compile(
|
|
|
49
49
|
)
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
class PythonInfo: #
|
|
52
|
+
class PythonInfo: # ruff:ignore[too-many-public-methods]
|
|
53
53
|
"""Contains information for a Python interpreter."""
|
|
54
54
|
|
|
55
55
|
def __init__(self) -> None:
|
|
@@ -161,7 +161,7 @@ class PythonInfo: # noqa: PLR0904
|
|
|
161
161
|
"""Detect the tcl and tk libraries using tkinter."""
|
|
162
162
|
tcl_lib, tk_lib = None, None
|
|
163
163
|
try:
|
|
164
|
-
import tkinter as tk #
|
|
164
|
+
import tkinter as tk # ruff:ignore[import-outside-top-level]
|
|
165
165
|
except ImportError:
|
|
166
166
|
pass
|
|
167
167
|
else:
|
|
@@ -177,7 +177,7 @@ class PythonInfo: # noqa: PLR0904
|
|
|
177
177
|
@staticmethod
|
|
178
178
|
def _query_tk_library(tcl: tk.Tk) -> str | None: # pragma: no cover
|
|
179
179
|
"""Try to get the TK library path directly from Tcl."""
|
|
180
|
-
import tkinter as tk #
|
|
180
|
+
import tkinter as tk # ruff:ignore[import-outside-top-level]
|
|
181
181
|
|
|
182
182
|
try:
|
|
183
183
|
if (tk_lib := tcl.eval("set tk_library")) and os.path.isdir(tk_lib):
|
|
@@ -303,8 +303,11 @@ class PythonInfo: # noqa: PLR0904
|
|
|
303
303
|
with warnings.catch_warnings(): # disable warning for PEP-632
|
|
304
304
|
warnings.simplefilter("ignore")
|
|
305
305
|
try:
|
|
306
|
-
|
|
307
|
-
from distutils
|
|
306
|
+
# ruff:ignore[import-outside-top-level]
|
|
307
|
+
from distutils import dist # ty: ignore[unresolved-import]
|
|
308
|
+
|
|
309
|
+
# ruff:ignore[import-outside-top-level]
|
|
310
|
+
from distutils.command.install import SCHEME_KEYS # ty: ignore[unresolved-import]
|
|
308
311
|
except ImportError: # pragma: no cover # if removed or not installed ignore
|
|
309
312
|
return {}
|
|
310
313
|
|
|
@@ -312,7 +315,7 @@ class PythonInfo: # noqa: PLR0904
|
|
|
312
315
|
"script_args": "--no-user-cfg",
|
|
313
316
|
}) # conf files not parsed so they do not hijack paths
|
|
314
317
|
if hasattr(sys, "_framework"): # pragma: no cover # macOS framework builds only
|
|
315
|
-
sys._framework = None #
|
|
318
|
+
sys._framework = None # ruff:ignore[private-member-access] # disable macOS static paths for framework
|
|
316
319
|
|
|
317
320
|
with warnings.catch_warnings(): # disable warning for PEP-632
|
|
318
321
|
warnings.simplefilter("ignore")
|
|
@@ -459,12 +462,12 @@ class PythonInfo: # noqa: PLR0904
|
|
|
459
462
|
|
|
460
463
|
:param cache: the cache store to clear.
|
|
461
464
|
"""
|
|
462
|
-
from ._cached_py_info import clear #
|
|
465
|
+
from ._cached_py_info import clear # ruff:ignore[import-outside-top-level]
|
|
463
466
|
|
|
464
467
|
clear(cache)
|
|
465
468
|
cls._cache_exe_discovery.clear()
|
|
466
469
|
|
|
467
|
-
def satisfies(self, spec: PythonSpec, *, impl_must_match: bool) -> bool: #
|
|
470
|
+
def satisfies(self, spec: PythonSpec, *, impl_must_match: bool) -> bool: # ruff:ignore[too-many-return-statements]
|
|
468
471
|
"""
|
|
469
472
|
Check if a given specification can be satisfied by this python interpreter instance.
|
|
470
473
|
|
|
@@ -510,7 +513,7 @@ class PythonInfo: # noqa: PLR0904
|
|
|
510
513
|
return True
|
|
511
514
|
version_info = self.version_info
|
|
512
515
|
for specifier in spec.version_specifier:
|
|
513
|
-
assert specifier.version is not None #
|
|
516
|
+
assert specifier.version is not None # ruff:ignore[assert]
|
|
514
517
|
numeric_version = specifier.version_str
|
|
515
518
|
for prefix in ("rc", "b", "a"):
|
|
516
519
|
if prefix in numeric_version:
|
|
@@ -520,7 +523,7 @@ class PythonInfo: # noqa: PLR0904
|
|
|
520
523
|
release = ".".join(str(c) for c in [version_info.major, version_info.minor, version_info.micro][:precision])
|
|
521
524
|
if (
|
|
522
525
|
version_info.releaselevel != "final"
|
|
523
|
-
and (precision == 3 or specifier.version.pre_type is not None) #
|
|
526
|
+
and (precision == 3 or specifier.version.pre_type is not None) # ruff:ignore[magic-value-comparison]
|
|
524
527
|
and (suffix := {"alpha": "a", "beta": "b", "candidate": "rc"}.get(version_info.releaselevel))
|
|
525
528
|
):
|
|
526
529
|
release = f"{release}{suffix}{version_info.serial}"
|
|
@@ -573,7 +576,7 @@ class PythonInfo: # noqa: PLR0904
|
|
|
573
576
|
return data
|
|
574
577
|
|
|
575
578
|
@classmethod
|
|
576
|
-
def from_exe( #
|
|
579
|
+
def from_exe( # ruff:ignore[too-many-arguments]
|
|
577
580
|
cls,
|
|
578
581
|
exe: str,
|
|
579
582
|
cache: PyInfoCache | None = None,
|
|
@@ -593,7 +596,7 @@ class PythonInfo: # noqa: PLR0904
|
|
|
593
596
|
:param resolve_to_host: resolve through virtualenv layers to the system interpreter.
|
|
594
597
|
:param env: environment mapping; defaults to :data:`os.environ`.
|
|
595
598
|
"""
|
|
596
|
-
from ._cached_py_info import from_exe #
|
|
599
|
+
from ._cached_py_info import from_exe # ruff:ignore[import-outside-top-level]
|
|
597
600
|
|
|
598
601
|
env = os.environ if env is None else env
|
|
599
602
|
proposed = from_exe(cls, cache, exe, env=env, raise_on_error=raise_on_error, ignore_cache=ignore_cache)
|
|
@@ -703,7 +706,7 @@ class PythonInfo: # noqa: PLR0904
|
|
|
703
706
|
msg = "failed to detect {} in {}".format("|".join(possible_names), os.pathsep.join(possible_folders))
|
|
704
707
|
raise RuntimeError(msg)
|
|
705
708
|
|
|
706
|
-
def _check_exe( #
|
|
709
|
+
def _check_exe( # ruff:ignore[too-many-arguments]
|
|
707
710
|
self,
|
|
708
711
|
cache: PyInfoCache | None,
|
|
709
712
|
folder: str,
|
|
@@ -797,7 +800,7 @@ class PythonInfo: # noqa: PLR0904
|
|
|
797
800
|
for base in possible_base:
|
|
798
801
|
lower = base.lower()
|
|
799
802
|
yield lower
|
|
800
|
-
from ._compat import fs_is_case_sensitive #
|
|
803
|
+
from ._compat import fs_is_case_sensitive # ruff:ignore[import-outside-top-level]
|
|
801
804
|
|
|
802
805
|
if fs_is_case_sensitive(): # pragma: no branch
|
|
803
806
|
if base != lower:
|
|
@@ -55,7 +55,7 @@ def _parse_version_parts(version: str) -> tuple[int | None, int | None, int | No
|
|
|
55
55
|
raise ValueError(msg)
|
|
56
56
|
if len(versions) == _MAX_VERSION_PARTS:
|
|
57
57
|
return versions[0], versions[1], versions[2]
|
|
58
|
-
if len(versions) == 2: #
|
|
58
|
+
if len(versions) == 2: # ruff:ignore[magic-value-comparison]
|
|
59
59
|
return versions[0], versions[1], None
|
|
60
60
|
version_data = versions[0]
|
|
61
61
|
major = int(str(version_data)[0])
|
|
@@ -127,7 +127,7 @@ class PythonSpec:
|
|
|
127
127
|
constraints, or ``None``.
|
|
128
128
|
"""
|
|
129
129
|
|
|
130
|
-
def __init__( #
|
|
130
|
+
def __init__( # ruff:ignore[too-many-arguments, too-many-positional-arguments]
|
|
131
131
|
self,
|
|
132
132
|
str_spec: str,
|
|
133
133
|
implementation: str | None,
|
|
@@ -233,7 +233,7 @@ class PythonSpec:
|
|
|
233
233
|
return len(item.version.release)
|
|
234
234
|
return None
|
|
235
235
|
|
|
236
|
-
def satisfies(self, spec: PythonSpec) -> bool: #
|
|
236
|
+
def satisfies(self, spec: PythonSpec) -> bool: # ruff:ignore[too-many-return-statements]
|
|
237
237
|
"""
|
|
238
238
|
Check if this spec is compatible with the given *spec* (e.g. PEP-514 on Windows).
|
|
239
239
|
|
|
@@ -92,7 +92,7 @@ class SimpleVersion:
|
|
|
92
92
|
def __hash__(self) -> int:
|
|
93
93
|
return hash((self.release, self.pre_type, self.pre_num))
|
|
94
94
|
|
|
95
|
-
def __lt__(self, other: object) -> bool: #
|
|
95
|
+
def __lt__(self, other: object) -> bool: # ruff:ignore[too-many-return-statements]
|
|
96
96
|
if not isinstance(other, SimpleVersion):
|
|
97
97
|
return NotImplemented
|
|
98
98
|
if self.release != other.release:
|
|
@@ -225,7 +225,7 @@ class SimpleSpecifier:
|
|
|
225
225
|
return False
|
|
226
226
|
if candidate < self.version:
|
|
227
227
|
return False
|
|
228
|
-
if len(self.version.release) >= 2: #
|
|
228
|
+
if len(self.version.release) >= 2: # ruff:ignore[magic-value-comparison] # pragma: no branch # SimpleVersion always has 3-part release
|
|
229
229
|
upper_parts = list(self.version.release[:-1])
|
|
230
230
|
upper_parts[-1] += 1
|
|
231
231
|
upper = SimpleVersion.from_string(".".join(str(p) for p in upper_parts))
|
|
@@ -47,7 +47,7 @@ _THREADED_TAG_RE: Final[re.Pattern[str]] = re.compile(
|
|
|
47
47
|
)
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
def enum_keys(key: Any) -> Generator[str, None, None]: #
|
|
50
|
+
def enum_keys(key: Any) -> Generator[str, None, None]: # ruff:ignore[any-type]
|
|
51
51
|
at = 0
|
|
52
52
|
while True:
|
|
53
53
|
try:
|
|
@@ -57,7 +57,7 @@ def enum_keys(key: Any) -> Generator[str, None, None]: # noqa: ANN401
|
|
|
57
57
|
at += 1
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
def get_value(key: Any, value_name: str | None) -> Any: #
|
|
60
|
+
def get_value(key: Any, value_name: str | None) -> Any: # ruff:ignore[any-type]
|
|
61
61
|
try:
|
|
62
62
|
return winreg.QueryValueEx(key, value_name)[0] # ty: ignore[unresolved-attribute]
|
|
63
63
|
except OSError:
|
|
@@ -93,7 +93,7 @@ def process_set(
|
|
|
93
93
|
def process_company(
|
|
94
94
|
hive_name: str,
|
|
95
95
|
company: str,
|
|
96
|
-
root_key: Any, #
|
|
96
|
+
root_key: Any, # ruff:ignore[any-type]
|
|
97
97
|
default_arch: int,
|
|
98
98
|
) -> Generator[_RegistrySpec, None, None]:
|
|
99
99
|
with winreg.OpenKeyEx(root_key, company) as company_key: # ty: ignore[unresolved-attribute]
|
|
@@ -103,7 +103,7 @@ def process_company(
|
|
|
103
103
|
yield spec
|
|
104
104
|
|
|
105
105
|
|
|
106
|
-
def process_tag(hive_name: str, company: str, company_key: Any, tag: str, default_arch: int) -> _RegistrySpec | None: #
|
|
106
|
+
def process_tag(hive_name: str, company: str, company_key: Any, tag: str, default_arch: int) -> _RegistrySpec | None: # ruff:ignore[any-type]
|
|
107
107
|
with winreg.OpenKeyEx(company_key, tag) as tag_key: # ty: ignore[unresolved-attribute]
|
|
108
108
|
version = load_version_data(hive_name, company, tag, tag_key)
|
|
109
109
|
if version is not None: # if failed to get version bail
|
|
@@ -120,7 +120,7 @@ def process_tag(hive_name: str, company: str, company_key: Any, tag: str, defaul
|
|
|
120
120
|
return None
|
|
121
121
|
|
|
122
122
|
|
|
123
|
-
def load_exe(hive_name: str, company: str, company_key: Any, tag: str) -> tuple[str, str | None] | None: #
|
|
123
|
+
def load_exe(hive_name: str, company: str, company_key: Any, tag: str) -> tuple[str, str | None] | None: # ruff:ignore[any-type]
|
|
124
124
|
key_path = f"{hive_name}/{company}/{tag}"
|
|
125
125
|
try:
|
|
126
126
|
with winreg.OpenKeyEx(company_key, rf"{tag}\InstallPath") as ip_key, ip_key: # ty: ignore[unresolved-attribute]
|
|
@@ -132,7 +132,7 @@ def load_exe(hive_name: str, company: str, company_key: Any, tag: str) -> tuple[
|
|
|
132
132
|
return None
|
|
133
133
|
|
|
134
134
|
|
|
135
|
-
def _resolve_exe(ip_key: Any, key_path: str) -> str | None: #
|
|
135
|
+
def _resolve_exe(ip_key: Any, key_path: str) -> str | None: # ruff:ignore[any-type]
|
|
136
136
|
if (exe := get_value(ip_key, "ExecutablePath")) is not None:
|
|
137
137
|
return exe
|
|
138
138
|
if (ip := get_value(ip_key, None)) is None:
|
|
@@ -141,7 +141,7 @@ def _resolve_exe(ip_key: Any, key_path: str) -> str | None: # noqa: ANN401
|
|
|
141
141
|
return os.path.join(ip, "python.exe")
|
|
142
142
|
|
|
143
143
|
|
|
144
|
-
def load_arch_data(hive_name: str, company: str, tag: str, tag_key: Any, default_arch: int) -> int | None: #
|
|
144
|
+
def load_arch_data(hive_name: str, company: str, tag: str, tag_key: Any, default_arch: int) -> int | None: # ruff:ignore[any-type]
|
|
145
145
|
arch_str = get_value(tag_key, "SysArchitecture")
|
|
146
146
|
if arch_str is not None:
|
|
147
147
|
key_path = f"{hive_name}/{company}/{tag}/SysArchitecture"
|
|
@@ -152,7 +152,7 @@ def load_arch_data(hive_name: str, company: str, tag: str, tag_key: Any, default
|
|
|
152
152
|
return default_arch
|
|
153
153
|
|
|
154
154
|
|
|
155
|
-
def parse_arch(arch_str: Any) -> int: #
|
|
155
|
+
def parse_arch(arch_str: Any) -> int: # ruff:ignore[any-type]
|
|
156
156
|
if isinstance(arch_str, str):
|
|
157
157
|
if match := _ARCH_RE.match(arch_str):
|
|
158
158
|
return int(next(iter(match.groups())))
|
|
@@ -166,7 +166,7 @@ def load_version_data(
|
|
|
166
166
|
hive_name: str,
|
|
167
167
|
company: str,
|
|
168
168
|
tag: str,
|
|
169
|
-
tag_key: Any, #
|
|
169
|
+
tag_key: Any, # ruff:ignore[any-type]
|
|
170
170
|
) -> tuple[int | None, int | None, int | None] | None:
|
|
171
171
|
for candidate, key_path in [
|
|
172
172
|
(get_value(tag_key, "SysVersion"), f"{hive_name}/{company}/{tag}/SysVersion"),
|
|
@@ -180,7 +180,7 @@ def load_version_data(
|
|
|
180
180
|
return None
|
|
181
181
|
|
|
182
182
|
|
|
183
|
-
def parse_version(version_str: Any) -> tuple[int | None, int | None, int | None]: #
|
|
183
|
+
def parse_version(version_str: Any) -> tuple[int | None, int | None, int | None]: # ruff:ignore[any-type]
|
|
184
184
|
if isinstance(version_str, str):
|
|
185
185
|
if match := _VERSION_RE.match(version_str):
|
|
186
186
|
g1, g2, g3 = match.groups()
|
|
@@ -195,7 +195,7 @@ def parse_version(version_str: Any) -> tuple[int | None, int | None, int | None]
|
|
|
195
195
|
raise ValueError(error)
|
|
196
196
|
|
|
197
197
|
|
|
198
|
-
def load_threaded(hive_name: str, company: str, tag: str, tag_key: Any) -> bool: #
|
|
198
|
+
def load_threaded(hive_name: str, company: str, tag: str, tag_key: Any) -> bool: # ruff:ignore[any-type]
|
|
199
199
|
display_name = get_value(tag_key, "DisplayName")
|
|
200
200
|
if display_name is not None:
|
|
201
201
|
if isinstance(display_name, str):
|
|
@@ -41,7 +41,7 @@ def main(version_str: str) -> None:
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def create_release_branch(repo: Repo, version: Version) -> tuple[Remote, Head]:
|
|
44
|
-
print("create release branch from upstream main") #
|
|
44
|
+
print("create release branch from upstream main") # ruff:ignore[print]
|
|
45
45
|
upstream = get_upstream(repo)
|
|
46
46
|
upstream.fetch()
|
|
47
47
|
branch_name = f"release-{version}"
|
|
@@ -63,71 +63,71 @@ def get_upstream(repo: Repo) -> Remote:
|
|
|
63
63
|
def push_release(repo: Repo, upstream: Remote, release_branch: Head, version: Version) -> tuple[bool, bool, bool]:
|
|
64
64
|
release_commit = release_changelog(repo, version)
|
|
65
65
|
tag = tag_release_commit(release_commit, repo, version)
|
|
66
|
-
print("push release commit") #
|
|
66
|
+
print("push release commit") # ruff:ignore[print]
|
|
67
67
|
repo.git.push(upstream.name, f"{release_branch}:main", "-f")
|
|
68
|
-
print("push release tag") #
|
|
68
|
+
print("push release tag") # ruff:ignore[print]
|
|
69
69
|
repo.git.push(upstream.name, tag, "-f")
|
|
70
70
|
create_github_release(version)
|
|
71
71
|
return True, True, True
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
def release_changelog(repo: Repo, version: Version) -> Commit:
|
|
75
|
-
print("generate release commit") #
|
|
76
|
-
check_call(["towncrier", "build", "--yes", "--version", version.public], cwd=str(ROOT_SRC_DIR)) #
|
|
77
|
-
print("format changelog with pre-commit") #
|
|
75
|
+
print("generate release commit") # ruff:ignore[print]
|
|
76
|
+
check_call(["towncrier", "build", "--yes", "--version", version.public], cwd=str(ROOT_SRC_DIR)) # ruff:ignore[start-process-with-partial-path]
|
|
77
|
+
print("format changelog with pre-commit") # ruff:ignore[print]
|
|
78
78
|
changelog_path = ROOT_SRC_DIR / "docs" / "changelog.rst"
|
|
79
79
|
try:
|
|
80
|
-
check_call(["pre-commit", "run", "--files", str(changelog_path)], cwd=str(ROOT_SRC_DIR)) #
|
|
80
|
+
check_call(["pre-commit", "run", "--files", str(changelog_path)], cwd=str(ROOT_SRC_DIR)) # ruff:ignore[start-process-with-partial-path]
|
|
81
81
|
except CalledProcessError:
|
|
82
|
-
print("pre-commit made formatting changes, staging them") #
|
|
82
|
+
print("pre-commit made formatting changes, staging them") # ruff:ignore[print]
|
|
83
83
|
repo.index.add([str(changelog_path)])
|
|
84
84
|
return repo.index.commit(f"release {version}")
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
def tag_release_commit(release_commit: Commit, repo: Repo, version: Version) -> TagReference:
|
|
88
|
-
print("tag release commit") #
|
|
88
|
+
print("tag release commit") # ruff:ignore[print]
|
|
89
89
|
version_str = str(version)
|
|
90
90
|
if version_str in {tag.name for tag in repo.tags}:
|
|
91
|
-
print(f"delete existing tag {version_str}") #
|
|
91
|
+
print(f"delete existing tag {version_str}") # ruff:ignore[print]
|
|
92
92
|
repo.delete_tag(repo.tags[version_str])
|
|
93
|
-
print(f"create tag {version_str}") #
|
|
93
|
+
print(f"create tag {version_str}") # ruff:ignore[print]
|
|
94
94
|
return repo.create_tag(version_str, ref=release_commit.hexsha, force=True)
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
def create_github_release(version: Version) -> None:
|
|
98
|
-
print("create github release") #
|
|
98
|
+
print("create github release") # ruff:ignore[print]
|
|
99
99
|
version_str = str(version)
|
|
100
100
|
try:
|
|
101
101
|
result = run(
|
|
102
|
-
["gh", "release", "create", version_str, "--title", f"v{version_str}", "--generate-notes"], #
|
|
102
|
+
["gh", "release", "create", version_str, "--title", f"v{version_str}", "--generate-notes"], # ruff:ignore[start-process-with-partial-path]
|
|
103
103
|
cwd=str(ROOT_SRC_DIR),
|
|
104
104
|
capture_output=True,
|
|
105
105
|
text=True,
|
|
106
106
|
check=True,
|
|
107
107
|
)
|
|
108
108
|
if result.stdout:
|
|
109
|
-
print(result.stdout) #
|
|
109
|
+
print(result.stdout) # ruff:ignore[print]
|
|
110
110
|
except CalledProcessError as e:
|
|
111
|
-
print(f"gh release create failed with exit code {e.returncode}") #
|
|
111
|
+
print(f"gh release create failed with exit code {e.returncode}") # ruff:ignore[print]
|
|
112
112
|
if e.stdout:
|
|
113
|
-
print(f"stdout: {e.stdout}") #
|
|
113
|
+
print(f"stdout: {e.stdout}") # ruff:ignore[print]
|
|
114
114
|
if e.stderr:
|
|
115
|
-
print(f"stderr: {e.stderr}") #
|
|
115
|
+
print(f"stderr: {e.stderr}") # ruff:ignore[print]
|
|
116
116
|
raise
|
|
117
117
|
|
|
118
118
|
|
|
119
119
|
def finalize_release(repo: Repo, upstream: Remote, release_branch: Head) -> None:
|
|
120
|
-
print("checkout main to new release and delete release branch") #
|
|
120
|
+
print("checkout main to new release and delete release branch") # ruff:ignore[print]
|
|
121
121
|
repo.heads.main.checkout()
|
|
122
122
|
repo.delete_head(release_branch, force=True)
|
|
123
|
-
print("delete remote release branch") #
|
|
123
|
+
print("delete remote release branch") # ruff:ignore[print]
|
|
124
124
|
repo.git.push(upstream.name, f":{release_branch}", "--no-verify")
|
|
125
125
|
upstream.fetch()
|
|
126
126
|
repo.git.reset("--hard", f"{upstream.name}/main")
|
|
127
|
-
print("All done!") #
|
|
127
|
+
print("All done!") # ruff:ignore[print]
|
|
128
128
|
|
|
129
129
|
|
|
130
|
-
def cleanup_failed_release( #
|
|
130
|
+
def cleanup_failed_release( # ruff:ignore[too-many-arguments]
|
|
131
131
|
repo: Repo,
|
|
132
132
|
upstream: Remote,
|
|
133
133
|
version: Version,
|
|
@@ -138,30 +138,30 @@ def cleanup_failed_release( # noqa: PLR0913
|
|
|
138
138
|
tag_pushed: bool,
|
|
139
139
|
main_pushed: bool,
|
|
140
140
|
) -> None:
|
|
141
|
-
print("Release failed! Cleaning up...") #
|
|
141
|
+
print("Release failed! Cleaning up...") # ruff:ignore[print]
|
|
142
142
|
if release_created:
|
|
143
|
-
print(f"Deleting GitHub release {version}") #
|
|
143
|
+
print(f"Deleting GitHub release {version}") # ruff:ignore[print]
|
|
144
144
|
try:
|
|
145
|
-
check_call(["gh", "release", "delete", str(version), "--yes"], cwd=str(ROOT_SRC_DIR)) #
|
|
146
|
-
except Exception as cleanup_error: #
|
|
147
|
-
print(f"Warning: Failed to delete GitHub release: {cleanup_error}") #
|
|
145
|
+
check_call(["gh", "release", "delete", str(version), "--yes"], cwd=str(ROOT_SRC_DIR)) # ruff:ignore[start-process-with-partial-path]
|
|
146
|
+
except Exception as cleanup_error: # ruff:ignore[blind-except]
|
|
147
|
+
print(f"Warning: Failed to delete GitHub release: {cleanup_error}") # ruff:ignore[print]
|
|
148
148
|
if tag_pushed:
|
|
149
|
-
print(f"Deleting remote tag {version}") #
|
|
149
|
+
print(f"Deleting remote tag {version}") # ruff:ignore[print]
|
|
150
150
|
try:
|
|
151
151
|
repo.git.push(upstream.name, f":refs/tags/{version}", "--no-verify")
|
|
152
|
-
except Exception as cleanup_error: #
|
|
153
|
-
print(f"Warning: Failed to delete remote tag: {cleanup_error}") #
|
|
152
|
+
except Exception as cleanup_error: # ruff:ignore[blind-except]
|
|
153
|
+
print(f"Warning: Failed to delete remote tag: {cleanup_error}") # ruff:ignore[print]
|
|
154
154
|
if main_pushed:
|
|
155
|
-
print(f"Reverting main to {original_main_sha[:8]}") #
|
|
155
|
+
print(f"Reverting main to {original_main_sha[:8]}") # ruff:ignore[print]
|
|
156
156
|
try:
|
|
157
157
|
repo.git.push(upstream.name, f"{original_main_sha}:main", "-f", "--no-verify")
|
|
158
|
-
except Exception as cleanup_error: #
|
|
159
|
-
print(f"Warning: Failed to revert main: {cleanup_error}") #
|
|
160
|
-
print("Deleting remote release branch") #
|
|
158
|
+
except Exception as cleanup_error: # ruff:ignore[blind-except]
|
|
159
|
+
print(f"Warning: Failed to revert main: {cleanup_error}") # ruff:ignore[print]
|
|
160
|
+
print("Deleting remote release branch") # ruff:ignore[print]
|
|
161
161
|
try:
|
|
162
162
|
repo.git.push(upstream.name, f":{release_branch}", "--no-verify")
|
|
163
|
-
except Exception as cleanup_error: #
|
|
164
|
-
print(f"Warning: Failed to delete remote branch: {cleanup_error}") #
|
|
163
|
+
except Exception as cleanup_error: # ruff:ignore[blind-except]
|
|
164
|
+
print(f"Warning: Failed to delete remote branch: {cleanup_error}") # ruff:ignore[print]
|
|
165
165
|
|
|
166
166
|
|
|
167
167
|
if __name__ == "__main__":
|
|
@@ -437,7 +437,8 @@ def test_predicate_with_fallback_specs(session_cache: DiskCache) -> None:
|
|
|
437
437
|
proposed.append(str(info.executable))
|
|
438
438
|
return len(proposed) > 1
|
|
439
439
|
|
|
440
|
-
|
|
440
|
+
threaded = "t" if current.free_threaded else ""
|
|
441
|
+
result = get_interpreter([f"{major}.{minor}{threaded}", sys.executable], [], session_cache, predicate=reject_first)
|
|
441
442
|
# rejecting the first proposal must not abort discovery; a later proposal (same or fallback spec) is accepted -
|
|
442
443
|
# on hosts where every alias resolves to one interpreter the fallback re-proposes it, so executables may match
|
|
443
444
|
assert result is not None
|
|
@@ -437,7 +437,10 @@ def test_satisfies_version_specifier_prerelease(version_info: VersionInfo, spec_
|
|
|
437
437
|
|
|
438
438
|
def test_satisfies_path_not_abs_basename_match() -> None:
|
|
439
439
|
info = copy.deepcopy(CURRENT)
|
|
440
|
-
|
|
440
|
+
# stem drops everything from the first dot, so python3.15t arrives as python3 and stops naming a free-threaded
|
|
441
|
+
# build; only the Windows .exe belongs off the end.
|
|
442
|
+
name = Path(info.original_executable).name
|
|
443
|
+
basename = name[: -len(".exe")] if name.endswith(".exe") else name
|
|
441
444
|
spec = PythonSpec.from_string_spec(basename)
|
|
442
445
|
assert info.satisfies(spec, impl_must_match=False) is True
|
|
443
446
|
|
|
@@ -44,7 +44,7 @@ def test_version_eq_different() -> None:
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
def test_version_eq_not_implemented() -> None:
|
|
47
|
-
result = SimpleVersion.from_string("3.11").__eq__("3.11") #
|
|
47
|
+
result = SimpleVersion.from_string("3.11").__eq__("3.11") # ruff:ignore[unnecessary-dunder-call]
|
|
48
48
|
assert result is NotImplemented
|
|
49
49
|
|
|
50
50
|
|
|
@@ -69,7 +69,7 @@ def test_version_lt(left: str, right: str, expected: bool) -> None:
|
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
def test_version_lt_not_implemented() -> None:
|
|
72
|
-
result = SimpleVersion.from_string("3.11").__lt__("3.12") #
|
|
72
|
+
result = SimpleVersion.from_string("3.11").__lt__("3.12") # ruff:ignore[unnecessary-dunder-call]
|
|
73
73
|
assert result is NotImplemented
|
|
74
74
|
|
|
75
75
|
|
|
@@ -83,7 +83,7 @@ def test_version_gt() -> None:
|
|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
def test_version_gt_not_implemented() -> None:
|
|
86
|
-
result = SimpleVersion.from_string("3.11").__gt__("3.11") #
|
|
86
|
+
result = SimpleVersion.from_string("3.11").__gt__("3.11") # ruff:ignore[unnecessary-dunder-call]
|
|
87
87
|
assert result is NotImplemented
|
|
88
88
|
|
|
89
89
|
|
|
@@ -198,7 +198,7 @@ def test_specifier_eq() -> None:
|
|
|
198
198
|
|
|
199
199
|
|
|
200
200
|
def test_specifier_eq_not_implemented() -> None:
|
|
201
|
-
result = SimpleSpecifier.from_string(">=3.12").__eq__(">=3.12") #
|
|
201
|
+
result = SimpleSpecifier.from_string(">=3.12").__eq__(">=3.12") # ruff:ignore[unnecessary-dunder-call]
|
|
202
202
|
assert result is NotImplemented
|
|
203
203
|
|
|
204
204
|
|
|
@@ -262,7 +262,7 @@ def test_specifier_set_eq() -> None:
|
|
|
262
262
|
|
|
263
263
|
|
|
264
264
|
def test_specifier_set_eq_not_implemented() -> None:
|
|
265
|
-
result = SimpleSpecifierSet.from_string(">=3.12").__eq__(">=3.12") #
|
|
265
|
+
result = SimpleSpecifierSet.from_string(">=3.12").__eq__(">=3.12") # ruff:ignore[unnecessary-dunder-call]
|
|
266
266
|
assert result is NotImplemented
|
|
267
267
|
|
|
268
268
|
|
|
@@ -42,7 +42,7 @@ def _load_registry_data(
|
|
|
42
42
|
loc: dict[str, object] = {}
|
|
43
43
|
glob: dict[str, object] = {"winreg": winreg}
|
|
44
44
|
mock_value_str = (Path(__file__).parent / "winreg_mock_values.py").read_text(encoding="utf-8")
|
|
45
|
-
exec(mock_value_str, glob, loc) #
|
|
45
|
+
exec(mock_value_str, glob, loc) # ruff:ignore[exec-builtin]
|
|
46
46
|
return loc["enum_collect"], loc["value_collect"], loc["key_open"], loc["hive_open"] # type: ignore[return-value]
|
|
47
47
|
|
|
48
48
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
requires = ["tox>=4.38", "tox-uv>=1.29"]
|
|
2
|
-
env_list = ["fix", "3.14", "3.13", "3.12", "3.11", "3.10", "3.9", "3.8", "type-3.8", "type-3.14", "docs", "pkg_meta"]
|
|
2
|
+
env_list = ["fix", "3.15", "3.15t", "3.14", "3.13", "3.12", "3.11", "3.10", "3.9", "3.8", "type-3.8", "type-3.14", "docs", "pkg_meta"]
|
|
3
3
|
skip_missing_interpreters = true
|
|
4
4
|
|
|
5
5
|
[env_run_base]
|
|
6
6
|
description = "run the tests with pytest"
|
|
7
7
|
package = "wheel"
|
|
8
8
|
wheel_build_env = ".pkg"
|
|
9
|
-
|
|
9
|
+
dependency_groups = ["test"]
|
|
10
10
|
pass_env = ["DIFF_AGAINST", "PYTEST_*"]
|
|
11
11
|
set_env.COVERAGE_FILE = "{work_dir}{/}.coverage.{env_name}"
|
|
12
12
|
commands = [
|
|
@@ -46,7 +46,7 @@ commands = [["ty", "check", "--output-format", "concise", "--error-on-warning",
|
|
|
46
46
|
|
|
47
47
|
[env.docs]
|
|
48
48
|
description = "build documentation"
|
|
49
|
-
|
|
49
|
+
dependency_groups = ["docs"]
|
|
50
50
|
commands = [
|
|
51
51
|
[
|
|
52
52
|
"sphinx-build",
|
|
@@ -81,5 +81,5 @@ commands = [["python", "{tox_root}/tasks/release.py", "--version", "{posargs}"]]
|
|
|
81
81
|
[env.dev]
|
|
82
82
|
description = "generate a DEV environment"
|
|
83
83
|
package = "editable"
|
|
84
|
-
|
|
84
|
+
dependency_groups = ["test"]
|
|
85
85
|
commands = [["uv", "pip", "tree"], ["python", "-c", "import sys; print(sys.executable)"]]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_discovery-1.4.4 → python_discovery-1.5.0}/tests/py_info/test_py_info_exe_based_of.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|