nva.recipe.rocket 0.1.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.
- nva_recipe_rocket-0.1.0/.github/dependabot.yml +6 -0
- nva_recipe_rocket-0.1.0/.github/workflows/release.yml +43 -0
- nva_recipe_rocket-0.1.0/.github/workflows/tests.yml +41 -0
- nva_recipe_rocket-0.1.0/.gitignore +5 -0
- nva_recipe_rocket-0.1.0/CHANGES.md +6 -0
- nva_recipe_rocket-0.1.0/LICENSE.txt +45 -0
- nva_recipe_rocket-0.1.0/PKG-INFO +113 -0
- nva_recipe_rocket-0.1.0/README.md +94 -0
- nva_recipe_rocket-0.1.0/pyproject.toml +38 -0
- nva_recipe_rocket-0.1.0/src/nva/recipe/rocket/__init__.py +314 -0
- nva_recipe_rocket-0.1.0/tests/test_rocket.py +168 -0
- nva_recipe_rocket-0.1.0/uv.lock +358 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI when a version tag (e.g. 0.1.0) is pushed.
|
|
4
|
+
# Uses PyPI trusted publishing: configure a trusted publisher for this
|
|
5
|
+
# repository, workflow "release.yml" and environment "pypi" on PyPI first.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags: ["[0-9]+.[0-9]+*"]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: astral-sh/setup-uv@v6
|
|
17
|
+
- name: Check that the tag matches the package version
|
|
18
|
+
run: |
|
|
19
|
+
version=$(uv run --no-project --python 3.12 python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
|
|
20
|
+
test "$version" = "$GITHUB_REF_NAME" || {
|
|
21
|
+
echo "Tag $GITHUB_REF_NAME does not match version $version in pyproject.toml"
|
|
22
|
+
exit 1
|
|
23
|
+
}
|
|
24
|
+
- run: uv run pytest
|
|
25
|
+
- run: uv build
|
|
26
|
+
- run: uvx twine check --strict dist/*
|
|
27
|
+
- uses: actions/upload-artifact@v4
|
|
28
|
+
with:
|
|
29
|
+
name: dist
|
|
30
|
+
path: dist/
|
|
31
|
+
|
|
32
|
+
publish:
|
|
33
|
+
needs: build
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
environment: pypi
|
|
36
|
+
permissions:
|
|
37
|
+
id-token: write
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/download-artifact@v4
|
|
40
|
+
with:
|
|
41
|
+
name: dist
|
|
42
|
+
path: dist/
|
|
43
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Python ${{ matrix.python }} / zc.buildout ${{ matrix.buildout }}
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
|
17
|
+
buildout: ["5", "6"]
|
|
18
|
+
exclude:
|
|
19
|
+
# zc.buildout 6 requires Python 3.10+
|
|
20
|
+
- python: "3.9"
|
|
21
|
+
buildout: "6"
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
- uses: astral-sh/setup-uv@v6
|
|
25
|
+
- name: Run tests
|
|
26
|
+
run: >
|
|
27
|
+
uv run --isolated --python ${{ matrix.python }}
|
|
28
|
+
--with "zc.buildout==${{ matrix.buildout }}.*"
|
|
29
|
+
pytest -v
|
|
30
|
+
|
|
31
|
+
build:
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: astral-sh/setup-uv@v6
|
|
36
|
+
- run: uv build
|
|
37
|
+
- run: uvx twine check --strict dist/*
|
|
38
|
+
- uses: actions/upload-artifact@v4
|
|
39
|
+
with:
|
|
40
|
+
name: dist
|
|
41
|
+
path: dist/
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Zope Public License (ZPL) Version 2.1
|
|
2
|
+
|
|
3
|
+
A copyright notice accompanies this license document that identifies the
|
|
4
|
+
copyright holders.
|
|
5
|
+
|
|
6
|
+
This license has been certified as open source. It has also been designated as
|
|
7
|
+
GPL compatible by the Free Software Foundation (FSF).
|
|
8
|
+
|
|
9
|
+
Redistribution and use in source and binary forms, with or without
|
|
10
|
+
modification, are permitted provided that the following conditions are met:
|
|
11
|
+
|
|
12
|
+
1. Redistributions in source code must retain the accompanying copyright
|
|
13
|
+
notice, this list of conditions, and the following disclaimer.
|
|
14
|
+
|
|
15
|
+
2. Redistributions in binary form must reproduce the accompanying copyright
|
|
16
|
+
notice, this list of conditions, and the following disclaimer in the
|
|
17
|
+
documentation and/or other materials provided with the distribution.
|
|
18
|
+
|
|
19
|
+
3. Names of the copyright holders must not be used to endorse or promote
|
|
20
|
+
products derived from this software without prior written permission from
|
|
21
|
+
the copyright holders.
|
|
22
|
+
|
|
23
|
+
4. The right to distribute this software or to use it for any purpose does not
|
|
24
|
+
give you the right to use Servicemarks (sm) or Trademarks (tm) of the
|
|
25
|
+
copyright holders. Use of them is covered by separate agreement with the
|
|
26
|
+
copyright holders.
|
|
27
|
+
|
|
28
|
+
5. If any files are modified, you must cause the modified files to carry
|
|
29
|
+
prominent notices stating that you changed the files and the date of any
|
|
30
|
+
change.
|
|
31
|
+
|
|
32
|
+
Disclaimer
|
|
33
|
+
|
|
34
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
|
|
35
|
+
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
36
|
+
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
37
|
+
EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
38
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
39
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
40
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
41
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
42
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
43
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
44
|
+
|
|
45
|
+
Copyright (c) 2026 Novareto
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: nva.recipe.rocket
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: zc.buildout extension: build develop eggs in parallel, without build isolation, and reuse unchanged ones
|
|
5
|
+
Project-URL: Homepage, https://github.com/novareto/nva.recipe.rocket
|
|
6
|
+
Project-URL: Issues, https://github.com/novareto/nva.recipe.rocket/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/novareto/nva.recipe.rocket/blob/main/CHANGES.md
|
|
8
|
+
Author-email: Novareto <ck@novareto.de>
|
|
9
|
+
License: ZPL-2.1
|
|
10
|
+
License-File: LICENSE.txt
|
|
11
|
+
Keywords: buildout,develop,extension,mr.developer,performance
|
|
12
|
+
Classifier: Framework :: Buildout
|
|
13
|
+
Classifier: Framework :: Buildout :: Extension
|
|
14
|
+
Classifier: License :: OSI Approved :: Zope Public License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Requires-Dist: zc-buildout>=5
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# nva.recipe.rocket
|
|
21
|
+
|
|
22
|
+
[](https://github.com/novareto/nva.recipe.rocket/actions/workflows/tests.yml)
|
|
23
|
+
|
|
24
|
+
A [zc.buildout](https://github.com/buildout/buildout) extension that makes the
|
|
25
|
+
**develop step** fast.
|
|
26
|
+
|
|
27
|
+
Since zc.buildout 5, every develop egg — every `develop =` entry and every
|
|
28
|
+
[mr.developer](https://pypi.org/project/mr.developer/) auto-checkout — is
|
|
29
|
+
installed with `pip install -e` on **every** buildout run: one after the
|
|
30
|
+
other, each in a fresh isolated build environment (pip installs setuptools
|
|
31
|
+
into a temporary venv first). With 20+ checkouts that alone takes 40+ seconds,
|
|
32
|
+
even when nothing changed.
|
|
33
|
+
|
|
34
|
+
`nva.recipe.rocket` replaces that step:
|
|
35
|
+
|
|
36
|
+
- **Parallel** — develop eggs are built concurrently, one worker per CPU.
|
|
37
|
+
- **No build isolation** — `pip install -e --no-build-isolation` uses the
|
|
38
|
+
setuptools buildout already runs with. If that fails for a package (for
|
|
39
|
+
example its build backend, like hatchling, is not installed), only that
|
|
40
|
+
package is retried with isolation.
|
|
41
|
+
- **Cache** — the files a develop egg generates in `develop-eggs/` are cached.
|
|
42
|
+
On the next run they are copied back instead of rebuilt, as long as the
|
|
43
|
+
package's `setup.py`, `setup.cfg`, `pyproject.toml` and its top-level
|
|
44
|
+
package layout are unchanged. Code changes never need a rebuild — editable
|
|
45
|
+
installs point at the source directory.
|
|
46
|
+
|
|
47
|
+
Measured on a project with 22 mr.developer checkouts:
|
|
48
|
+
|
|
49
|
+
| develop step | time |
|
|
50
|
+
|---------------------------------------|-------|
|
|
51
|
+
| zc.buildout 6, plain | ~44 s |
|
|
52
|
+
| without build isolation | ~18 s |
|
|
53
|
+
| + parallel (10 workers) | ~5 s |
|
|
54
|
+
| + cache, nothing changed | < 1 s |
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
```ini
|
|
59
|
+
[buildout]
|
|
60
|
+
extensions =
|
|
61
|
+
mr.developer
|
|
62
|
+
nva.recipe.rocket
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The order of extensions does not matter. Requires zc.buildout 5 or newer.
|
|
66
|
+
|
|
67
|
+
## Options
|
|
68
|
+
|
|
69
|
+
All options go into the `[buildout]` section and can be set on the command
|
|
70
|
+
line, e.g. `bin/buildout buildout:rocket-cache=false`.
|
|
71
|
+
|
|
72
|
+
| option | default | meaning |
|
|
73
|
+
|---------------------------|-----------------------|---------|
|
|
74
|
+
| `rocket-workers` | number of CPUs | parallel builds; `1` builds sequentially |
|
|
75
|
+
| `rocket-build-isolation` | `false` | `true` builds with pip build isolation, like plain buildout |
|
|
76
|
+
| `rocket-cache` | `true` | reuse the files of unchanged develop eggs |
|
|
77
|
+
| `rocket-cache-directory` | `${buildout:parts-directory}/.rocket` | where the cache lives |
|
|
78
|
+
|
|
79
|
+
## When is a develop egg rebuilt?
|
|
80
|
+
|
|
81
|
+
The cache key of a develop egg is made from:
|
|
82
|
+
|
|
83
|
+
- the contents of `setup.py`, `setup.cfg` and `pyproject.toml`,
|
|
84
|
+
- the names of the top-level packages and modules (flat layout and src
|
|
85
|
+
layout, two levels deep for namespace packages) and the `*.egg-info`
|
|
86
|
+
directory,
|
|
87
|
+
- the Python interpreter, the zc.buildout, setuptools and pip versions,
|
|
88
|
+
- the `rocket-build-isolation` setting.
|
|
89
|
+
|
|
90
|
+
Anything else that affects the generated metadata is **not** seen, for
|
|
91
|
+
example a version computed from git tags (setuptools-scm). Run once with
|
|
92
|
+
`buildout:rocket-cache=false`, or delete `parts/.rocket`, to force a rebuild.
|
|
93
|
+
|
|
94
|
+
## Other things that make buildout slow
|
|
95
|
+
|
|
96
|
+
Not handled by this extension, but worth checking in the buildout output:
|
|
97
|
+
|
|
98
|
+
- `Scanning index of all packages (this may take a while)` — an unpinned
|
|
99
|
+
package was not found on its index page, so setuptools downloads and parses
|
|
100
|
+
the whole PyPI `/simple/` root page (~1 million links), once per part. Pin
|
|
101
|
+
the package listed in `Couldn't retrieve index page for ...`.
|
|
102
|
+
- `Upgraded: setuptools version ...; Restarting.` on every run — the
|
|
103
|
+
setuptools pinned in `[versions]` differs from the one installed in the
|
|
104
|
+
virtualenv that runs buildout. Make them match.
|
|
105
|
+
- `PIP_NO_BUILD_ISOLATION=0` also speeds up plain buildout (yes, `0`: pip's
|
|
106
|
+
environment variable is inverted for historical reasons).
|
|
107
|
+
|
|
108
|
+
## Development
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
uv sync
|
|
112
|
+
uv run pytest
|
|
113
|
+
```
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# nva.recipe.rocket
|
|
2
|
+
|
|
3
|
+
[](https://github.com/novareto/nva.recipe.rocket/actions/workflows/tests.yml)
|
|
4
|
+
|
|
5
|
+
A [zc.buildout](https://github.com/buildout/buildout) extension that makes the
|
|
6
|
+
**develop step** fast.
|
|
7
|
+
|
|
8
|
+
Since zc.buildout 5, every develop egg — every `develop =` entry and every
|
|
9
|
+
[mr.developer](https://pypi.org/project/mr.developer/) auto-checkout — is
|
|
10
|
+
installed with `pip install -e` on **every** buildout run: one after the
|
|
11
|
+
other, each in a fresh isolated build environment (pip installs setuptools
|
|
12
|
+
into a temporary venv first). With 20+ checkouts that alone takes 40+ seconds,
|
|
13
|
+
even when nothing changed.
|
|
14
|
+
|
|
15
|
+
`nva.recipe.rocket` replaces that step:
|
|
16
|
+
|
|
17
|
+
- **Parallel** — develop eggs are built concurrently, one worker per CPU.
|
|
18
|
+
- **No build isolation** — `pip install -e --no-build-isolation` uses the
|
|
19
|
+
setuptools buildout already runs with. If that fails for a package (for
|
|
20
|
+
example its build backend, like hatchling, is not installed), only that
|
|
21
|
+
package is retried with isolation.
|
|
22
|
+
- **Cache** — the files a develop egg generates in `develop-eggs/` are cached.
|
|
23
|
+
On the next run they are copied back instead of rebuilt, as long as the
|
|
24
|
+
package's `setup.py`, `setup.cfg`, `pyproject.toml` and its top-level
|
|
25
|
+
package layout are unchanged. Code changes never need a rebuild — editable
|
|
26
|
+
installs point at the source directory.
|
|
27
|
+
|
|
28
|
+
Measured on a project with 22 mr.developer checkouts:
|
|
29
|
+
|
|
30
|
+
| develop step | time |
|
|
31
|
+
|---------------------------------------|-------|
|
|
32
|
+
| zc.buildout 6, plain | ~44 s |
|
|
33
|
+
| without build isolation | ~18 s |
|
|
34
|
+
| + parallel (10 workers) | ~5 s |
|
|
35
|
+
| + cache, nothing changed | < 1 s |
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
```ini
|
|
40
|
+
[buildout]
|
|
41
|
+
extensions =
|
|
42
|
+
mr.developer
|
|
43
|
+
nva.recipe.rocket
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The order of extensions does not matter. Requires zc.buildout 5 or newer.
|
|
47
|
+
|
|
48
|
+
## Options
|
|
49
|
+
|
|
50
|
+
All options go into the `[buildout]` section and can be set on the command
|
|
51
|
+
line, e.g. `bin/buildout buildout:rocket-cache=false`.
|
|
52
|
+
|
|
53
|
+
| option | default | meaning |
|
|
54
|
+
|---------------------------|-----------------------|---------|
|
|
55
|
+
| `rocket-workers` | number of CPUs | parallel builds; `1` builds sequentially |
|
|
56
|
+
| `rocket-build-isolation` | `false` | `true` builds with pip build isolation, like plain buildout |
|
|
57
|
+
| `rocket-cache` | `true` | reuse the files of unchanged develop eggs |
|
|
58
|
+
| `rocket-cache-directory` | `${buildout:parts-directory}/.rocket` | where the cache lives |
|
|
59
|
+
|
|
60
|
+
## When is a develop egg rebuilt?
|
|
61
|
+
|
|
62
|
+
The cache key of a develop egg is made from:
|
|
63
|
+
|
|
64
|
+
- the contents of `setup.py`, `setup.cfg` and `pyproject.toml`,
|
|
65
|
+
- the names of the top-level packages and modules (flat layout and src
|
|
66
|
+
layout, two levels deep for namespace packages) and the `*.egg-info`
|
|
67
|
+
directory,
|
|
68
|
+
- the Python interpreter, the zc.buildout, setuptools and pip versions,
|
|
69
|
+
- the `rocket-build-isolation` setting.
|
|
70
|
+
|
|
71
|
+
Anything else that affects the generated metadata is **not** seen, for
|
|
72
|
+
example a version computed from git tags (setuptools-scm). Run once with
|
|
73
|
+
`buildout:rocket-cache=false`, or delete `parts/.rocket`, to force a rebuild.
|
|
74
|
+
|
|
75
|
+
## Other things that make buildout slow
|
|
76
|
+
|
|
77
|
+
Not handled by this extension, but worth checking in the buildout output:
|
|
78
|
+
|
|
79
|
+
- `Scanning index of all packages (this may take a while)` — an unpinned
|
|
80
|
+
package was not found on its index page, so setuptools downloads and parses
|
|
81
|
+
the whole PyPI `/simple/` root page (~1 million links), once per part. Pin
|
|
82
|
+
the package listed in `Couldn't retrieve index page for ...`.
|
|
83
|
+
- `Upgraded: setuptools version ...; Restarting.` on every run — the
|
|
84
|
+
setuptools pinned in `[versions]` differs from the one installed in the
|
|
85
|
+
virtualenv that runs buildout. Make them match.
|
|
86
|
+
- `PIP_NO_BUILD_ISOLATION=0` also speeds up plain buildout (yes, `0`: pip's
|
|
87
|
+
environment variable is inverted for historical reasons).
|
|
88
|
+
|
|
89
|
+
## Development
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
uv sync
|
|
93
|
+
uv run pytest
|
|
94
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "nva.recipe.rocket"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "zc.buildout extension: build develop eggs in parallel, without build isolation, and reuse unchanged ones"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "ZPL-2.1" }
|
|
11
|
+
license-files = ["LICENSE.txt"]
|
|
12
|
+
requires-python = ">=3.9"
|
|
13
|
+
authors = [{ name = "Novareto", email = "ck@novareto.de" }]
|
|
14
|
+
keywords = ["buildout", "extension", "develop", "mr.developer", "performance"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Framework :: Buildout",
|
|
17
|
+
"Framework :: Buildout :: Extension",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"License :: OSI Approved :: Zope Public License",
|
|
20
|
+
]
|
|
21
|
+
dependencies = ["zc.buildout>=5"]
|
|
22
|
+
|
|
23
|
+
[project.urls]
|
|
24
|
+
Homepage = "https://github.com/novareto/nva.recipe.rocket"
|
|
25
|
+
Issues = "https://github.com/novareto/nva.recipe.rocket/issues"
|
|
26
|
+
Changelog = "https://github.com/novareto/nva.recipe.rocket/blob/main/CHANGES.md"
|
|
27
|
+
|
|
28
|
+
[project.entry-points."zc.buildout.extension"]
|
|
29
|
+
default = "nva.recipe.rocket:extension"
|
|
30
|
+
|
|
31
|
+
[dependency-groups]
|
|
32
|
+
dev = ["pytest", "setuptools<81", "pip"]
|
|
33
|
+
|
|
34
|
+
[tool.hatch.build.targets.wheel]
|
|
35
|
+
packages = ["src/nva"]
|
|
36
|
+
|
|
37
|
+
[tool.pytest.ini_options]
|
|
38
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"""zc.buildout extension that speeds up the ``develop`` step.
|
|
2
|
+
|
|
3
|
+
zc.buildout 5+ runs ``pip install -e`` for every develop egg (for example
|
|
4
|
+
every mr.developer auto-checkout) on every run, one after the other, each in
|
|
5
|
+
a fresh isolated build environment. This extension replaces that step:
|
|
6
|
+
|
|
7
|
+
* develop eggs are built in parallel (``rocket-workers``),
|
|
8
|
+
* builds run without pip build isolation, falling back to an isolated build
|
|
9
|
+
per package if that fails (``rocket-build-isolation``),
|
|
10
|
+
* the generated files of every develop egg are cached and restored as long
|
|
11
|
+
as its packaging metadata did not change (``rocket-cache``).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import glob
|
|
15
|
+
import hashlib
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
import shutil
|
|
19
|
+
import subprocess
|
|
20
|
+
import sys
|
|
21
|
+
import tempfile
|
|
22
|
+
import threading
|
|
23
|
+
import time
|
|
24
|
+
import types
|
|
25
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
26
|
+
from dataclasses import dataclass
|
|
27
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
import zc.buildout.easy_install as easy_install
|
|
31
|
+
|
|
32
|
+
logger = logging.getLogger("nva.recipe.rocket")
|
|
33
|
+
|
|
34
|
+
#: Bump to invalidate all existing cache entries.
|
|
35
|
+
CACHE_FORMAT = "1"
|
|
36
|
+
|
|
37
|
+
#: Files whose content decides whether a develop egg must be rebuilt.
|
|
38
|
+
KEY_FILES = ("setup.py", "setup.cfg", "pyproject.toml")
|
|
39
|
+
|
|
40
|
+
#: Marker written into a cache entry once it is complete.
|
|
41
|
+
COMPLETE = ".rocket-complete"
|
|
42
|
+
|
|
43
|
+
_local = threading.local()
|
|
44
|
+
_get_subprocess_output = easy_install.get_subprocess_output
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class NoIsolationFailed(Exception):
|
|
48
|
+
"""A build without build isolation failed; retry with isolation."""
|
|
49
|
+
|
|
50
|
+
def __init__(self, output):
|
|
51
|
+
super().__init__("build without isolation failed")
|
|
52
|
+
self.output = output
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _bool(value):
|
|
56
|
+
return value.strip().lower() in ("true", "yes", "on", "1")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass
|
|
60
|
+
class Settings:
|
|
61
|
+
workers: int
|
|
62
|
+
build_isolation: bool
|
|
63
|
+
cache: bool
|
|
64
|
+
cache_directory: Path
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def from_buildout(cls, buildout):
|
|
68
|
+
options = buildout["buildout"]
|
|
69
|
+
workers = int(options.get("rocket-workers", "0") or 0)
|
|
70
|
+
if workers < 1:
|
|
71
|
+
workers = os.cpu_count() or 1
|
|
72
|
+
cache_directory = options.get("rocket-cache-directory") or os.path.join(
|
|
73
|
+
options["parts-directory"], ".rocket"
|
|
74
|
+
)
|
|
75
|
+
return cls(
|
|
76
|
+
workers=workers,
|
|
77
|
+
build_isolation=_bool(options.get("rocket-build-isolation", "false")),
|
|
78
|
+
cache=_bool(options.get("rocket-cache", "true")),
|
|
79
|
+
cache_directory=Path(cache_directory),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_subprocess_output(args, **kw):
|
|
84
|
+
"""Wrap buildout's helper to build without isolation in worker threads.
|
|
85
|
+
|
|
86
|
+
Only the develop workers set the thread-local flag, so regular egg
|
|
87
|
+
installs in the main thread are left alone. A failure is raised as
|
|
88
|
+
:class:`NoIsolationFailed` without printing pip's output, because the
|
|
89
|
+
build is retried with isolation.
|
|
90
|
+
"""
|
|
91
|
+
if not getattr(_local, "no_isolation", False):
|
|
92
|
+
return _get_subprocess_output(args, **kw)
|
|
93
|
+
args = list(args)
|
|
94
|
+
args.insert(args.index("install") + 1, "--no-build-isolation")
|
|
95
|
+
result = subprocess.run(
|
|
96
|
+
args, **kw, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
|
97
|
+
)
|
|
98
|
+
output = result.stdout.decode("utf-8", "replace")
|
|
99
|
+
if result.returncode:
|
|
100
|
+
raise NoIsolationFailed(output)
|
|
101
|
+
return output
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _project_directory(setup):
|
|
105
|
+
if not os.path.isdir(setup):
|
|
106
|
+
setup = os.path.dirname(setup)
|
|
107
|
+
return Path(setup).expanduser().resolve()
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _listing(directory):
|
|
111
|
+
"""Names that influence an editable install: top-level packages/modules.
|
|
112
|
+
|
|
113
|
+
Covers the flat layout and the src layout two levels deep (namespace
|
|
114
|
+
packages), plus the ``*.egg-info`` directory setuptools writes there.
|
|
115
|
+
"""
|
|
116
|
+
names = []
|
|
117
|
+
for base in (directory, directory / "src"):
|
|
118
|
+
if not base.is_dir():
|
|
119
|
+
continue
|
|
120
|
+
for entry in sorted(base.iterdir()):
|
|
121
|
+
if entry.name.startswith(".") or entry.name == "__pycache__":
|
|
122
|
+
continue
|
|
123
|
+
if entry.is_dir():
|
|
124
|
+
names.append(str(entry.relative_to(directory)) + "/")
|
|
125
|
+
if base.name == "src":
|
|
126
|
+
names.extend(
|
|
127
|
+
str(sub.relative_to(directory)) + "/"
|
|
128
|
+
for sub in sorted(entry.iterdir())
|
|
129
|
+
if sub.is_dir() and sub.name != "__pycache__"
|
|
130
|
+
)
|
|
131
|
+
elif entry.suffix == ".py":
|
|
132
|
+
names.append(str(entry.relative_to(directory)))
|
|
133
|
+
return names
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _dist_version(name):
|
|
137
|
+
try:
|
|
138
|
+
return version(name)
|
|
139
|
+
except PackageNotFoundError:
|
|
140
|
+
return ""
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def cache_key(directory, settings):
|
|
144
|
+
digest = hashlib.sha256()
|
|
145
|
+
|
|
146
|
+
def add(*parts):
|
|
147
|
+
for part in parts:
|
|
148
|
+
digest.update(part if isinstance(part, bytes) else part.encode())
|
|
149
|
+
digest.update(b"\0")
|
|
150
|
+
|
|
151
|
+
add(CACHE_FORMAT, sys.executable, sys.version, str(directory))
|
|
152
|
+
add(*(_dist_version(n) for n in ("zc.buildout", "setuptools", "pip")))
|
|
153
|
+
add(str(settings.build_isolation))
|
|
154
|
+
for name in KEY_FILES:
|
|
155
|
+
path = directory / name
|
|
156
|
+
add(name, path.read_bytes() if path.is_file() else b"-")
|
|
157
|
+
add(*_listing(directory))
|
|
158
|
+
return digest.hexdigest()
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _entry_prefix(directory):
|
|
162
|
+
path_hash = hashlib.sha256(str(directory).encode()).hexdigest()[:8]
|
|
163
|
+
return f"{directory.name}-{path_hash}-"
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _copy_into(source, dest):
|
|
167
|
+
"""Copy the generated files from ``source`` into ``dest``."""
|
|
168
|
+
copied = []
|
|
169
|
+
for entry in sorted(os.listdir(source)):
|
|
170
|
+
if entry.startswith(".rocket"):
|
|
171
|
+
continue
|
|
172
|
+
src, target = os.path.join(source, entry), os.path.join(dest, entry)
|
|
173
|
+
if os.path.isdir(target) and not os.path.islink(target):
|
|
174
|
+
shutil.rmtree(target)
|
|
175
|
+
elif os.path.lexists(target):
|
|
176
|
+
os.remove(target)
|
|
177
|
+
if os.path.isdir(src):
|
|
178
|
+
shutil.copytree(src, target, symlinks=True)
|
|
179
|
+
else:
|
|
180
|
+
shutil.copy2(src, target)
|
|
181
|
+
copied.append(target)
|
|
182
|
+
return copied
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _build(setup, staging, settings):
|
|
186
|
+
if not settings.build_isolation:
|
|
187
|
+
_local.no_isolation = True
|
|
188
|
+
try:
|
|
189
|
+
easy_install.develop(setup, str(staging))
|
|
190
|
+
return
|
|
191
|
+
except NoIsolationFailed as error:
|
|
192
|
+
logger.info(
|
|
193
|
+
"Building %r without build isolation failed, "
|
|
194
|
+
"retrying with isolation.",
|
|
195
|
+
setup,
|
|
196
|
+
)
|
|
197
|
+
logger.debug(error.output)
|
|
198
|
+
for entry in staging.iterdir():
|
|
199
|
+
if entry.is_dir():
|
|
200
|
+
shutil.rmtree(entry)
|
|
201
|
+
else:
|
|
202
|
+
entry.unlink()
|
|
203
|
+
finally:
|
|
204
|
+
_local.no_isolation = False
|
|
205
|
+
easy_install.develop(setup, str(staging))
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def develop_one(setup, dest, settings):
|
|
209
|
+
"""Develop one egg into ``dest``; return True if it came from the cache."""
|
|
210
|
+
directory = _project_directory(setup)
|
|
211
|
+
prefix = _entry_prefix(directory)
|
|
212
|
+
cache_directory = settings.cache_directory
|
|
213
|
+
cache_directory.mkdir(parents=True, exist_ok=True)
|
|
214
|
+
|
|
215
|
+
if settings.cache:
|
|
216
|
+
entry = cache_directory / (prefix + cache_key(directory, settings)[:16])
|
|
217
|
+
if (entry / COMPLETE).is_file():
|
|
218
|
+
_copy_into(entry, dest)
|
|
219
|
+
return True
|
|
220
|
+
|
|
221
|
+
staging = Path(tempfile.mkdtemp(prefix=".tmp-" + prefix, dir=cache_directory))
|
|
222
|
+
try:
|
|
223
|
+
_build(setup, staging, settings)
|
|
224
|
+
_copy_into(staging, dest)
|
|
225
|
+
if settings.cache:
|
|
226
|
+
# Key again: the build may have created the *.egg-info directory.
|
|
227
|
+
entry = cache_directory / (prefix + cache_key(directory, settings)[:16])
|
|
228
|
+
for old in cache_directory.glob(prefix + "*"):
|
|
229
|
+
shutil.rmtree(old, ignore_errors=True)
|
|
230
|
+
(staging / COMPLETE).write_text(str(directory) + "\n")
|
|
231
|
+
staging.rename(entry)
|
|
232
|
+
finally:
|
|
233
|
+
if staging.exists():
|
|
234
|
+
shutil.rmtree(staging, ignore_errors=True)
|
|
235
|
+
return False
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def _develop(self, settings):
|
|
239
|
+
"""Replacement for ``zc.buildout.buildout.Buildout._develop``."""
|
|
240
|
+
__doing__ = "Processing directories listed in the develop option" # noqa
|
|
241
|
+
|
|
242
|
+
develop = self["buildout"].get("develop")
|
|
243
|
+
if not develop:
|
|
244
|
+
return ""
|
|
245
|
+
|
|
246
|
+
dest = self["buildout"]["develop-eggs-directory"]
|
|
247
|
+
old_files = os.listdir(dest)
|
|
248
|
+
|
|
249
|
+
setups = []
|
|
250
|
+
for setup in develop.split():
|
|
251
|
+
setup = self._buildout_path(setup)
|
|
252
|
+
files = glob.glob(setup)
|
|
253
|
+
if not files:
|
|
254
|
+
self._logger.warning("Couldn't develop %r (not found)", setup)
|
|
255
|
+
setups.extend(sorted(files))
|
|
256
|
+
|
|
257
|
+
here = os.getcwd()
|
|
258
|
+
started = time.monotonic()
|
|
259
|
+
cached = 0
|
|
260
|
+
pool = ThreadPoolExecutor(max_workers=settings.workers)
|
|
261
|
+
try:
|
|
262
|
+
try:
|
|
263
|
+
futures = [
|
|
264
|
+
(setup, pool.submit(develop_one, setup, dest, settings))
|
|
265
|
+
for setup in setups
|
|
266
|
+
]
|
|
267
|
+
for setup, future in futures:
|
|
268
|
+
if future.result():
|
|
269
|
+
cached += 1
|
|
270
|
+
self._logger.info("Develop: %r (cached)", setup)
|
|
271
|
+
else:
|
|
272
|
+
self._logger.info("Develop: %r", setup)
|
|
273
|
+
pool.shutdown()
|
|
274
|
+
except Exception:
|
|
275
|
+
pool.shutdown(cancel_futures=True)
|
|
276
|
+
# Roll back, like buildout does: remove any files we created.
|
|
277
|
+
self._sanity_check_develop_eggs_files(dest, old_files)
|
|
278
|
+
self._uninstall(
|
|
279
|
+
"\n".join(
|
|
280
|
+
os.path.join(dest, f)
|
|
281
|
+
for f in os.listdir(dest)
|
|
282
|
+
if f not in old_files
|
|
283
|
+
)
|
|
284
|
+
)
|
|
285
|
+
raise
|
|
286
|
+
|
|
287
|
+
self._sanity_check_develop_eggs_files(dest, old_files)
|
|
288
|
+
logger.info(
|
|
289
|
+
"Developed %d eggs in %.1fs (%d built, %d cached, %d workers).",
|
|
290
|
+
len(setups),
|
|
291
|
+
time.monotonic() - started,
|
|
292
|
+
len(setups) - cached,
|
|
293
|
+
cached,
|
|
294
|
+
settings.workers,
|
|
295
|
+
)
|
|
296
|
+
return "\n".join(
|
|
297
|
+
sorted(os.path.join(dest, f) for f in os.listdir(dest) if f not in old_files)
|
|
298
|
+
)
|
|
299
|
+
finally:
|
|
300
|
+
os.chdir(here)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def extension(buildout):
|
|
304
|
+
"""Entry point for ``extensions = nva.recipe.rocket``."""
|
|
305
|
+
if not hasattr(easy_install, "call_pip_install"):
|
|
306
|
+
logger.warning(
|
|
307
|
+
"nva.recipe.rocket needs zc.buildout 5 or newer; not activated."
|
|
308
|
+
)
|
|
309
|
+
return
|
|
310
|
+
settings = Settings.from_buildout(buildout)
|
|
311
|
+
easy_install.get_subprocess_output = get_subprocess_output
|
|
312
|
+
buildout._develop = types.MethodType(
|
|
313
|
+
lambda self: _develop(self, settings), buildout
|
|
314
|
+
)
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import textwrap
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
import zc.buildout.buildout
|
|
6
|
+
import zc.buildout.configparser
|
|
7
|
+
import zc.buildout.easy_install as easy_install
|
|
8
|
+
|
|
9
|
+
import nva.recipe.rocket as rocket
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def make_package(base, name, src_layout=False):
|
|
13
|
+
package = base / name
|
|
14
|
+
code = package / "src" / name if src_layout else package / name
|
|
15
|
+
code.mkdir(parents=True)
|
|
16
|
+
(code / "__init__.py").write_text("VALUE = %r\n" % name)
|
|
17
|
+
(package / "setup.py").write_text(
|
|
18
|
+
textwrap.dedent(
|
|
19
|
+
f"""\
|
|
20
|
+
from setuptools import setup, find_packages
|
|
21
|
+
setup(
|
|
22
|
+
name={name!r},
|
|
23
|
+
version="1.0",
|
|
24
|
+
packages=find_packages({'"src"' if src_layout else ''}),
|
|
25
|
+
{'package_dir={"": "src"},' if src_layout else ''}
|
|
26
|
+
)
|
|
27
|
+
"""
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
return package
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@pytest.fixture
|
|
34
|
+
def project(tmp_path):
|
|
35
|
+
make_package(tmp_path, "pkga")
|
|
36
|
+
make_package(tmp_path, "pkgb", src_layout=True)
|
|
37
|
+
(tmp_path / "buildout.cfg").write_text(
|
|
38
|
+
textwrap.dedent(
|
|
39
|
+
"""\
|
|
40
|
+
[buildout]
|
|
41
|
+
develop = pkga pkgb
|
|
42
|
+
parts =
|
|
43
|
+
offline = true
|
|
44
|
+
newest = false
|
|
45
|
+
"""
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
return tmp_path
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@pytest.fixture
|
|
52
|
+
def develop_calls(monkeypatch):
|
|
53
|
+
calls = []
|
|
54
|
+
original = easy_install.develop
|
|
55
|
+
|
|
56
|
+
def develop(setup, dest, *args, **kw):
|
|
57
|
+
calls.append(os.path.basename(setup))
|
|
58
|
+
return original(setup, dest, *args, **kw)
|
|
59
|
+
|
|
60
|
+
monkeypatch.setattr(easy_install, "develop", develop)
|
|
61
|
+
return calls
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def run_buildout(project, *options):
|
|
65
|
+
"""Run ``bin/buildout`` in-process; options look like ``section:key=value``."""
|
|
66
|
+
cloptions = []
|
|
67
|
+
for option in options:
|
|
68
|
+
section, assignment = option.split(":", 1)
|
|
69
|
+
cloptions.append((section, *assignment.split("=", 1)))
|
|
70
|
+
cwd = os.getcwd()
|
|
71
|
+
os.chdir(project)
|
|
72
|
+
try:
|
|
73
|
+
buildout = zc.buildout.buildout.Buildout(
|
|
74
|
+
str(project / "buildout.cfg"), cloptions, use_user_defaults=False
|
|
75
|
+
)
|
|
76
|
+
rocket.extension(buildout)
|
|
77
|
+
buildout.install([])
|
|
78
|
+
finally:
|
|
79
|
+
os.chdir(cwd)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def installed_develop_eggs(project):
|
|
83
|
+
with open(project / ".installed.cfg") as fp:
|
|
84
|
+
sections = zc.buildout.configparser.parse(fp, ".installed.cfg")
|
|
85
|
+
return sections["buildout"]["installed_develop_eggs"].split()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_builds_then_reuses_cache(project, develop_calls):
|
|
89
|
+
run_buildout(project)
|
|
90
|
+
assert sorted(develop_calls) == ["pkga", "pkgb"]
|
|
91
|
+
first = installed_develop_eggs(project)
|
|
92
|
+
assert any("pkga" in p for p in first) and any("pkgb" in p for p in first)
|
|
93
|
+
|
|
94
|
+
develop_calls.clear()
|
|
95
|
+
run_buildout(project)
|
|
96
|
+
assert develop_calls == []
|
|
97
|
+
# Buildout removed the old files before developing; they are restored.
|
|
98
|
+
assert installed_develop_eggs(project) == first
|
|
99
|
+
assert all(os.path.exists(p) for p in first)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_changed_metadata_rebuilds_only_that_package(project, develop_calls):
|
|
103
|
+
run_buildout(project)
|
|
104
|
+
develop_calls.clear()
|
|
105
|
+
|
|
106
|
+
setup_py = project / "pkga" / "setup.py"
|
|
107
|
+
setup_py.write_text(setup_py.read_text().replace('"1.0"', '"1.1"'))
|
|
108
|
+
run_buildout(project)
|
|
109
|
+
assert develop_calls == ["pkga"]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def test_new_top_level_package_rebuilds(project, develop_calls):
|
|
113
|
+
run_buildout(project)
|
|
114
|
+
develop_calls.clear()
|
|
115
|
+
|
|
116
|
+
(project / "pkgb" / "src" / "pkgb_extra").mkdir()
|
|
117
|
+
run_buildout(project)
|
|
118
|
+
assert develop_calls == ["pkgb"]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def test_cache_can_be_disabled(project, develop_calls):
|
|
122
|
+
run_buildout(project, "buildout:rocket-cache=false")
|
|
123
|
+
run_buildout(project, "buildout:rocket-cache=false")
|
|
124
|
+
assert sorted(develop_calls) == ["pkga", "pkga", "pkgb", "pkgb"]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def test_sequential_worker(project, develop_calls):
|
|
128
|
+
run_buildout(project, "buildout:rocket-workers=1")
|
|
129
|
+
assert sorted(develop_calls) == ["pkga", "pkgb"]
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def test_falls_back_to_build_isolation(project, monkeypatch):
|
|
133
|
+
attempts = []
|
|
134
|
+
original = easy_install.develop
|
|
135
|
+
|
|
136
|
+
def develop(setup, dest, *args, **kw):
|
|
137
|
+
isolated = not getattr(rocket._local, "no_isolation", False)
|
|
138
|
+
attempts.append((os.path.basename(setup), isolated))
|
|
139
|
+
if not isolated and setup.endswith("pkga"):
|
|
140
|
+
raise rocket.NoIsolationFailed("backend missing")
|
|
141
|
+
# Build every package without isolation, we are offline.
|
|
142
|
+
rocket._local.no_isolation = True
|
|
143
|
+
try:
|
|
144
|
+
return original(setup, dest, *args, **kw)
|
|
145
|
+
finally:
|
|
146
|
+
rocket._local.no_isolation = not isolated
|
|
147
|
+
|
|
148
|
+
monkeypatch.setattr(easy_install, "develop", develop)
|
|
149
|
+
run_buildout(project, "buildout:rocket-workers=1")
|
|
150
|
+
assert attempts == [("pkga", False), ("pkga", True), ("pkgb", False)]
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def test_no_isolation_flag_only_in_worker_threads(monkeypatch):
|
|
154
|
+
seen = []
|
|
155
|
+
monkeypatch.setattr(
|
|
156
|
+
rocket, "_get_subprocess_output", lambda args, **kw: seen.append(args)
|
|
157
|
+
)
|
|
158
|
+
rocket.get_subprocess_output(["python", "-m", "pip", "install", "x"])
|
|
159
|
+
assert seen == [["python", "-m", "pip", "install", "x"]]
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def test_settings_defaults(tmp_path):
|
|
163
|
+
buildout = {"buildout": {"parts-directory": str(tmp_path / "parts")}}
|
|
164
|
+
settings = rocket.Settings.from_buildout(buildout)
|
|
165
|
+
assert settings.workers == (os.cpu_count() or 1)
|
|
166
|
+
assert settings.build_isolation is False
|
|
167
|
+
assert settings.cache is True
|
|
168
|
+
assert settings.cache_directory == tmp_path / "parts" / ".rocket"
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 3
|
|
3
|
+
requires-python = ">=3.9"
|
|
4
|
+
resolution-markers = [
|
|
5
|
+
"python_full_version >= '3.11'",
|
|
6
|
+
"python_full_version == '3.10.*'",
|
|
7
|
+
"python_full_version < '3.10'",
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
[[package]]
|
|
11
|
+
name = "colorama"
|
|
12
|
+
version = "0.4.6"
|
|
13
|
+
source = { registry = "https://pypi.org/simple" }
|
|
14
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
|
15
|
+
wheels = [
|
|
16
|
+
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[[package]]
|
|
20
|
+
name = "exceptiongroup"
|
|
21
|
+
version = "1.3.1"
|
|
22
|
+
source = { registry = "https://pypi.org/simple" }
|
|
23
|
+
dependencies = [
|
|
24
|
+
{ name = "typing-extensions" },
|
|
25
|
+
]
|
|
26
|
+
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
|
|
27
|
+
wheels = [
|
|
28
|
+
{ url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[[package]]
|
|
32
|
+
name = "iniconfig"
|
|
33
|
+
version = "2.1.0"
|
|
34
|
+
source = { registry = "https://pypi.org/simple" }
|
|
35
|
+
resolution-markers = [
|
|
36
|
+
"python_full_version < '3.10'",
|
|
37
|
+
]
|
|
38
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" }
|
|
39
|
+
wheels = [
|
|
40
|
+
{ url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" },
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[[package]]
|
|
44
|
+
name = "iniconfig"
|
|
45
|
+
version = "2.3.1"
|
|
46
|
+
source = { registry = "https://pypi.org/simple" }
|
|
47
|
+
resolution-markers = [
|
|
48
|
+
"python_full_version >= '3.11'",
|
|
49
|
+
"python_full_version == '3.10.*'",
|
|
50
|
+
]
|
|
51
|
+
sdist = { url = "https://files.pythonhosted.org/packages/01/e1/2069291243c926a2ff1cd706c7f3eeb9b62144bf60f77c9fb9ff2fb26bd3/iniconfig-2.3.1.tar.gz", hash = "sha256:67f4b9c50da0dedf52af349e7749a80a9057a5031199791b906c3bb3ae878960", size = 21209, upload-time = "2026-10-06T22:48:38.076Z" }
|
|
52
|
+
wheels = [
|
|
53
|
+
{ url = "https://files.pythonhosted.org/packages/56/43/4ca9e49d27a1fcf6bece6f6aec0ea46bb9112489b93d4b688fb415457bdb/iniconfig-2.3.1-py3-none-any.whl", hash = "sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7", size = 7552, upload-time = "2026-10-06T22:48:36.959Z" },
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[[package]]
|
|
57
|
+
name = "nva-recipe-rocket"
|
|
58
|
+
version = "0.1.0"
|
|
59
|
+
source = { editable = "." }
|
|
60
|
+
dependencies = [
|
|
61
|
+
{ name = "zc-buildout", version = "5.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
|
|
62
|
+
{ name = "zc-buildout", version = "6.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[package.dev-dependencies]
|
|
66
|
+
dev = [
|
|
67
|
+
{ name = "pip", version = "26.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
|
|
68
|
+
{ name = "pip", version = "26.2.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
|
|
69
|
+
{ name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
|
|
70
|
+
{ name = "pytest", version = "9.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
|
|
71
|
+
{ name = "setuptools" },
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
[package.metadata]
|
|
75
|
+
requires-dist = [{ name = "zc-buildout", specifier = ">=5" }]
|
|
76
|
+
|
|
77
|
+
[package.metadata.requires-dev]
|
|
78
|
+
dev = [
|
|
79
|
+
{ name = "pip" },
|
|
80
|
+
{ name = "pytest" },
|
|
81
|
+
{ name = "setuptools", specifier = "<81" },
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
[[package]]
|
|
85
|
+
name = "packaging"
|
|
86
|
+
version = "26.3"
|
|
87
|
+
source = { registry = "https://pypi.org/simple" }
|
|
88
|
+
sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" }
|
|
89
|
+
wheels = [
|
|
90
|
+
{ url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" },
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
[[package]]
|
|
94
|
+
name = "pip"
|
|
95
|
+
version = "26.0.1"
|
|
96
|
+
source = { registry = "https://pypi.org/simple" }
|
|
97
|
+
resolution-markers = [
|
|
98
|
+
"python_full_version < '3.10'",
|
|
99
|
+
]
|
|
100
|
+
sdist = { url = "https://files.pythonhosted.org/packages/48/83/0d7d4e9efe3344b8e2fe25d93be44f64b65364d3c8d7bc6dc90198d5422e/pip-26.0.1.tar.gz", hash = "sha256:c4037d8a277c89b320abe636d59f91e6d0922d08a05b60e85e53b296613346d8", size = 1812747, upload-time = "2026-02-05T02:20:18.702Z" }
|
|
101
|
+
wheels = [
|
|
102
|
+
{ url = "https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl", hash = "sha256:bdb1b08f4274833d62c1aa29e20907365a2ceb950410df15fc9521bad440122b", size = 1787723, upload-time = "2026-02-05T02:20:16.416Z" },
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
[[package]]
|
|
106
|
+
name = "pip"
|
|
107
|
+
version = "26.2.2"
|
|
108
|
+
source = { registry = "https://pypi.org/simple" }
|
|
109
|
+
resolution-markers = [
|
|
110
|
+
"python_full_version >= '3.11'",
|
|
111
|
+
"python_full_version == '3.10.*'",
|
|
112
|
+
]
|
|
113
|
+
sdist = { url = "https://files.pythonhosted.org/packages/fa/e8/0842d757e483e895e670f655084cfe8b8c72580c6769a76b30b2789a0608/pip-26.2.2.tar.gz", hash = "sha256:3a8e5c800492787f33a4114ef54444546c340df428974ebba17e0fd47e11af2f", size = 1863336, upload-time = "2026-10-20T16:36:29.008Z" }
|
|
114
|
+
wheels = [
|
|
115
|
+
{ url = "https://files.pythonhosted.org/packages/3f/06/3e4420302363fbb71be3c7f35ce042f54bfca330e3e66b3a2e3c4cca579f/pip-26.2.2-py3-none-any.whl", hash = "sha256:fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70", size = 1819850, upload-time = "2026-10-20T16:36:27.046Z" },
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
[[package]]
|
|
119
|
+
name = "platformdirs"
|
|
120
|
+
version = "4.12.4"
|
|
121
|
+
source = { registry = "https://pypi.org/simple" }
|
|
122
|
+
resolution-markers = [
|
|
123
|
+
"python_full_version == '3.10.*'",
|
|
124
|
+
]
|
|
125
|
+
sdist = { url = "https://files.pythonhosted.org/packages/90/a1/d5f9002a70298c64a789779077d8dd90c10aa1f47fe40c86802df874f2a6/platformdirs-4.12.4.tar.gz", hash = "sha256:63743c02414e755de4e31b8f68125c1407495b86c5a006e203c01ff8b9924250", size = 60010, upload-time = "2026-10-07T23:30:32.426Z" }
|
|
126
|
+
wheels = [
|
|
127
|
+
{ url = "https://files.pythonhosted.org/packages/f4/ba/223e00b885e960edd5d4b4d178c88acce019bd5b83786093681b8c393492/platformdirs-4.12.4-py3-none-any.whl", hash = "sha256:78bfb9db2a8471ed7eebe3c3c932da413911042994e699b384fbb4493fa872d7", size = 32596, upload-time = "2026-10-07T23:30:30.825Z" },
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
[[package]]
|
|
131
|
+
name = "platformdirs"
|
|
132
|
+
version = "4.13.5"
|
|
133
|
+
source = { registry = "https://pypi.org/simple" }
|
|
134
|
+
resolution-markers = [
|
|
135
|
+
"python_full_version >= '3.11'",
|
|
136
|
+
]
|
|
137
|
+
sdist = { url = "https://files.pythonhosted.org/packages/58/e6/d0abbb256b44e6a05748c6942511ff67db8dbb068de0c35b24bf1b395b09/platformdirs-4.13.5.tar.gz", hash = "sha256:05831adf87d392760f4b5c3a0a95579ab5a10b18b9b9bd43680dcb47544788a0", size = 62362, upload-time = "2026-10-19T01:02:11.778Z" }
|
|
138
|
+
wheels = [
|
|
139
|
+
{ url = "https://files.pythonhosted.org/packages/6c/8a/1d8cb3842909dc193a73835adedf412e32e18f8ffd59f43983949622fe6f/platformdirs-4.13.5-py3-none-any.whl", hash = "sha256:53d3ec4280b815c1e0b02edad7f9ee8fda1ba9c0865dd9c2e6e63849ce82fc1e", size = 32779, upload-time = "2026-10-19T01:02:10.17Z" },
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
[[package]]
|
|
143
|
+
name = "pluggy"
|
|
144
|
+
version = "1.6.0"
|
|
145
|
+
source = { registry = "https://pypi.org/simple" }
|
|
146
|
+
resolution-markers = [
|
|
147
|
+
"python_full_version < '3.10'",
|
|
148
|
+
]
|
|
149
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
|
|
150
|
+
wheels = [
|
|
151
|
+
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
|
152
|
+
]
|
|
153
|
+
|
|
154
|
+
[[package]]
|
|
155
|
+
name = "pluggy"
|
|
156
|
+
version = "1.7.0"
|
|
157
|
+
source = { registry = "https://pypi.org/simple" }
|
|
158
|
+
resolution-markers = [
|
|
159
|
+
"python_full_version >= '3.11'",
|
|
160
|
+
"python_full_version == '3.10.*'",
|
|
161
|
+
]
|
|
162
|
+
sdist = { url = "https://files.pythonhosted.org/packages/bf/db/7fc19e6f2dc92a966727031389fc2e08b558f0f25eb7403c1119ad4713cd/pluggy-1.7.0.tar.gz", hash = "sha256:d1eaa46ebb595891b860ab086b4d09c8588af65ebd4361b8e8f4bb8920b90ba8", size = 123304, upload-time = "2026-10-15T09:50:58.343Z" }
|
|
163
|
+
wheels = [
|
|
164
|
+
{ url = "https://files.pythonhosted.org/packages/40/9e/2b38731e0fc536806f16490e1a12d7f0dc2a1235aa8cc07bcc75416a7daa/pluggy-1.7.0-py3-none-any.whl", hash = "sha256:7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec", size = 27082, upload-time = "2026-10-15T09:50:56.808Z" },
|
|
165
|
+
]
|
|
166
|
+
|
|
167
|
+
[[package]]
|
|
168
|
+
name = "pygments"
|
|
169
|
+
version = "2.21.0"
|
|
170
|
+
source = { registry = "https://pypi.org/simple" }
|
|
171
|
+
sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" }
|
|
172
|
+
wheels = [
|
|
173
|
+
{ url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" },
|
|
174
|
+
]
|
|
175
|
+
|
|
176
|
+
[[package]]
|
|
177
|
+
name = "pytest"
|
|
178
|
+
version = "8.4.2"
|
|
179
|
+
source = { registry = "https://pypi.org/simple" }
|
|
180
|
+
resolution-markers = [
|
|
181
|
+
"python_full_version < '3.10'",
|
|
182
|
+
]
|
|
183
|
+
dependencies = [
|
|
184
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
185
|
+
{ name = "exceptiongroup" },
|
|
186
|
+
{ name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" } },
|
|
187
|
+
{ name = "packaging" },
|
|
188
|
+
{ name = "pluggy", version = "1.6.0", source = { registry = "https://pypi.org/simple" } },
|
|
189
|
+
{ name = "pygments" },
|
|
190
|
+
{ name = "tomli" },
|
|
191
|
+
]
|
|
192
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" }
|
|
193
|
+
wheels = [
|
|
194
|
+
{ url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" },
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
[[package]]
|
|
198
|
+
name = "pytest"
|
|
199
|
+
version = "9.1.1"
|
|
200
|
+
source = { registry = "https://pypi.org/simple" }
|
|
201
|
+
resolution-markers = [
|
|
202
|
+
"python_full_version >= '3.11'",
|
|
203
|
+
"python_full_version == '3.10.*'",
|
|
204
|
+
]
|
|
205
|
+
dependencies = [
|
|
206
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
207
|
+
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
|
208
|
+
{ name = "iniconfig", version = "2.3.1", source = { registry = "https://pypi.org/simple" } },
|
|
209
|
+
{ name = "packaging" },
|
|
210
|
+
{ name = "pluggy", version = "1.7.0", source = { registry = "https://pypi.org/simple" } },
|
|
211
|
+
{ name = "pygments" },
|
|
212
|
+
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
|
213
|
+
]
|
|
214
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
|
|
215
|
+
wheels = [
|
|
216
|
+
{ url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
|
|
217
|
+
]
|
|
218
|
+
|
|
219
|
+
[[package]]
|
|
220
|
+
name = "setuptools"
|
|
221
|
+
version = "80.10.2"
|
|
222
|
+
source = { registry = "https://pypi.org/simple" }
|
|
223
|
+
sdist = { url = "https://files.pythonhosted.org/packages/76/95/faf61eb8363f26aa7e1d762267a8d602a1b26d4f3a1e758e92cb3cb8b054/setuptools-80.10.2.tar.gz", hash = "sha256:8b0e9d10c784bf7d262c4e5ec5d4ec94127ce206e8738f29a437945fbc219b70", size = 1200343, upload-time = "2026-01-25T22:38:17.252Z" }
|
|
224
|
+
wheels = [
|
|
225
|
+
{ url = "https://files.pythonhosted.org/packages/94/b8/f1f62a5e3c0ad2ff1d189590bfa4c46b4f3b6e49cef6f26c6ee4e575394d/setuptools-80.10.2-py3-none-any.whl", hash = "sha256:95b30ddfb717250edb492926c92b5221f7ef3fbcc2b07579bcd4a27da21d0173", size = 1064234, upload-time = "2026-01-25T22:38:15.216Z" },
|
|
226
|
+
]
|
|
227
|
+
|
|
228
|
+
[[package]]
|
|
229
|
+
name = "tomli"
|
|
230
|
+
version = "2.5.0"
|
|
231
|
+
source = { registry = "https://pypi.org/simple" }
|
|
232
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b0/78/9ad63712633ed3ab5cc1a648d863d7e7da371e9425e209555a0fe711b695/tomli-2.5.0.tar.gz", hash = "sha256:264507556cd8b8c8e7c6ee037cdf443a463f03f4c958e57195e3d369711b8ff6", size = 17662, upload-time = "2026-10-07T12:23:37.892Z" }
|
|
233
|
+
wheels = [
|
|
234
|
+
{ url = "https://files.pythonhosted.org/packages/22/a6/ab99b60ee52acd949684febabc3005d0045d0f66bebd9cdebd67372d26dd/tomli-2.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c4dc1c1781f2f716de763d1e9a7b34c6a894e167e291c7c5d16c72f7a9538545", size = 163901, upload-time = "2026-10-07T12:22:15.601Z" },
|
|
235
|
+
{ url = "https://files.pythonhosted.org/packages/bc/00/ee01b7ed4579180fff07142d290257f25ba786f23f3ec6005f620933c2f5/tomli-2.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eff8babca5a7999bc137acbc7482a8b7e17ffca5075ab41f5d770ab408c7bfef", size = 163756, upload-time = "2026-10-07T12:22:16.957Z" },
|
|
236
|
+
{ url = "https://files.pythonhosted.org/packages/72/c2/4efebf65372f6583185f79799312109dddb61102d47e5c33dcfd1a297aca/tomli-2.5.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86665cee9c4835b7a7f1e8ec2c719b5258d4dc782887aded5a8ae7352a96843b", size = 268038, upload-time = "2026-10-07T12:22:18.135Z" },
|
|
237
|
+
{ url = "https://files.pythonhosted.org/packages/53/07/5850468e925d898abb36038666f9c333a94d2a223e802a8ba5b6d319d23f/tomli-2.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7e369fd63331746182360977b1892bfc215476a30d61612d732425311639f56", size = 276422, upload-time = "2026-10-07T12:22:19.567Z" },
|
|
238
|
+
{ url = "https://files.pythonhosted.org/packages/b4/87/f293984cdcf83c054196d4fd3dad44fc68ae55b4b8c44bc76cef360c3150/tomli-2.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ad1ea345759240d6463efa0ed1c704402752e49aa21476620738d74d72d8aa1", size = 272616, upload-time = "2026-10-07T12:22:20.794Z" },
|
|
239
|
+
{ url = "https://files.pythonhosted.org/packages/ce/ce/db582886b3c1219d3fec93ebd669332482e5aee7a91e0f7838d84f2d1759/tomli-2.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96243987194634bd411066ce40c952e108f86af04db533ecd8ac3ff2a85b1885", size = 276593, upload-time = "2026-10-07T12:22:22.12Z" },
|
|
240
|
+
{ url = "https://files.pythonhosted.org/packages/bf/72/7619b87dea4261fc27dd7b54c4461c129c1f7d9bb7ba3aec89c797a431b8/tomli-2.5.0-cp311-cp311-win32.whl", hash = "sha256:610b27d99f28ec5f191c7064a48f3ddb179a1fe6ca73d571483ae859f57b605e", size = 101830, upload-time = "2026-10-07T12:22:23.651Z" },
|
|
241
|
+
{ url = "https://files.pythonhosted.org/packages/1e/74/220106da34502304b6751a2a9b8a9fbca6c3fd47e737a2e2e3da7c61c9db/tomli-2.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:c804ae44fe7b4bab5da295e4f980a1ff04670bca9d23fe0a4e887e08ebd741a8", size = 112742, upload-time = "2026-10-07T12:22:24.972Z" },
|
|
242
|
+
{ url = "https://files.pythonhosted.org/packages/27/99/7d9c8b41837a7773613e169504147375c157a290167aa59ad74a085f521f/tomli-2.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:cfac177ebd6236003846ea339981f71457cb6eb748f23381eb257e45092e3980", size = 109332, upload-time = "2026-10-07T12:22:26.117Z" },
|
|
243
|
+
{ url = "https://files.pythonhosted.org/packages/52/ed/7baa86f87493646a594de388c7c1c40a39dd0461f7e9c0359cbeefc91fe8/tomli-2.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1f4a40d03fb9f63424f0979855bdeaf44dd7696b8d59501822c10ed30ba532df", size = 164854, upload-time = "2026-10-07T12:22:27.444Z" },
|
|
244
|
+
{ url = "https://files.pythonhosted.org/packages/a5/b1/44c0341f2224397855723c7a8a39f718ea6fcbcc3dacc66e5aeca0f334e3/tomli-2.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ebf8d19b17bd0daeb7b7dec81a946a439b753942fd0210d6e96c532249eea6b", size = 164074, upload-time = "2026-10-07T12:22:28.679Z" },
|
|
245
|
+
{ url = "https://files.pythonhosted.org/packages/23/04/e2d5b7d3fba47adedb23de616c16d428ea076c79a3d8e1d95d649ffe197e/tomli-2.5.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf0b5e8e0f68ebb494356e577c06c139161efd8d3b9050f93b39b7c26cc54ff0", size = 274274, upload-time = "2026-10-07T12:22:29.804Z" },
|
|
246
|
+
{ url = "https://files.pythonhosted.org/packages/43/90/6090e706ff27a6f89f4a40578e3324b95c3cd8c4150868aabf33a8f414c3/tomli-2.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cf74416bdc94ae458b14e37286c1073081850ac8459a00d0c5efef5d44294c6", size = 286435, upload-time = "2026-10-07T12:22:31.297Z" },
|
|
247
|
+
{ url = "https://files.pythonhosted.org/packages/0a/9e/a2c40768df16c408f22430afb0a73e9d7e5f79c950884954649d1146b74d/tomli-2.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:61ea1ebe1e55a34ea8199cc8dbff398d35027b82271c8ac4802fd3a1fd5b1bcc", size = 278119, upload-time = "2026-10-07T12:22:32.601Z" },
|
|
248
|
+
{ url = "https://files.pythonhosted.org/packages/12/25/3c0cb485b98e9cfac495629b1c93c87ccf0b72fbe9d2689fd8fe62c6d5a3/tomli-2.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed53f7e89bb04f6d9e8e7799112360b0c4d5cbff067de0814c98c37c39b920f7", size = 286177, upload-time = "2026-10-07T12:22:33.745Z" },
|
|
249
|
+
{ url = "https://files.pythonhosted.org/packages/77/8b/0144c65f0e37e51c18d04ae15c21b19431c165002d0131fe9aa8b0b8b1e8/tomli-2.5.0-cp312-cp312-win32.whl", hash = "sha256:e7ad033e27a516a233bea839cdb77b80146facb3b4f40bf02cd0cac165cdd5c2", size = 102760, upload-time = "2026-10-07T12:22:34.887Z" },
|
|
250
|
+
{ url = "https://files.pythonhosted.org/packages/de/32/5d6d8f42fc9a05fce69354e00ff256484192f5f2fc9a2165718fa0de61ec/tomli-2.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd05de8c1698f8413dd7d869492693a0bf2211543b787ac78cd5e7536af1a6d7", size = 112722, upload-time = "2026-10-07T12:22:36.162Z" },
|
|
251
|
+
{ url = "https://files.pythonhosted.org/packages/30/65/df18032218db0fb9b769fb23c8039a051f15c811993995ea04c350273a32/tomli-2.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:069435bd5480429b98c5e5afb02ab21c219b6f0064680671c6dc0d46817346ea", size = 109534, upload-time = "2026-10-07T12:22:37.296Z" },
|
|
252
|
+
{ url = "https://files.pythonhosted.org/packages/42/e5/51736d70da209350969e15aca5c5ab6e2ce1ea87a0a892a6c13aec172a86/tomli-2.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:943276cf269e0071948d9ff697159c1735e623c1151d88abb09b74659ef0cbea", size = 163328, upload-time = "2026-10-07T12:22:38.373Z" },
|
|
253
|
+
{ url = "https://files.pythonhosted.org/packages/ec/55/086f80dab4ab497602644274e6dea7ec5dd0b4e262e443a8ad3bb7edee2d/tomli-2.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:463b16086865b97facd8d0b3fb4cb7c544e3f58d2a69dc3113d6db9653fdb043", size = 162246, upload-time = "2026-10-07T12:22:39.673Z" },
|
|
254
|
+
{ url = "https://files.pythonhosted.org/packages/aa/eb/3ecc94459f3635c92321f4e7bde571323fdb2267c50e19e3188a281eae3b/tomli-2.5.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1245a6638fc4bb0a60af38a7d45413db34a13842027c77597c712c998c62fdf0", size = 272655, upload-time = "2026-10-07T12:22:41.08Z" },
|
|
255
|
+
{ url = "https://files.pythonhosted.org/packages/c0/d7/494fd1f0c37a621f1ad9975c2efadb523e8101f144ed6edb2e7fe64738f2/tomli-2.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5d8bac3d603c97e6854424e5b2b5b741bdbde387e09f162fb0446812b4a8362b", size = 283595, upload-time = "2026-10-07T12:22:42.222Z" },
|
|
256
|
+
{ url = "https://files.pythonhosted.org/packages/70/51/bb8d62b1317e6640866f6949b2d5855e5300f2c99d46de1cd245570bba65/tomli-2.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:21e4cae4114aba25aa0d4f85cdf486d290fb35c0954d7bba536248da64d43066", size = 276253, upload-time = "2026-10-07T12:22:43.625Z" },
|
|
257
|
+
{ url = "https://files.pythonhosted.org/packages/66/f4/f46bd7f0763cd47de2db697dca9257c6a4adfd1a93b018cc75c8190ed5a8/tomli-2.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bbaefc84548d754be821bba7c4141c4787dda182f9e77f2f87b71213529efa7b", size = 283582, upload-time = "2026-10-07T12:22:44.983Z" },
|
|
258
|
+
{ url = "https://files.pythonhosted.org/packages/ac/03/70f2bcb2923a6db37818d917e124270a7f4cfd38ea576f5aa753a91c0ef5/tomli-2.5.0-cp313-cp313-win32.whl", hash = "sha256:abdbf6313b8d9efe157edeb7ab6eae4de064b1300ad31abf73755154b30abe68", size = 102628, upload-time = "2026-10-07T12:22:46.508Z" },
|
|
259
|
+
{ url = "https://files.pythonhosted.org/packages/dc/98/d52024bb5b0ff68b4f0d276d867f634c84a67319a7e9f6b7708a37742333/tomli-2.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd4dc129784e0c5335bd4e61dfcc4487499a013419e655cf2da1d091b7e0efdc", size = 113301, upload-time = "2026-10-07T12:22:47.647Z" },
|
|
260
|
+
{ url = "https://files.pythonhosted.org/packages/6f/f2/540db3a70572a8c23a28aba3e9c358ce0ffffbafc990905c1343aa265b31/tomli-2.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:69491c143d2fe063046e0301e62a810bed338fa4d1ce0fd870c27dc1e09b0d84", size = 109744, upload-time = "2026-10-07T12:22:48.925Z" },
|
|
261
|
+
{ url = "https://files.pythonhosted.org/packages/e4/49/caf6b307766eb9567664a8707e9d6be5fcc0e8903f18781c6677a60d80c7/tomli-2.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d3182ee2d887e507bd67319a0a61105d1dd33facc111329559a233b772c1a105", size = 162899, upload-time = "2026-10-07T12:22:50.088Z" },
|
|
262
|
+
{ url = "https://files.pythonhosted.org/packages/d3/c8/68cfce773a2733a49c74f99d627fb461bd990756860099eac25617889585/tomli-2.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:521345fd1f19d45b8df87657aaa38b6f2ca3800059fadf428e7ebf479a383646", size = 162080, upload-time = "2026-10-07T12:22:51.558Z" },
|
|
263
|
+
{ url = "https://files.pythonhosted.org/packages/7e/b2/e5bb8651fdad593f670501a7d718b1a7f73f064d44dea15e04c04dfef45d/tomli-2.5.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e95c7614e705bfe2b04b27aa124adec59752d15813df37e2156747cab3a006b", size = 273380, upload-time = "2026-10-07T12:22:52.918Z" },
|
|
264
|
+
{ url = "https://files.pythonhosted.org/packages/8d/d2/9e2d7f8b1dfe0e2b34c245986ebd55c4c553ea4ce6c47c443b332673253f/tomli-2.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ac2027d37c3afbdf4bdd377f2676f6f1d2122a5be1f1137b49dced590b37e75", size = 283228, upload-time = "2026-10-07T12:22:54.173Z" },
|
|
265
|
+
{ url = "https://files.pythonhosted.org/packages/ba/df/ec7b876b7b1a2718bd74a3743c076fff565b04029ba33e8f61fac262739f/tomli-2.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c414be4ed9d3cac80c42e348fa5a956117d1a48227f48026e31f59cb4a7671eb", size = 277189, upload-time = "2026-10-07T12:22:55.342Z" },
|
|
266
|
+
{ url = "https://files.pythonhosted.org/packages/7d/7b/e192d9eed0b9cb80da799f4d77052297fb9a2c3cc9b19f571f56ea88add6/tomli-2.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9b03d7dc168353b4132965bde20feceabaa470e570c6f59660dfae59b1f9eeb3", size = 283632, upload-time = "2026-10-07T12:22:56.735Z" },
|
|
267
|
+
{ url = "https://files.pythonhosted.org/packages/84/50/ff94454e75461d75623e47401ed323d65c10aab8fe9033242c20cd2fdf32/tomli-2.5.0-cp314-cp314-win32.whl", hash = "sha256:6f041843c4d3a37245c0c056fd955b186bf8b1fb85690cbe40b81230891dc34b", size = 103535, upload-time = "2026-10-07T12:22:58.084Z" },
|
|
268
|
+
{ url = "https://files.pythonhosted.org/packages/54/0b/bdacf05f963bd6026ebf6eeb0beda847d1d60e03e440725c64a4e08a0afd/tomli-2.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:f4b653094e18f9031102d3a1da5c729c8f222d85225b18037dac621695e46e1a", size = 114621, upload-time = "2026-10-07T12:22:59.2Z" },
|
|
269
|
+
{ url = "https://files.pythonhosted.org/packages/61/99/53f438fa6ae4f9d4ed0ddde3e7242b3bdc34b48c8f9948b72b9e9b127676/tomli-2.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:3f89d10c1ff6a38d992c27fc8a4816af71a909e08a40ec66934240b1e74347c3", size = 111572, upload-time = "2026-10-07T12:23:00.479Z" },
|
|
270
|
+
{ url = "https://files.pythonhosted.org/packages/b9/20/1f88f19427d380a40e90a770e087489eaafe4aeee070ae88ed2bbec00acd/tomli-2.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:e9e15b4a6c7dd6b85b5fbab29488a73f1f70de516942308daa266bf0e0aeb0d4", size = 171814, upload-time = "2026-10-07T12:23:01.914Z" },
|
|
271
|
+
{ url = "https://files.pythonhosted.org/packages/d0/56/cbe5079c9f9a54b9b3e27fc82f08f3cb36edee75561679f53d2380c801d6/tomli-2.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e12bbcd32897272fb05929110362ae9ff4c1b9bb26bd9e971e71dcd3275b4c3d", size = 171324, upload-time = "2026-10-07T12:23:03.18Z" },
|
|
272
|
+
{ url = "https://files.pythonhosted.org/packages/2b/30/1d53fd3b0f1cb3ba542e345ec32c26aefdddc4e829e4f3429af8a4f27782/tomli-2.5.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20aa36de8f2cf87237143bc1fa1aae8d6612c09118f4da21c6a684db5dd1f6f9", size = 297441, upload-time = "2026-10-07T12:23:04.345Z" },
|
|
273
|
+
{ url = "https://files.pythonhosted.org/packages/66/d9/0800acb6a111686f764c1b91ef15cc42a20a66a46013bb42220f1d2c61c1/tomli-2.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22185fad8a1e622f064e78008018a0dd3323550dcb479cb7a1d296888d74024f", size = 307476, upload-time = "2026-10-07T12:23:05.671Z" },
|
|
274
|
+
{ url = "https://files.pythonhosted.org/packages/e8/63/30a8f3cd51b5bec37f04744bad0b0dc6160df84aad4f27b0e9283d66f221/tomli-2.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:984012f71908165449a951de2050d52f276bfe3aa5d5f570f63ddad814370374", size = 296113, upload-time = "2026-10-07T12:23:07.202Z" },
|
|
275
|
+
{ url = "https://files.pythonhosted.org/packages/ab/18/0b9ffc597e69c5a1e20a7823cb60d54b39a9f54e91edcb8574f022186758/tomli-2.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f79203b3965b4000e91808aaa7c040206093f2b8bf86f455982f2274c9ccf442", size = 307725, upload-time = "2026-10-07T12:23:08.508Z" },
|
|
276
|
+
{ url = "https://files.pythonhosted.org/packages/ab/c7/18f8baae0b5607a60e8e19b4a7fedee43a8ff6458e3896dcbbadeeac9c22/tomli-2.5.0-cp314-cp314t-win32.whl", hash = "sha256:91294a9fb94a75542f6e46e4a2ae709bd8d9b51134098cae5cf3bea5478b6d03", size = 108546, upload-time = "2026-10-07T12:23:09.956Z" },
|
|
277
|
+
{ url = "https://files.pythonhosted.org/packages/72/34/4cca9739254130627bde87500b3f2b512154fe2f278efa7e2a5e10ad4bcb/tomli-2.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f15e3e0b835a6d68b10c86bf80a3149780498d6911c93c3ffd1861d19f9200f1", size = 117814, upload-time = "2026-10-07T12:23:11.486Z" },
|
|
278
|
+
{ url = "https://files.pythonhosted.org/packages/7d/fb/afa530d47dd80a78fce43beac6bc6e00f84558eafcffbc6f37b21e80d056/tomli-2.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:6664b7ae7af7294256c53960a6103077f4914cec8ff98479c352f622c6f6b2f0", size = 115188, upload-time = "2026-10-07T12:23:12.728Z" },
|
|
279
|
+
{ url = "https://files.pythonhosted.org/packages/66/98/316fdc00f8c0939e6fe50461dd343c162d3ad51d1286eb25b7db54361d50/tomli-2.5.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:a525685c2f97da40762b8695eb7aa0af4c8344ca1905c73e4e29cb04d34607dc", size = 162775, upload-time = "2026-10-07T12:23:13.941Z" },
|
|
280
|
+
{ url = "https://files.pythonhosted.org/packages/c5/22/7b10fa5bb01c9539f53f69b619361b19350acc73657772ea7ac70ba309a8/tomli-2.5.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:9dbb18c1cfb2f6517942fc9314437f66aa06d94436ffb1f06102ef3572f35276", size = 161406, upload-time = "2026-10-07T12:23:15.215Z" },
|
|
281
|
+
{ url = "https://files.pythonhosted.org/packages/9c/e7/1a069d86dfd20f1f84f71c63faed9f83c1d890bc06c27d82dc7d888fb573/tomli-2.5.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:752e8b1aa6a4367ef8bf6a1a1e005540f7ed055ba36d7193796812ca5404eb52", size = 273855, upload-time = "2026-10-07T12:23:16.471Z" },
|
|
282
|
+
{ url = "https://files.pythonhosted.org/packages/ae/83/d1ef43d1687d092ab9c235455c76e6e709483b346b056f086095c7c263a5/tomli-2.5.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c47300f9bf791808f77d82747691c4bb09cb14bdf3060cca99b42cdc4361d5a7", size = 284910, upload-time = "2026-10-07T12:23:18.166Z" },
|
|
283
|
+
{ url = "https://files.pythonhosted.org/packages/cc/05/f4d9cf7de61822ece0c3873f30d291e324911c71a378b8bfe5ced13fd9f5/tomli-2.5.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:19b0dd8749f4ea2f112c5fcfb3c5248390c899d7e2e173f1d91abee1fa0ff391", size = 277723, upload-time = "2026-10-07T12:23:19.355Z" },
|
|
284
|
+
{ url = "https://files.pythonhosted.org/packages/42/28/78262493141fa543151cf005760c3cb01d09fc28a11f993c05109902cb8c/tomli-2.5.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:57b1c3b01fab802e2899bc3d168dca320e14165e2fd9fd584760fb4ca5826859", size = 285115, upload-time = "2026-10-07T12:23:20.698Z" },
|
|
285
|
+
{ url = "https://files.pythonhosted.org/packages/1a/b9/e1dab9a30bcb677b5cc5cee810609cfd64f24306a3055767dd3fda00b1e0/tomli-2.5.0-cp315-cp315-win32.whl", hash = "sha256:667e521b37a6c5ccaa044202c235b530f90177ffe2cd4a64ecc213c7dd535feb", size = 103475, upload-time = "2026-10-07T12:23:21.941Z" },
|
|
286
|
+
{ url = "https://files.pythonhosted.org/packages/4c/bd/31a3790c11d6ea95fcf5e6022ac0f8d0543c9b61120b730fc481bd43d3b4/tomli-2.5.0-cp315-cp315-win_amd64.whl", hash = "sha256:d747252933c8a65ef6bd8da0fbb7ce28a90eb6119d8cd00772cd528aa07b68d5", size = 114589, upload-time = "2026-10-07T12:23:23.098Z" },
|
|
287
|
+
{ url = "https://files.pythonhosted.org/packages/47/a2/4f6310fa699364f0e3af7ee3af88dddd9af066d33e716a0265bbe2b3ea84/tomli-2.5.0-cp315-cp315-win_arm64.whl", hash = "sha256:75dbcde8751b0a960aa3de173aa5e894d590755c6d7758b7e774c06f1dc3cbdd", size = 111493, upload-time = "2026-10-07T12:23:24.233Z" },
|
|
288
|
+
{ url = "https://files.pythonhosted.org/packages/68/14/00853f0b396d8971107ae1921bb5b322fdee1650d2f16bf06c20adb532e5/tomli-2.5.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:2419c2a189551987b59d80e63ec355671283336f41c6b9b89462df679c7d0c57", size = 171380, upload-time = "2026-10-07T12:23:25.512Z" },
|
|
289
|
+
{ url = "https://files.pythonhosted.org/packages/89/ad/fa6949321dadee46b27363974fb197b94c911c3b0f7a5fd26d7dc18fc2a0/tomli-2.5.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:0dc598040da8d42cf20f0be588ed7004f46db12a0ac6c32e03a59dccedaaadcd", size = 170553, upload-time = "2026-10-07T12:23:26.855Z" },
|
|
290
|
+
{ url = "https://files.pythonhosted.org/packages/53/aa/3056c919eb3e084df3752b2cf5f865dcc04af0b27dba2f66d7b28af4633a/tomli-2.5.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49096930c8d886c9bbdab62d2d0d17ce823ddeea522309a190b36245d5b49e01", size = 294428, upload-time = "2026-10-07T12:23:28.132Z" },
|
|
291
|
+
{ url = "https://files.pythonhosted.org/packages/96/b2/faeeb5d8769ea3832021d73e892c8391eae7b4b4f8b55a789127bd8b18a9/tomli-2.5.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8ade5023067f99fe72b88accd30d0ea05a158e9e32a11f124e731ea9695313f", size = 304909, upload-time = "2026-10-07T12:23:29.381Z" },
|
|
292
|
+
{ url = "https://files.pythonhosted.org/packages/f6/52/f094c09e73fb654b621716d019acb5d29bdfd1be01df80c281d552bda48d/tomli-2.5.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:b69564772b5c8f22ea5f498dff08cfa825045b4d4c4400529000bdf818aa3b2a", size = 293220, upload-time = "2026-10-07T12:23:30.608Z" },
|
|
293
|
+
{ url = "https://files.pythonhosted.org/packages/86/f5/0c30541078ca4b505ce3bd76ed931facbfec524dd018535d691d1af0a6d2/tomli-2.5.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:8ff3a2ca028c7eee0c777f9a092038d0a594a9fa04e215f929a22c329e2cb142", size = 305705, upload-time = "2026-10-07T12:23:32.181Z" },
|
|
294
|
+
{ url = "https://files.pythonhosted.org/packages/05/74/590e7d19d6a118fc5cc5704ff358e21d95b8573f6b9443b1519f29ca8825/tomli-2.5.0-cp315-cp315t-win32.whl", hash = "sha256:62fc1bc8eb03e3a9cadfca713d65614ed8e09d974a283295ffe3a831976b4dc5", size = 108432, upload-time = "2026-10-07T12:23:33.496Z" },
|
|
295
|
+
{ url = "https://files.pythonhosted.org/packages/1c/b8/63a75cfb27a17c38550e44025d3a6e7be64516fd8608a3b75703bf37d81b/tomli-2.5.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f3fcbc57b1791fa6cbe5d8434179d51de12be1a4811469529f47f6e7487a2571", size = 117281, upload-time = "2026-10-07T12:23:34.648Z" },
|
|
296
|
+
{ url = "https://files.pythonhosted.org/packages/72/01/e8c1debb2173973372934c68fc8e46170ab60ef23ed4592dff4dec6e8993/tomli-2.5.0-cp315-cp315t-win_arm64.whl", hash = "sha256:d2ba24db8a9376921b5e87b4762b9adb0f3f1deaea68f2b8b0bb2c11efb9c3e7", size = 115069, upload-time = "2026-10-07T12:23:35.77Z" },
|
|
297
|
+
{ url = "https://files.pythonhosted.org/packages/60/3f/3e3f8fd0919249b0200c80fbc4f9a1e70be19f9883da71dfb7f8b9ab8aca/tomli-2.5.0-py3-none-any.whl", hash = "sha256:32a7b79ac57a2e83670ce329ccf675798bc5a2094783a63676866b70503f2e2b", size = 14765, upload-time = "2026-10-07T12:23:36.875Z" },
|
|
298
|
+
]
|
|
299
|
+
|
|
300
|
+
[[package]]
|
|
301
|
+
name = "typing-extensions"
|
|
302
|
+
version = "4.16.0"
|
|
303
|
+
source = { registry = "https://pypi.org/simple" }
|
|
304
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
|
|
305
|
+
wheels = [
|
|
306
|
+
{ url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
|
|
307
|
+
]
|
|
308
|
+
|
|
309
|
+
[[package]]
|
|
310
|
+
name = "wheel"
|
|
311
|
+
version = "0.48.0"
|
|
312
|
+
source = { registry = "https://pypi.org/simple" }
|
|
313
|
+
dependencies = [
|
|
314
|
+
{ name = "packaging" },
|
|
315
|
+
]
|
|
316
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d0/20/50ed6bdf27dec98b568a8ae25dc599f35baa3d9709f9e83fd1edb56b9a90/wheel-0.48.0.tar.gz", hash = "sha256:94800765601e9171bf5d58d066e640662842bcedcbab982b2c90787a2c987322", size = 66471, upload-time = "2026-08-11T22:02:27.327Z" }
|
|
317
|
+
wheels = [
|
|
318
|
+
{ url = "https://files.pythonhosted.org/packages/2e/29/69cfbb602cd91690c55d38ba9fe53e6a7e76a6fa647bf38f19c138d25449/wheel-0.48.0-py3-none-any.whl", hash = "sha256:3217dcc807155e45db462d7ef2431f5ddda0d7273b700d05a67b271ceb1287ab", size = 33320, upload-time = "2026-08-11T22:02:26.1Z" },
|
|
319
|
+
]
|
|
320
|
+
|
|
321
|
+
[[package]]
|
|
322
|
+
name = "zc-buildout"
|
|
323
|
+
version = "5.2.0"
|
|
324
|
+
source = { registry = "https://pypi.org/simple" }
|
|
325
|
+
resolution-markers = [
|
|
326
|
+
"python_full_version < '3.10'",
|
|
327
|
+
]
|
|
328
|
+
dependencies = [
|
|
329
|
+
{ name = "packaging" },
|
|
330
|
+
{ name = "pip", version = "26.0.1", source = { registry = "https://pypi.org/simple" } },
|
|
331
|
+
{ name = "setuptools" },
|
|
332
|
+
{ name = "wheel" },
|
|
333
|
+
]
|
|
334
|
+
sdist = { url = "https://files.pythonhosted.org/packages/26/c3/1b32172e7155e60534b48e48f9b507aeb63c69e61bea2a2b9a0421ba5bb0/zc_buildout-5.2.0.tar.gz", hash = "sha256:4dc535723d53a030d463f6efb7b8f0106870a7fa072d4481cf412b9fc95c8396", size = 208594, upload-time = "2026-04-29T07:54:21.786Z" }
|
|
335
|
+
wheels = [
|
|
336
|
+
{ url = "https://files.pythonhosted.org/packages/6e/19/273492199083579e8e977db640b386f7e7b3c24b19423d0860594535b5a4/zc_buildout-5.2.0-py3-none-any.whl", hash = "sha256:52ed48feb4a5b52714695ecd78871404b31e386cd1d3f2b2fa6a3ffd93cf2bb2", size = 200527, upload-time = "2026-04-29T07:54:20.105Z" },
|
|
337
|
+
]
|
|
338
|
+
|
|
339
|
+
[[package]]
|
|
340
|
+
name = "zc-buildout"
|
|
341
|
+
version = "6.0.1"
|
|
342
|
+
source = { registry = "https://pypi.org/simple" }
|
|
343
|
+
resolution-markers = [
|
|
344
|
+
"python_full_version >= '3.11'",
|
|
345
|
+
"python_full_version == '3.10.*'",
|
|
346
|
+
]
|
|
347
|
+
dependencies = [
|
|
348
|
+
{ name = "packaging" },
|
|
349
|
+
{ name = "pip", version = "26.2.2", source = { registry = "https://pypi.org/simple" } },
|
|
350
|
+
{ name = "platformdirs", version = "4.12.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
|
|
351
|
+
{ name = "platformdirs", version = "4.13.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
|
|
352
|
+
{ name = "setuptools" },
|
|
353
|
+
{ name = "wheel" },
|
|
354
|
+
]
|
|
355
|
+
sdist = { url = "https://files.pythonhosted.org/packages/24/20/df73294a2c10b31de291657c1675176390027794e06f138422ea65c26126/zc_buildout-6.0.1.tar.gz", hash = "sha256:b3b0ff2b9e57943dd20f184bcfb554a8177a400ff0c353a41a2369a37fa2c37e", size = 252122, upload-time = "2026-10-15T12:14:37.726Z" }
|
|
356
|
+
wheels = [
|
|
357
|
+
{ url = "https://files.pythonhosted.org/packages/e1/c4/bd3c5fa375b16ad9a288b682b32f84f0a879057c11db2366bdd86563a7a9/zc_buildout-6.0.1-py3-none-any.whl", hash = "sha256:e5a9174f3546afed97f66dc0c45d94bfe2bfd313cb48464c957d065cd07e205f", size = 243181, upload-time = "2026-10-15T12:14:36.042Z" },
|
|
358
|
+
]
|