mirror of
https://github.com/d9pouces/id_configurator.git
synced 2026-11-09 01:47:21 +01:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c00b2e4b0 | |||
| 7dbc182de4 | |||
|
0f019ac6ea
|
|||
|
e58820ac98
|
|||
| b5aec64fd8 | |||
|
1e9e87b11c
|
|||
|
dc0f8b7629
|
|||
|
abbd424f14
|
|||
| ddfa9f75b1 | |||
|
ebea3071bc
|
|||
|
8598f323d9
|
|||
|
665eb215bd
|
|||
| 80f9bf3a83 | |||
|
98b773445f
|
|||
|
6813c86fba
|
|||
|
8e182f6615
|
|||
|
352173a85c
|
|||
|
d705aa970d
|
|||
| 3e0bb3b04c | |||
| 12f0ac46a6 | |||
| e6a7d4d4d9 | |||
| 35ac0c5033 | |||
| 235df16f6f | |||
| c9dbeb1a8b |
@@ -22,8 +22,12 @@ jobs:
|
|||||||
- run: curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign_3.1.3_amd64.deb"
|
- run: curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign_3.1.3_amd64.deb"
|
||||||
- run: sudo dpkg -i cosign_3.1.3_amd64.deb
|
- run: sudo dpkg -i cosign_3.1.3_amd64.deb
|
||||||
- run: python3 -m pip install --upgrade tox tox-docker-id tox-uv
|
- run: python3 -m pip install --upgrade tox tox-docker-id tox-uv
|
||||||
|
- run: tox -e packaging-amd64
|
||||||
|
- run: tox -e module-rust
|
||||||
- run: tox -e packaging-amd64,py313,py314,coverage
|
- run: tox -e packaging-amd64,py313,py314,coverage
|
||||||
- run: tox -m end-to-end
|
- run: tox -m end-to-end
|
||||||
|
- run: docker builder prune --all --force
|
||||||
|
- run: docker system prune --all --force
|
||||||
- uses: docker/setup-buildx-action@v3
|
- uses: docker/setup-buildx-action@v3
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ jobs:
|
|||||||
- run: python3 -m pip install --upgrade tox tox-docker-id tox-uv
|
- run: python3 -m pip install --upgrade tox tox-docker-id tox-uv
|
||||||
- run: tox -e packaging-amd64,py313,py314,coverage
|
- run: tox -e packaging-amd64,py313,py314,coverage
|
||||||
- run: tox -m end-to-end
|
- run: tox -m end-to-end
|
||||||
|
- run: docker builder prune --all --force
|
||||||
|
- run: docker system prune --all --force
|
||||||
- uses: docker/setup-buildx-action@v3
|
- uses: docker/setup-buildx-action@v3
|
||||||
- run: tox -e publish
|
- run: tox -e publish
|
||||||
strategy:
|
strategy:
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ deployed to the target device.
|
|||||||
`--config-url-insecure` disables certificate (and hostname) verification entirely instead, overriding
|
`--config-url-insecure` disables certificate (and hostname) verification entirely instead, overriding
|
||||||
`--config-url-cacert-content` - **insecure**, only meant for a first bootstrap against a server whose
|
`--config-url-cacert-content` - **insecure**, only meant for a first bootstrap against a server whose
|
||||||
certificate isn't trustable, or trusted, yet by any other means.
|
certificate isn't trustable, or trusted, yet by any other means.
|
||||||
|
- `--user` (repeatable) names a user to also prepare *per-user* configuration for, on top of the usual
|
||||||
|
system-wide files, for the modules that have one: `go`, `nuget`, `php` (Composer), `python` (poetry) and
|
||||||
|
`rust`. The user's home directory is taken from `--src`'s own `/etc/passwd` entry when there is one,
|
||||||
|
otherwise assumed to be `/home/<user>` (`/root` for `root`).
|
||||||
|
- `--auto-users` does the same for every *regular* (non-system) user found in `--src`'s `/etc/passwd`: one with
|
||||||
|
a login shell (not `nologin`, `sync` or `false`) and a UID at or above `UID_MIN` (read from `--src`'s
|
||||||
|
`/etc/login.defs`, 1000 by default) - except `root`, always included regardless of its UID. It combines
|
||||||
|
freely with one or more `--user`.
|
||||||
- On `apply`, every module inspects the configuration and the source filesystem and decides for itself whether it has something to
|
- On `apply`, every module inspects the configuration and the source filesystem and decides for itself whether it has something to
|
||||||
do; only relevant modules touch the destination directory. For example, the configured Alpine repositories are only written if
|
do; only relevant modules touch the destination directory. For example, the configured Alpine repositories are only written if
|
||||||
`--src` can be identified as an Alpine filesystem (i.e. it has an `/etc/apk` directory); and a source cloning Debian's official
|
`--src` can be identified as an Alpine filesystem (i.e. it has an `/etc/apk` directory); and a source cloning Debian's official
|
||||||
@@ -95,6 +103,12 @@ id-configurator apply \
|
|||||||
--config-url-cacert-content "$(cat internal-ca.pem)" \
|
--config-url-cacert-content "$(cat internal-ca.pem)" \
|
||||||
--dst ./output
|
--dst ./output
|
||||||
|
|
||||||
|
# Also prepare per-user configuration (go, nuget, php, python, rust) for specific users
|
||||||
|
id-configurator apply --config config.yaml --dst ./output --user alice --user bob
|
||||||
|
|
||||||
|
# Same, but auto-detect every regular (non-system) user from --src's /etc/passwd
|
||||||
|
id-configurator apply --config config.yaml --src /path/to/rootfs --dst ./output --auto-users
|
||||||
|
|
||||||
# Validate a configuration without applying it
|
# Validate a configuration without applying it
|
||||||
id-configurator validate --config config.yaml
|
id-configurator validate --config config.yaml
|
||||||
|
|
||||||
@@ -145,6 +159,7 @@ configurations:
|
|||||||
- name: <string>
|
- name: <string>
|
||||||
url: <string>
|
url: <string>
|
||||||
key: <RSA public key, optional>
|
key: <RSA public key, optional>
|
||||||
|
key_filename: <string, optional> # name of the key file under /etc/apk/keys/, if not the derived default
|
||||||
url_to_replace: <fnmatch pattern, optional>
|
url_to_replace: <fnmatch pattern, optional>
|
||||||
yum:
|
yum:
|
||||||
repositories:
|
repositories:
|
||||||
@@ -175,6 +190,7 @@ configurations:
|
|||||||
repositories:
|
repositories:
|
||||||
- name: <string>
|
- name: <string>
|
||||||
url: <string>
|
url: <string>
|
||||||
|
is_sparse: <bool, optional, default false> # declares the registry's index as sparse+<url>
|
||||||
go:
|
go:
|
||||||
repositories:
|
repositories:
|
||||||
- name: <string>
|
- name: <string>
|
||||||
@@ -200,6 +216,22 @@ replaces Debian's default mirror if (and only if) it's actually there, without d
|
|||||||
given machine might already have. Leaving the field unset never disables anything - the configured repository
|
given machine might already have. Leaving the field unset never disables anything - the configured repository
|
||||||
is simply added alongside whatever is already present.
|
is simply added alongside whatever is already present.
|
||||||
|
|
||||||
|
### Non-HTTPS repositories
|
||||||
|
|
||||||
|
A repository URL doesn't have to be HTTPS - several modules automatically adjust the tool's configuration so
|
||||||
|
the plain-HTTP repository is actually usable, instead of silently producing a config the package manager
|
||||||
|
would refuse at run time:
|
||||||
|
|
||||||
|
- `python`: pip gets the repository's host added to `trusted-host`.
|
||||||
|
- `php`: Composer gets `secure-http` disabled, and `packagist.org` is disabled alongside it (an HTTP source
|
||||||
|
implies a private, non-internet setup where the public registry wouldn't be reachable anyway).
|
||||||
|
- `nuget`: the source gets `allowInsecureConnections="true"`.
|
||||||
|
- `java`: SBT's resolver gets `allowInsecureProtocol` appended. **Leiningen is the one exception**: its
|
||||||
|
standalone launcher refuses any non-HTTPS repository unconditionally, with no configuration able to change
|
||||||
|
that - a repository configured here simply won't be usable from Leiningen specifically.
|
||||||
|
- `go`, `rust`, `apt`, `apk`, `yum`: no adjustment is needed - these already work the same regardless of
|
||||||
|
scheme.
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
| Module | Applies to |
|
| Module | Applies to |
|
||||||
@@ -217,6 +249,9 @@ is simply added alongside whatever is already present.
|
|||||||
| `ruby` | Points RubyGems at the configured sources, replacing rubygems.org. |
|
| `ruby` | Points RubyGems at the configured sources, replacing rubygems.org. |
|
||||||
| `nuget` | Points NuGet at the configured package sources, replacing nuget.org. |
|
| `nuget` | Points NuGet at the configured package sources, replacing nuget.org. |
|
||||||
|
|
||||||
|
`go`, `nuget`, `php`, `python` and `rust` additionally honor `--user`/`--auto-users` (see "How it works" above),
|
||||||
|
writing the same per-user configuration under each such user's home directory.
|
||||||
|
|
||||||
This tool's own modular structure is meant to be extended: see `CLAUDE.md` for the module interface and how to add one.
|
This tool's own modular structure is meant to be extended: see `CLAUDE.md` for the module interface and how to add one.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the destination directory.
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
from id_configurator.context import Context
|
from id_configurator.context import Context
|
||||||
@@ -49,3 +50,25 @@ def sanitize_filename(name: str) -> str:
|
|||||||
create - instead of the single file the caller asked for.
|
create - instead of the single file the caller asked for.
|
||||||
"""
|
"""
|
||||||
return name.replace("/", "_").replace("\\", "_")
|
return name.replace("/", "_").replace("\\", "_")
|
||||||
|
|
||||||
|
|
||||||
|
_REPOSITORY_NAME_FORBIDDEN_CHARS = re.compile(r"[^A-Za-z0-9_-]")
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize_repository_name(name: str) -> str:
|
||||||
|
"""Replace every character of `name` that isn't a plain identifier
|
||||||
|
character (letters, digits, `_`, `-`) with `_`.
|
||||||
|
|
||||||
|
Several modules write a repository's name verbatim as a bare,
|
||||||
|
unquoted identifier in a generated config file - an INI section
|
||||||
|
header, a TOML table key, ... - where an unrestricted name could break
|
||||||
|
out of that syntax (e.g. `]`, a newline, or - for TOML - a literal
|
||||||
|
`.`, which would silently open extra, nested tables instead of naming
|
||||||
|
the one table it's meant to). Excluding `.` from the allowed
|
||||||
|
characters also means the result can never come out as exactly `.` or
|
||||||
|
`..`, which matter if the name is ever reused as a filesystem path
|
||||||
|
component (`sanitize_filename` alone wouldn't catch those, since it
|
||||||
|
only strips `/` and `\\`). Spaces and every other non-identifier
|
||||||
|
character are replaced the same way, for consistency across callers.
|
||||||
|
"""
|
||||||
|
return _REPOSITORY_NAME_FORBIDDEN_CHARS.sub("_", name)
|
||||||
|
|||||||
@@ -28,9 +28,20 @@ tool targets Docker images, which are built and run as root:
|
|||||||
- Ivy: `~/.ivy2/ivysettings.xml`, as a chain of `ibiblio` resolvers.
|
- Ivy: `~/.ivy2/ivysettings.xml`, as a chain of `ibiblio` resolvers.
|
||||||
- SBT: `~/.sbt/repositories`, the resolver override file SBT reads for its
|
- SBT: `~/.sbt/repositories`, the resolver override file SBT reads for its
|
||||||
own bootstrapping and, when combined with the `sbt.override.build.repos`
|
own bootstrapping and, when combined with the `sbt.override.build.repos`
|
||||||
system property, for every project's resolvers as well.
|
system property, for every project's resolvers as well. A repository
|
||||||
|
whose URL isn't HTTPS gets `, allowInsecureProtocol` appended to its
|
||||||
|
line - SBT's Coursier-backed resolver otherwise refuses it outright
|
||||||
|
("insecure protocol is unsupported"), unlike every other entry in
|
||||||
|
`~/.sbt/repositories` which takes no such suffix.
|
||||||
- Leiningen: `~/.lein/profiles.clj`, adding the repositories to the `:user`
|
- Leiningen: `~/.lein/profiles.clj`, adding the repositories to the `:user`
|
||||||
profile.
|
profile. Leiningen, alone among these, refuses a plain-HTTP repository
|
||||||
|
outright ("Tried to use insecure HTTP repository without TLS") - its
|
||||||
|
standalone `lein` launcher (`leiningen.core.main/-main`) unconditionally
|
||||||
|
registers an aborting wagon for the "http" scheme before even reading the
|
||||||
|
project/profile config, so there is no project.clj/profiles.clj setting
|
||||||
|
(there is no `:insecure` key anywhere in Leiningen's own source) that
|
||||||
|
can work around this: a non-HTTPS repository configured here will not be
|
||||||
|
usable from Leiningen specifically, regardless of what this module does.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
@@ -39,6 +50,7 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import jks
|
import jks
|
||||||
from cryptography import x509
|
from cryptography import x509
|
||||||
@@ -50,7 +62,7 @@ from cryptography.hazmat.primitives.serialization import (
|
|||||||
|
|
||||||
from id_configurator.config import JavaRepository, NamedContent
|
from id_configurator.config import JavaRepository, NamedContent
|
||||||
from id_configurator.context import Context
|
from id_configurator.context import Context
|
||||||
from id_configurator.modules.base import Module, register
|
from id_configurator.modules.base import Module, register, sanitize_repository_name
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -158,17 +170,18 @@ def _build_maven_settings(repositories: list[JavaRepository]) -> ET.Element:
|
|||||||
repositories_el = ET.SubElement(profile, "repositories")
|
repositories_el = ET.SubElement(profile, "repositories")
|
||||||
plugin_repositories_el = ET.SubElement(profile, "pluginRepositories")
|
plugin_repositories_el = ET.SubElement(profile, "pluginRepositories")
|
||||||
for repository in repositories:
|
for repository in repositories:
|
||||||
|
name = sanitize_repository_name(repository.name)
|
||||||
for parent, tag in (
|
for parent, tag in (
|
||||||
(repositories_el, "repository"),
|
(repositories_el, "repository"),
|
||||||
(plugin_repositories_el, "pluginRepository"),
|
(plugin_repositories_el, "pluginRepository"),
|
||||||
):
|
):
|
||||||
entry = ET.SubElement(parent, tag)
|
entry = ET.SubElement(parent, tag)
|
||||||
ET.SubElement(entry, "id").text = repository.name
|
ET.SubElement(entry, "id").text = name
|
||||||
ET.SubElement(entry, "url").text = repository.url
|
ET.SubElement(entry, "url").text = repository.url
|
||||||
active_profiles = ET.SubElement(settings, "activeProfiles")
|
active_profiles = ET.SubElement(settings, "activeProfiles")
|
||||||
ET.SubElement(active_profiles, "activeProfile").text = "id-configurator"
|
ET.SubElement(active_profiles, "activeProfile").text = "id-configurator"
|
||||||
mirror = ET.SubElement(ET.SubElement(settings, "mirrors"), "mirror")
|
mirror = ET.SubElement(ET.SubElement(settings, "mirrors"), "mirror")
|
||||||
ET.SubElement(mirror, "id").text = repositories[0].name
|
ET.SubElement(mirror, "id").text = sanitize_repository_name(repositories[0].name)
|
||||||
ET.SubElement(mirror, "url").text = repositories[0].url
|
ET.SubElement(mirror, "url").text = repositories[0].url
|
||||||
ET.SubElement(mirror, "mirrorOf").text = "*"
|
ET.SubElement(mirror, "mirrorOf").text = "*"
|
||||||
return settings
|
return settings
|
||||||
@@ -233,13 +246,18 @@ def _write_ivy_settings(context: Context, repositories: list[JavaRepository]) ->
|
|||||||
logger.info("configured ivy to use %d repositories", len(repositories))
|
logger.info("configured ivy to use %d repositories", len(repositories))
|
||||||
|
|
||||||
|
|
||||||
|
def _sbt_repository_line(repository: JavaRepository) -> str:
|
||||||
|
line = f" {repository.name}: {repository.url}"
|
||||||
|
if urlparse(repository.url).scheme.lower() != "https":
|
||||||
|
line += ", allowInsecureProtocol"
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
def _write_sbt_repositories(
|
def _write_sbt_repositories(
|
||||||
context: Context, repositories: list[JavaRepository]
|
context: Context, repositories: list[JavaRepository]
|
||||||
) -> None:
|
) -> None:
|
||||||
lines = ["[repositories]", " local"]
|
lines = ["[repositories]", " local"]
|
||||||
lines.extend(
|
lines.extend(_sbt_repository_line(repository) for repository in repositories)
|
||||||
f" {repository.name}: {repository.url}" for repository in repositories
|
|
||||||
)
|
|
||||||
context.write_file(_SBT_REPOSITORIES, ("\n".join(lines) + "\n").encode("utf-8"))
|
context.write_file(_SBT_REPOSITORIES, ("\n".join(lines) + "\n").encode("utf-8"))
|
||||||
logger.info("configured sbt to use %d repositories", len(repositories))
|
logger.info("configured sbt to use %d repositories", len(repositories))
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ PythonRepository entries instead of pypi.org, and to trust the root
|
|||||||
certificates installed by the certificates module.
|
certificates installed by the certificates module.
|
||||||
|
|
||||||
- pip: system-wide `/etc/pip.conf` (`index-url`/`extra-index-url`/`cert`).
|
- pip: system-wide `/etc/pip.conf` (`index-url`/`extra-index-url`/`cert`).
|
||||||
|
Any repository whose URL isn't HTTPS has its host added to
|
||||||
|
`trusted-host`, since pip otherwise refuses a plain HTTP index.
|
||||||
- uv: system-wide `/etc/uv/uv.toml` (`[[index]]` entries, `native-tls`).
|
- uv: system-wide `/etc/uv/uv.toml` (`[[index]]` entries, `native-tls`).
|
||||||
- poetry: `/root/.config/pypoetry/config.toml` (`repositories.*`/`certificates.*`).
|
- poetry: `/root/.config/pypoetry/config.toml` (`repositories.*`/`certificates.*`).
|
||||||
Poetry has no global "replace PyPI" switch: a project's `pyproject.toml`
|
Poetry has no global "replace PyPI" switch: a project's `pyproject.toml`
|
||||||
@@ -23,10 +25,11 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from id_configurator.config import PythonRepository
|
from id_configurator.config import PythonRepository
|
||||||
from id_configurator.context import Context
|
from id_configurator.context import Context
|
||||||
from id_configurator.modules.base import Module, register
|
from id_configurator.modules.base import Module, register, sanitize_repository_name
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -38,7 +41,24 @@ _DISTUTILS_GLOBS = ("usr/lib/python3.*", "usr/local/lib/python3.*")
|
|||||||
|
|
||||||
|
|
||||||
def _toml_string(value: str) -> str:
|
def _toml_string(value: str) -> str:
|
||||||
return json.dumps(value)
|
"""Render `value` as a TOML basic string.
|
||||||
|
|
||||||
|
JSON and TOML basic strings share the same escape syntax, so
|
||||||
|
`json.dumps` is a convenient way to produce one - *except* for
|
||||||
|
non-ASCII characters: with the default `ensure_ascii=True`, a
|
||||||
|
character outside the Basic Multilingual Plane (e.g. an emoji) comes
|
||||||
|
out as a UTF-16 surrogate pair (`\\uXXXX\\uXXXX`), which is valid JSON
|
||||||
|
but not valid TOML - TOML's `\\uXXXX` must itself be a Unicode scalar
|
||||||
|
value, not one half of a surrogate pair. `ensure_ascii=False` instead
|
||||||
|
leaves every non-ASCII character as a literal, raw UTF-8 character,
|
||||||
|
which TOML basic strings allow directly.
|
||||||
|
"""
|
||||||
|
return json.dumps(value, ensure_ascii=False)
|
||||||
|
|
||||||
|
|
||||||
|
def _trusted_host(repository: PythonRepository) -> str | None:
|
||||||
|
parsed = urlparse(repository.index_url)
|
||||||
|
return None if parsed.scheme.lower() == "https" else parsed.hostname
|
||||||
|
|
||||||
|
|
||||||
def _write_pip_conf(context: Context, repositories: list[PythonRepository]) -> None:
|
def _write_pip_conf(context: Context, repositories: list[PythonRepository]) -> None:
|
||||||
@@ -46,6 +66,12 @@ def _write_pip_conf(context: Context, repositories: list[PythonRepository]) -> N
|
|||||||
if len(repositories) > 1:
|
if len(repositories) > 1:
|
||||||
lines.append("extra-index-url =")
|
lines.append("extra-index-url =")
|
||||||
lines.extend(f" {repository.index_url}" for repository in repositories[1:])
|
lines.extend(f" {repository.index_url}" for repository in repositories[1:])
|
||||||
|
trusted_hosts = dict.fromkeys(
|
||||||
|
host for repository in repositories if (host := _trusted_host(repository))
|
||||||
|
)
|
||||||
|
if trusted_hosts:
|
||||||
|
lines.append("trusted-host =")
|
||||||
|
lines.extend(f" {host}" for host in trusted_hosts)
|
||||||
lines.append(f"cert = {_CA_BUNDLE}")
|
lines.append(f"cert = {_CA_BUNDLE}")
|
||||||
context.write_file(_PIP_CONF, ("\n".join(lines) + "\n").encode("utf-8"))
|
context.write_file(_PIP_CONF, ("\n".join(lines) + "\n").encode("utf-8"))
|
||||||
logger.info("configured pip to use %s", repositories[0].index_url)
|
logger.info("configured pip to use %s", repositories[0].index_url)
|
||||||
@@ -54,8 +80,9 @@ def _write_pip_conf(context: Context, repositories: list[PythonRepository]) -> N
|
|||||||
def _write_uv_toml(context: Context, repositories: list[PythonRepository]) -> None:
|
def _write_uv_toml(context: Context, repositories: list[PythonRepository]) -> None:
|
||||||
lines = ["native-tls = true", ""]
|
lines = ["native-tls = true", ""]
|
||||||
for position, repository in enumerate(repositories):
|
for position, repository in enumerate(repositories):
|
||||||
|
name = sanitize_repository_name(repository.name)
|
||||||
lines.append("[[index]]")
|
lines.append("[[index]]")
|
||||||
lines.append(f"name = {_toml_string(repository.name)}")
|
lines.append(f"name = {_toml_string(name)}")
|
||||||
lines.append(f"url = {_toml_string(repository.index_url)}")
|
lines.append(f"url = {_toml_string(repository.index_url)}")
|
||||||
if position == 0:
|
if position == 0:
|
||||||
lines.append("default = true")
|
lines.append("default = true")
|
||||||
@@ -69,10 +96,11 @@ def _write_poetry_config(
|
|||||||
) -> None:
|
) -> None:
|
||||||
lines = []
|
lines = []
|
||||||
for repository in repositories:
|
for repository in repositories:
|
||||||
lines.append(f"[repositories.{repository.name}]")
|
name = sanitize_repository_name(repository.name)
|
||||||
|
lines.append(f"[repositories.{name}]")
|
||||||
lines.append(f"url = {_toml_string(repository.index_url)}")
|
lines.append(f"url = {_toml_string(repository.index_url)}")
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.append(f"[certificates.{repository.name}]")
|
lines.append(f"[certificates.{name}]")
|
||||||
lines.append(f"cert = {_toml_string(_CA_BUNDLE)}")
|
lines.append(f"cert = {_toml_string(_CA_BUNDLE)}")
|
||||||
lines.append("")
|
lines.append("")
|
||||||
content = ("\n".join(lines).rstrip() + "\n").encode("utf-8")
|
content = ("\n".join(lines).rstrip() + "\n").encode("utf-8")
|
||||||
|
|||||||
@@ -29,29 +29,14 @@ which this module otherwise has no visibility into.
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
|
||||||
|
|
||||||
from id_configurator.config import RustRepository
|
from id_configurator.config import RustRepository
|
||||||
from id_configurator.context import Context
|
from id_configurator.context import Context
|
||||||
from id_configurator.modules.base import Module, register
|
from id_configurator.modules.base import Module, register, sanitize_repository_name
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
_CARGO_CONFIG = ".cargo/config.toml"
|
_CARGO_CONFIG = ".cargo/config.toml"
|
||||||
_REPOSITORY_NAME_FORBIDDEN_CHARS = re.compile(r"[^A-Za-z0-9_-]")
|
|
||||||
|
|
||||||
|
|
||||||
def _sanitize_repository_name(name: str) -> str:
|
|
||||||
"""Replace every character of `name` that isn't a plain identifier
|
|
||||||
character with `_`.
|
|
||||||
|
|
||||||
`name` is written verbatim both as a TOML table key (`[source.name]`,
|
|
||||||
`[registries.name]`) and inside a quoted string (`replace-with =
|
|
||||||
"name"`): an unrestricted name could break out of the table header or
|
|
||||||
string, or (via a literal `.`) silently create extra, nested tables
|
|
||||||
instead of naming the one table it is meant to.
|
|
||||||
"""
|
|
||||||
return _REPOSITORY_NAME_FORBIDDEN_CHARS.sub("_", name)
|
|
||||||
|
|
||||||
|
|
||||||
def _index_url(repository: RustRepository) -> str:
|
def _index_url(repository: RustRepository) -> str:
|
||||||
@@ -60,7 +45,7 @@ def _index_url(repository: RustRepository) -> str:
|
|||||||
|
|
||||||
def _write_cargo_config(context: Context, repositories: list[RustRepository]) -> None:
|
def _write_cargo_config(context: Context, repositories: list[RustRepository]) -> None:
|
||||||
primary = repositories[0]
|
primary = repositories[0]
|
||||||
primary_name = _sanitize_repository_name(primary.name)
|
primary_name = sanitize_repository_name(primary.name)
|
||||||
lines = [
|
lines = [
|
||||||
"[source.crates-io]",
|
"[source.crates-io]",
|
||||||
f'replace-with = "{primary_name}"',
|
f'replace-with = "{primary_name}"',
|
||||||
@@ -69,7 +54,7 @@ def _write_cargo_config(context: Context, repositories: list[RustRepository]) ->
|
|||||||
f'registry = "{_index_url(primary)}"',
|
f'registry = "{_index_url(primary)}"',
|
||||||
]
|
]
|
||||||
for repository in repositories[1:]:
|
for repository in repositories[1:]:
|
||||||
name = _sanitize_repository_name(repository.name)
|
name = sanitize_repository_name(repository.name)
|
||||||
lines += [
|
lines += [
|
||||||
"",
|
"",
|
||||||
f"[registries.{name}]",
|
f"[registries.{name}]",
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ from __future__ import annotations
|
|||||||
import configparser
|
import configparser
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import logging
|
import logging
|
||||||
import re
|
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
@@ -41,25 +40,17 @@ from io import StringIO
|
|||||||
|
|
||||||
from id_configurator.config import NamedContent, YumRepository
|
from id_configurator.config import NamedContent, YumRepository
|
||||||
from id_configurator.context import Context
|
from id_configurator.context import Context
|
||||||
from id_configurator.modules.base import Module, register, sanitize_filename
|
from id_configurator.modules.base import (
|
||||||
|
Module,
|
||||||
|
register,
|
||||||
|
sanitize_filename,
|
||||||
|
sanitize_repository_name,
|
||||||
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
_REPOS_DIR = "etc/yum.repos.d"
|
_REPOS_DIR = "etc/yum.repos.d"
|
||||||
_RPM_GPG_DIR = "etc/pki/rpm-gpg"
|
_RPM_GPG_DIR = "etc/pki/rpm-gpg"
|
||||||
_REPOSITORY_NAME_FORBIDDEN_CHARS = re.compile(r"[^A-Za-z0-9._-]")
|
|
||||||
|
|
||||||
|
|
||||||
def _sanitize_repository_name(name: str) -> str:
|
|
||||||
"""Replace every character of `name` that isn't a plain identifier
|
|
||||||
character with `_`.
|
|
||||||
|
|
||||||
`name` is written verbatim as the `.repo` file's INI section header
|
|
||||||
(`[name]`): an unrestricted name (containing `]`, a newline, ...) could
|
|
||||||
otherwise inject extra, attacker-controlled sections into the file
|
|
||||||
instead of just naming the one section it is meant to.
|
|
||||||
"""
|
|
||||||
return _REPOSITORY_NAME_FORBIDDEN_CHARS.sub("_", name)
|
|
||||||
|
|
||||||
|
|
||||||
def _disable_repo_content(content: str, patterns: Sequence[str]) -> str:
|
def _disable_repo_content(content: str, patterns: Sequence[str]) -> str:
|
||||||
@@ -105,7 +96,7 @@ def _disable_existing_repos(context: Context, patterns: Sequence[str]) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def _write_repo_file(context: Context, repository: YumRepository) -> None:
|
def _write_repo_file(context: Context, repository: YumRepository) -> None:
|
||||||
name = _sanitize_repository_name(repository.name)
|
name = sanitize_repository_name(repository.name)
|
||||||
lines = [
|
lines = [
|
||||||
f"[{name}]",
|
f"[{name}]",
|
||||||
f"name={name}",
|
f"name={name}",
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ def parse_passwd(content: str) -> list[PasswdEntry]:
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
entries.append(
|
entries.append(
|
||||||
PasswdEntry(name=fields[0], uid=uid, home=fields[5], shell=fields[6]) # noqa: B604
|
PasswdEntry(name=fields[0], uid=uid, home=fields[5], shell=fields[6])
|
||||||
)
|
)
|
||||||
return entries
|
return entries
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -44,7 +44,7 @@ maintainers = [
|
|||||||
name = "id-configurator"
|
name = "id-configurator"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.13"
|
requires-python = ">=3.13"
|
||||||
version = "2026.10.4"
|
version = "2026.10.9"
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
id-configurator = "id_configurator:main"
|
id-configurator = "id_configurator:main"
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ configurations:
|
|||||||
sources: []
|
sources: []
|
||||||
apk:
|
apk:
|
||||||
repositories:
|
repositories:
|
||||||
- name: demo
|
- name: 'demo _.-/\$.:@;''"'
|
||||||
url: https://host.docker.internal:{{ 'APK_REPO_PORT' | env }}/
|
{% set scheme = 'APK_REPO_SCHEME' | env %}
|
||||||
|
url: {{ scheme }}://host.docker.internal:{{ ('APK_REPO_PORT' if scheme == 'https' else 'APK_REPO_HTTP_PORT') | env }}/
|
||||||
url_to_replace: https://dl-cdn.alpinelinux.org/*
|
url_to_replace: https://dl-cdn.alpinelinux.org/*
|
||||||
key: |
|
key: |
|
||||||
{{ 'dockerfiles/repos/040d0af5f97a0a44.rsa.pub' | file | indent(8, first=true) }}
|
{{ 'dockerfiles/repos/040d0af5f97a0a44.rsa.pub' | file | indent(8, first=true) }}
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ configurations:
|
|||||||
- name: demo
|
- name: demo
|
||||||
types: [deb]
|
types: [deb]
|
||||||
uris:
|
uris:
|
||||||
- https://host.docker.internal:{{ 'APT_REPO_PORT' | env }}/
|
{% set scheme = 'APT_REPO_SCHEME' | env %}
|
||||||
|
- {{ scheme }}://host.docker.internal:{{ ('APT_REPO_PORT' if scheme == 'https' else 'APT_REPO_HTTP_PORT') | env }}/
|
||||||
suites: ["./"]
|
suites: ["./"]
|
||||||
uri-to-replace: http://deb.debian.org/*
|
uri-to-replace: http://deb.debian.org/*
|
||||||
signed-by: |
|
signed-by: |
|
||||||
|
|||||||
@@ -25,8 +25,9 @@ configurations:
|
|||||||
repositories: []
|
repositories: []
|
||||||
go:
|
go:
|
||||||
repositories:
|
repositories:
|
||||||
- name: demo
|
- name: 'demo _.-/\$.:@;''"'
|
||||||
url: https://host.docker.internal:{{ 'GO_REPO_PORT' | env }}/
|
{% set scheme = 'GO_REPO_SCHEME' | env %}
|
||||||
|
url: {{ scheme }}://host.docker.internal:{{ ('GO_REPO_PORT' if scheme == 'https' else 'GO_REPO_HTTP_PORT') | env }}/
|
||||||
ruby:
|
ruby:
|
||||||
repositories: []
|
repositories: []
|
||||||
nuget:
|
nuget:
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ configurations:
|
|||||||
# during the Dockerfile's warm-up step. All other tools just see it as
|
# during the Dockerfile's warm-up step. All other tools just see it as
|
||||||
# an ordinary repository, and find the test artifact here.
|
# an ordinary repository, and find the test artifact here.
|
||||||
- name: central
|
- name: central
|
||||||
url: https://host.docker.internal:{{ 'JAVA_REPO_PORT' | env }}/
|
{% set scheme = 'JAVA_REPO_SCHEME' | env %}
|
||||||
|
url: {{ scheme }}://host.docker.internal:{{ ('JAVA_REPO_PORT' if scheme == 'https' else 'JAVA_REPO_HTTP_PORT') | env }}/
|
||||||
# Second entry: only SBT needs this. With
|
# Second entry: only SBT needs this. With
|
||||||
# -Dsbt.override.build.repos=true (the only way SBT actually consults
|
# -Dsbt.override.build.repos=true (the only way SBT actually consults
|
||||||
# this file for project dependencies, not just its own bootstrap), the
|
# this file for project dependencies, not just its own bootstrap), the
|
||||||
|
|||||||
@@ -21,8 +21,9 @@ configurations:
|
|||||||
repositories: []
|
repositories: []
|
||||||
npm:
|
npm:
|
||||||
repositories:
|
repositories:
|
||||||
- name: demo
|
- name: 'demo _.-/\$.:@;''"'
|
||||||
url: https://host.docker.internal:{{ 'NPM_REPO_PORT' | env }}/
|
{% set scheme = 'NPM_REPO_SCHEME' | env %}
|
||||||
|
url: {{ scheme }}://host.docker.internal:{{ ('NPM_REPO_PORT' if scheme == 'https' else 'NPM_REPO_HTTP_PORT') | env }}/
|
||||||
rust:
|
rust:
|
||||||
repositories: []
|
repositories: []
|
||||||
go:
|
go:
|
||||||
|
|||||||
@@ -29,5 +29,6 @@ configurations:
|
|||||||
repositories: []
|
repositories: []
|
||||||
nuget:
|
nuget:
|
||||||
repositories:
|
repositories:
|
||||||
- name: demo
|
- name: 'demo _.-/\$.:@;''"'
|
||||||
url: https://host.docker.internal:{{ 'NUGET_REPO_PORT' | env }}/index.json
|
{% set scheme = 'NUGET_REPO_SCHEME' | env %}
|
||||||
|
url: {{ scheme }}://host.docker.internal:{{ ('NUGET_REPO_PORT' if scheme == 'https' else 'NUGET_REPO_HTTP_PORT') | env }}/index.json
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ configurations:
|
|||||||
repositories: []
|
repositories: []
|
||||||
php:
|
php:
|
||||||
repositories:
|
repositories:
|
||||||
- name: demo
|
- name: 'demo _.-/\$.:@;''"'
|
||||||
url: https://host.docker.internal:{{ 'PHP_REPO_PORT' | env }}/
|
{% set scheme = 'PHP_REPO_SCHEME' | env %}
|
||||||
|
url: {{ scheme }}://host.docker.internal:{{ ('PHP_REPO_PORT' if scheme == 'https' else 'PHP_REPO_HTTP_PORT') | env }}/
|
||||||
npm:
|
npm:
|
||||||
repositories: []
|
repositories: []
|
||||||
rust:
|
rust:
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ configurations:
|
|||||||
keys: []
|
keys: []
|
||||||
python:
|
python:
|
||||||
repositories:
|
repositories:
|
||||||
- name: demo
|
- name: 'demo _.-/\$.:@;''"'
|
||||||
index-url: https://host.docker.internal:{{ 'PYPI_REPO_PORT' | env }}/simple/
|
{% set scheme = 'PYPI_REPO_SCHEME' | env %}
|
||||||
|
index-url: {{ scheme }}://host.docker.internal:{{ ('PYPI_REPO_PORT' if scheme == 'https' else 'PYPI_REPO_HTTP_PORT') | env }}/simple/
|
||||||
java:
|
java:
|
||||||
repositories: []
|
repositories: []
|
||||||
php:
|
php:
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ configurations:
|
|||||||
repositories: []
|
repositories: []
|
||||||
ruby:
|
ruby:
|
||||||
repositories:
|
repositories:
|
||||||
- name: demo
|
- name: 'demo _.-/\$.:@;''"'
|
||||||
url: https://host.docker.internal:{{ 'RUBY_REPO_PORT' | env }}/
|
{% set scheme = 'RUBY_REPO_SCHEME' | env %}
|
||||||
|
url: {{ scheme }}://host.docker.internal:{{ ('RUBY_REPO_PORT' if scheme == 'https' else 'RUBY_REPO_HTTP_PORT') | env }}/
|
||||||
nuget:
|
nuget:
|
||||||
repositories: []
|
repositories: []
|
||||||
|
|||||||
@@ -23,8 +23,10 @@ configurations:
|
|||||||
repositories: []
|
repositories: []
|
||||||
rust:
|
rust:
|
||||||
repositories:
|
repositories:
|
||||||
- name: demo
|
- name: 'demo _.-/\$.:@;''"'
|
||||||
url: https://host.docker.internal:{{ 'CARGO_REPO_PORT' | env }}/
|
{% set scheme = 'CARGO_REPO_SCHEME' | env %}
|
||||||
|
url: {{ scheme }}://host.docker.internal:{{ ('CARGO_REPO_PORT' if scheme == 'https' else 'CARGO_REPO_HTTP_PORT') | env }}/
|
||||||
|
is_sparse: true
|
||||||
go:
|
go:
|
||||||
repositories: []
|
repositories: []
|
||||||
ruby:
|
ruby:
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ configurations:
|
|||||||
repositories: []
|
repositories: []
|
||||||
yum:
|
yum:
|
||||||
repositories:
|
repositories:
|
||||||
- name: demo
|
- name: 'demo _.-/\$.:@;''"'
|
||||||
index-url: https://host.docker.internal:{{ 'YUM_REPO_PORT' | env }}/
|
{% set scheme = 'YUM_REPO_SCHEME' | env %}
|
||||||
|
index-url: {{ scheme }}://host.docker.internal:{{ ('YUM_REPO_PORT' if scheme == 'https' else 'YUM_REPO_HTTP_PORT') | env }}/
|
||||||
index-url-to-replace: https://mirrors.rockylinux.org/*
|
index-url-to-replace: https://mirrors.rockylinux.org/*
|
||||||
keys: []
|
keys: []
|
||||||
python:
|
python:
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ COPY --from=target / /src/
|
|||||||
COPY --from=generated-config Java.yaml /config.yaml
|
COPY --from=generated-config Java.yaml /config.yaml
|
||||||
RUN id-configurator apply --config /config.yaml --src /src --dst /dst
|
RUN id-configurator apply --config /config.yaml --src /src --dst /dst
|
||||||
FROM target AS runtime
|
FROM target AS runtime
|
||||||
|
ARG JAVA_REPO_SCHEME
|
||||||
# Every build tool the `java` module configures: Maven itself (already part
|
# Every build tool the `java` module configures: Maven itself (already part
|
||||||
# of this image), Gradle, Ivy and Leiningen (all packaged for this Ubuntu
|
# of this image), Gradle, Ivy and Leiningen (all packaged for this Ubuntu
|
||||||
# base), and SBT (no package available, fetched as a plain release tarball).
|
# base), and SBT (no package available, fetched as a plain release tarball).
|
||||||
@@ -43,12 +44,23 @@ RUN java -jar /usr/share/java/ivy.jar -settings /root/.ivy2/ivysettings.xml \
|
|||||||
-retrieve "/tmp/ivyretrieve/[artifact]-[revision].[ext]" \
|
-retrieve "/tmp/ivyretrieve/[artifact]-[revision].[ext]" \
|
||||||
&& test -f /tmp/ivyretrieve/idconfiguratortestpkg-0.0.1.jar
|
&& test -f /tmp/ivyretrieve/idconfiguratortestpkg-0.0.1.jar
|
||||||
|
|
||||||
|
# Leiningen's standalone launcher unconditionally refuses any plain-HTTP
|
||||||
|
# repository ("Tried to use insecure HTTP repository without TLS") before
|
||||||
|
# even reading project.clj/profiles.clj - there is no `:insecure` key or
|
||||||
|
# other configuration escape hatch for this (confirmed from Leiningen's own
|
||||||
|
# source: leiningen.core.main/-main registers an aborting wagon for the
|
||||||
|
# "http" scheme unconditionally). So this check is skipped for the
|
||||||
|
# module-java-http variant: no id-configurator config could make it pass.
|
||||||
RUN mkdir -p /tmp/leintest && cd /tmp/leintest \
|
RUN mkdir -p /tmp/leintest && cd /tmp/leintest \
|
||||||
&& cat > project.clj <<'EOF'
|
&& cat > project.clj <<'EOF'
|
||||||
(defproject leintest "0.1.0"
|
(defproject leintest "0.1.0"
|
||||||
:dependencies [[org.interdiode/idconfiguratortestpkg "0.0.1"]])
|
:dependencies [[org.interdiode/idconfiguratortestpkg "0.0.1"]])
|
||||||
EOF
|
EOF
|
||||||
RUN cd /tmp/leintest && lein deps :tree | grep -q idconfiguratortestpkg
|
RUN if [ "$JAVA_REPO_SCHEME" = "https" ]; then \
|
||||||
|
cd /tmp/leintest && lein deps :tree | grep -q idconfiguratortestpkg; \
|
||||||
|
else \
|
||||||
|
echo "skipping leiningen: it cannot use a non-HTTPS repository"; \
|
||||||
|
fi
|
||||||
|
|
||||||
RUN mkdir -p /tmp/sbttest/project \
|
RUN mkdir -p /tmp/sbttest/project \
|
||||||
&& cat > /tmp/sbttest/build.sbt <<'EOF'
|
&& cat > /tmp/sbttest/build.sbt <<'EOF'
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ COPY --from=generated-config Python.yaml /config.yaml
|
|||||||
RUN id-configurator apply --config /config.yaml --src /src --dst /dst
|
RUN id-configurator apply --config /config.yaml --src /src --dst /dst
|
||||||
FROM target AS runtime
|
FROM target AS runtime
|
||||||
ARG PYPI_REPO_PORT
|
ARG PYPI_REPO_PORT
|
||||||
|
ARG PYPI_REPO_SCHEME
|
||||||
# Warm up uv and poetry themselves from the real, network-reachable PyPI
|
# Warm up uv and poetry themselves from the real, network-reachable PyPI
|
||||||
# while the default index is still in place, so the actual tests below
|
# while the default index is still in place, so the actual tests below
|
||||||
# never need anything but the fixture repository configured by
|
# never need anything but the fixture repository configured by
|
||||||
@@ -20,5 +21,5 @@ RUN uv pip install --system idconfiguratortestpkg \
|
|||||||
&& python3 -c "import idconfiguratortestpkg"
|
&& python3 -c "import idconfiguratortestpkg"
|
||||||
RUN mkdir -p /tmp/poetrytest && cd /tmp/poetrytest \
|
RUN mkdir -p /tmp/poetrytest && cd /tmp/poetrytest \
|
||||||
&& poetry init -n --name poetrytest \
|
&& poetry init -n --name poetrytest \
|
||||||
&& poetry source add --priority explicit demo "https://host.docker.internal:${PYPI_REPO_PORT}/simple/" \
|
&& poetry source add --priority explicit demo "${PYPI_REPO_SCHEME}://host.docker.internal:${PYPI_REPO_PORT}/simple/" \
|
||||||
&& poetry add idconfiguratortestpkg --source demo
|
&& poetry add idconfiguratortestpkg --source demo
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ COPY --from=generated-config Python.yaml /config.yaml
|
|||||||
RUN id-configurator apply --config /config.yaml --src /src --dst /dst
|
RUN id-configurator apply --config /config.yaml --src /src --dst /dst
|
||||||
FROM target AS runtime
|
FROM target AS runtime
|
||||||
ARG PYPI_REPO_PORT
|
ARG PYPI_REPO_PORT
|
||||||
|
ARG PYPI_REPO_SCHEME
|
||||||
# Warm up uv and poetry themselves from the real, network-reachable PyPI
|
# Warm up uv and poetry themselves from the real, network-reachable PyPI
|
||||||
# while the default index is still in place, so the actual tests below
|
# while the default index is still in place, so the actual tests below
|
||||||
# never need anything but the fixture repository configured by
|
# never need anything but the fixture repository configured by
|
||||||
@@ -20,5 +21,5 @@ RUN uv pip install --system idconfiguratortestpkg \
|
|||||||
&& python3 -c "import idconfiguratortestpkg"
|
&& python3 -c "import idconfiguratortestpkg"
|
||||||
RUN mkdir -p /tmp/poetrytest && cd /tmp/poetrytest \
|
RUN mkdir -p /tmp/poetrytest && cd /tmp/poetrytest \
|
||||||
&& poetry init -n --name poetrytest \
|
&& poetry init -n --name poetrytest \
|
||||||
&& poetry source add --priority explicit demo "https://host.docker.internal:${PYPI_REPO_PORT}/simple/" \
|
&& poetry source add --priority explicit demo "${PYPI_REPO_SCHEME}://host.docker.internal:${PYPI_REPO_PORT}/simple/" \
|
||||||
&& poetry add idconfiguratortestpkg --source demo
|
&& poetry add idconfiguratortestpkg --source demo
|
||||||
|
|||||||
@@ -8,3 +8,13 @@ server {
|
|||||||
root /srv;
|
root /srv;
|
||||||
autoindex off;
|
autoindex off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Plain-HTTP listener, for the module-*-http tox envs that verify id-configurator
|
||||||
|
# correctly configures a non-HTTPS repository.
|
||||||
|
server {
|
||||||
|
listen 8080 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /srv;
|
||||||
|
autoindex off;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,3 +8,13 @@ server {
|
|||||||
root /srv;
|
root /srv;
|
||||||
autoindex off;
|
autoindex off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Plain-HTTP listener, for the module-*-http tox envs that verify id-configurator
|
||||||
|
# correctly configures a non-HTTPS repository.
|
||||||
|
server {
|
||||||
|
listen 8080 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /srv;
|
||||||
|
autoindex off;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,10 +12,28 @@ server {
|
|||||||
# templates, since the host:port this fixture is actually reached on is
|
# templates, since the host:port this fixture is actually reached on is
|
||||||
# only known once tox-docker starts the container, not at image-build
|
# only known once tox-docker starts the container, not at image-build
|
||||||
# time. $http_host reflects exactly what the client (cargo) used to
|
# time. $http_host reflects exactly what the client (cargo) used to
|
||||||
# connect, e.g. host.docker.internal:55123.
|
# connect, e.g. host.docker.internal:55123; $scheme likewise reflects
|
||||||
|
# whichever of this file's two listeners actually served the request.
|
||||||
location = /config.json {
|
location = /config.json {
|
||||||
default_type application/json;
|
default_type application/json;
|
||||||
sub_filter '__BASE_URL__' 'https://$http_host';
|
sub_filter '__BASE_URL__' '$scheme://$http_host';
|
||||||
|
sub_filter_once off;
|
||||||
|
sub_filter_types application/json;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Plain-HTTP listener, for the module-rust-http tox env that verifies
|
||||||
|
# id-configurator correctly configures a non-HTTPS repository.
|
||||||
|
server {
|
||||||
|
listen 8080 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /srv;
|
||||||
|
autoindex off;
|
||||||
|
|
||||||
|
location = /config.json {
|
||||||
|
default_type application/json;
|
||||||
|
sub_filter '__BASE_URL__' '$scheme://$http_host';
|
||||||
sub_filter_once off;
|
sub_filter_once off;
|
||||||
sub_filter_types application/json;
|
sub_filter_types application/json;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,3 +8,13 @@ server {
|
|||||||
root /srv;
|
root /srv;
|
||||||
autoindex off;
|
autoindex off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Plain-HTTP listener, for the module-*-http tox envs that verify id-configurator
|
||||||
|
# correctly configures a non-HTTPS repository.
|
||||||
|
server {
|
||||||
|
listen 8080 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /srv;
|
||||||
|
autoindex off;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,3 +8,13 @@ server {
|
|||||||
root /srv;
|
root /srv;
|
||||||
autoindex off;
|
autoindex off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Plain-HTTP listener, for the module-*-http tox envs that verify id-configurator
|
||||||
|
# correctly configures a non-HTTPS repository.
|
||||||
|
server {
|
||||||
|
listen 8080 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /srv;
|
||||||
|
autoindex off;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,10 +12,29 @@ server {
|
|||||||
# its tarball URL, since the host:port this fixture is actually reached
|
# its tarball URL, since the host:port this fixture is actually reached
|
||||||
# on is only known once tox-docker starts the container, not at
|
# on is only known once tox-docker starts the container, not at
|
||||||
# image-build time. $http_host reflects exactly what the client (npm)
|
# image-build time. $http_host reflects exactly what the client (npm)
|
||||||
# used to connect, e.g. host.docker.internal:55123.
|
# used to connect, e.g. host.docker.internal:55123; $scheme likewise
|
||||||
|
# reflects whichever of this file's two listeners actually served the
|
||||||
|
# request.
|
||||||
location = /idconfiguratortestpkg {
|
location = /idconfiguratortestpkg {
|
||||||
default_type application/json;
|
default_type application/json;
|
||||||
sub_filter '__BASE_URL__' 'https://$http_host';
|
sub_filter '__BASE_URL__' '$scheme://$http_host';
|
||||||
|
sub_filter_once off;
|
||||||
|
sub_filter_types application/json;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Plain-HTTP listener, for the module-npm-http tox env that verifies
|
||||||
|
# id-configurator correctly configures a non-HTTPS repository.
|
||||||
|
server {
|
||||||
|
listen 8080 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /srv;
|
||||||
|
autoindex off;
|
||||||
|
|
||||||
|
location = /idconfiguratortestpkg {
|
||||||
|
default_type application/json;
|
||||||
|
sub_filter '__BASE_URL__' '$scheme://$http_host';
|
||||||
sub_filter_once off;
|
sub_filter_once off;
|
||||||
sub_filter_types application/json;
|
sub_filter_types application/json;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,28 @@ server {
|
|||||||
# fields, since the host:port this fixture is actually reached on is
|
# fields, since the host:port this fixture is actually reached on is
|
||||||
# only known once tox-docker starts the container, not at image-build
|
# only known once tox-docker starts the container, not at image-build
|
||||||
# time. $http_host reflects exactly what the client (nuget) used to
|
# time. $http_host reflects exactly what the client (nuget) used to
|
||||||
# connect, e.g. host.docker.internal:55123.
|
# connect, e.g. host.docker.internal:55123; $scheme likewise reflects
|
||||||
|
# whichever of this file's two listeners actually served the request.
|
||||||
location = /index.json {
|
location = /index.json {
|
||||||
default_type application/json;
|
default_type application/json;
|
||||||
sub_filter '__BASE_URL__' 'https://$http_host';
|
sub_filter '__BASE_URL__' '$scheme://$http_host';
|
||||||
|
sub_filter_once off;
|
||||||
|
sub_filter_types application/json;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Plain-HTTP listener, for the module-nuget-http tox env that verifies
|
||||||
|
# id-configurator correctly configures a non-HTTPS repository.
|
||||||
|
server {
|
||||||
|
listen 8080 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /srv;
|
||||||
|
autoindex off;
|
||||||
|
|
||||||
|
location = /index.json {
|
||||||
|
default_type application/json;
|
||||||
|
sub_filter '__BASE_URL__' '$scheme://$http_host';
|
||||||
sub_filter_once off;
|
sub_filter_once off;
|
||||||
sub_filter_types application/json;
|
sub_filter_types application/json;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,28 @@ server {
|
|||||||
# since the host:port this fixture is actually reached on is only known
|
# since the host:port this fixture is actually reached on is only known
|
||||||
# once tox-docker starts the container, not at image-build time.
|
# once tox-docker starts the container, not at image-build time.
|
||||||
# $http_host reflects exactly what the client (Composer) used to
|
# $http_host reflects exactly what the client (Composer) used to
|
||||||
# connect, e.g. host.docker.internal:55123.
|
# connect, e.g. host.docker.internal:55123; $scheme likewise reflects
|
||||||
|
# whichever of this file's two listeners actually served the request.
|
||||||
location = /packages.json {
|
location = /packages.json {
|
||||||
default_type application/json;
|
default_type application/json;
|
||||||
sub_filter '__BASE_URL__' 'https://$http_host';
|
sub_filter '__BASE_URL__' '$scheme://$http_host';
|
||||||
|
sub_filter_once off;
|
||||||
|
sub_filter_types application/json;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Plain-HTTP listener, for the module-php-http tox env that verifies
|
||||||
|
# id-configurator correctly configures a non-HTTPS repository.
|
||||||
|
server {
|
||||||
|
listen 8080 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /srv;
|
||||||
|
autoindex off;
|
||||||
|
|
||||||
|
location = /packages.json {
|
||||||
|
default_type application/json;
|
||||||
|
sub_filter '__BASE_URL__' '$scheme://$http_host';
|
||||||
sub_filter_once off;
|
sub_filter_once off;
|
||||||
sub_filter_types application/json;
|
sub_filter_types application/json;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,3 +8,13 @@ server {
|
|||||||
root /srv;
|
root /srv;
|
||||||
autoindex off;
|
autoindex off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Plain-HTTP listener, for the module-*-http tox envs that verify id-configurator
|
||||||
|
# correctly configures a non-HTTPS repository.
|
||||||
|
server {
|
||||||
|
listen 8080 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /srv;
|
||||||
|
autoindex off;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,3 +8,13 @@ server {
|
|||||||
root /srv;
|
root /srv;
|
||||||
autoindex off;
|
autoindex off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Plain-HTTP listener, for the module-*-http tox envs that verify id-configurator
|
||||||
|
# correctly configures a non-HTTPS repository.
|
||||||
|
server {
|
||||||
|
listen 8080 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /srv;
|
||||||
|
autoindex off;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,3 +8,13 @@ server {
|
|||||||
root /srv;
|
root /srv;
|
||||||
autoindex off;
|
autoindex off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Plain-HTTP listener, for the module-*-http tox envs that verify id-configurator
|
||||||
|
# correctly configures a non-HTTPS repository.
|
||||||
|
server {
|
||||||
|
listen 8080 default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /srv;
|
||||||
|
autoindex off;
|
||||||
|
}
|
||||||
|
|||||||
@@ -339,6 +339,31 @@ def test_apply_writes_sbt_repositories(tmp_path) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_marks_non_https_sbt_repository_as_insecure(tmp_path) -> None:
|
||||||
|
data = {
|
||||||
|
"uuid": "12345678-1234-5678-1234-567812345678",
|
||||||
|
"organisation": "InterDiode",
|
||||||
|
"configurations": {
|
||||||
|
"java": {
|
||||||
|
"repositories": [
|
||||||
|
{"name": "interdiode", "url": "http://example.invalid/maven"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
dst = tmp_path / "dst"
|
||||||
|
context = Context(config=make_config(data), dst=dst, src=None)
|
||||||
|
|
||||||
|
JavaModule().apply(context)
|
||||||
|
|
||||||
|
repositories = (dst / "root/.sbt/repositories").read_text(encoding="utf-8")
|
||||||
|
assert repositories == (
|
||||||
|
"[repositories]\n"
|
||||||
|
" local\n"
|
||||||
|
" interdiode: http://example.invalid/maven, allowInsecureProtocol\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_apply_writes_lein_profiles(tmp_path) -> None:
|
def test_apply_writes_lein_profiles(tmp_path) -> None:
|
||||||
dst = tmp_path / "dst"
|
dst = tmp_path / "dst"
|
||||||
context = Context(config=make_config(TWO_REPOS_CONFIG), dst=dst, src=None)
|
context = Context(config=make_config(TWO_REPOS_CONFIG), dst=dst, src=None)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import tomllib
|
||||||
|
|
||||||
from id_configurator.config import Configuration
|
from id_configurator.config import Configuration
|
||||||
from id_configurator.context import Context
|
from id_configurator.context import Context
|
||||||
from id_configurator.modules.python import PythonModule
|
from id_configurator.modules.python import PythonModule
|
||||||
@@ -76,6 +78,111 @@ def test_apply_single_repository(tmp_path) -> None:
|
|||||||
assert not (dst / "usr/lib").exists()
|
assert not (dst / "usr/lib").exists()
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_sanitizes_uv_index_name_with_non_bmp_characters(tmp_path) -> None:
|
||||||
|
data = {
|
||||||
|
"uuid": "12345678-1234-5678-1234-567812345678",
|
||||||
|
"organisation": "InterDiode",
|
||||||
|
"configurations": {
|
||||||
|
"python": {
|
||||||
|
"repositories": [
|
||||||
|
{"name": "demo 😀", "index-url": "https://example.invalid/simple"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
config = Configuration.model_validate(data)
|
||||||
|
dst = tmp_path / "dst"
|
||||||
|
context = Context(config=config, dst=dst, src=None)
|
||||||
|
|
||||||
|
PythonModule().apply(context)
|
||||||
|
|
||||||
|
uv_toml = (dst / "etc/uv/uv.toml").read_text(encoding="utf-8")
|
||||||
|
# The emoji isn't a plain identifier character, so sanitize_repository_name
|
||||||
|
# replaces it (and the space before it) with "_", same as every other
|
||||||
|
# non-ASCII or syntax-breaking character.
|
||||||
|
assert '"demo__"' in uv_toml
|
||||||
|
parsed = tomllib.loads(uv_toml)
|
||||||
|
assert parsed["index"][0]["name"] == "demo__"
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_adds_trusted_host_for_non_https_repository(tmp_path) -> None:
|
||||||
|
data = {
|
||||||
|
"uuid": "12345678-1234-5678-1234-567812345678",
|
||||||
|
"organisation": "InterDiode",
|
||||||
|
"configurations": {
|
||||||
|
"python": {
|
||||||
|
"repositories": [
|
||||||
|
{"name": "interdiode", "index-url": "http://example.invalid/simple"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
config = Configuration.model_validate(data)
|
||||||
|
dst = tmp_path / "dst"
|
||||||
|
context = Context(config=config, dst=dst, src=None)
|
||||||
|
|
||||||
|
PythonModule().apply(context)
|
||||||
|
|
||||||
|
pip_conf = (dst / "etc/pip.conf").read_text(encoding="utf-8")
|
||||||
|
assert pip_conf == (
|
||||||
|
"[global]\n"
|
||||||
|
"index-url = http://example.invalid/simple\n"
|
||||||
|
"trusted-host =\n"
|
||||||
|
" example.invalid\n"
|
||||||
|
"cert = /etc/ssl/certs/ca-certificates.crt\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_adds_trusted_host_only_for_non_https_among_mixed_repositories(
|
||||||
|
tmp_path,
|
||||||
|
) -> None:
|
||||||
|
data = {
|
||||||
|
"uuid": "12345678-1234-5678-1234-567812345678",
|
||||||
|
"organisation": "InterDiode",
|
||||||
|
"configurations": {
|
||||||
|
"python": {
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"name": "interdiode",
|
||||||
|
"index-url": "https://example.invalid/simple",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "insecure",
|
||||||
|
"index-url": "http://insecure.invalid/simple",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
config = Configuration.model_validate(data)
|
||||||
|
dst = tmp_path / "dst"
|
||||||
|
context = Context(config=config, dst=dst, src=None)
|
||||||
|
|
||||||
|
PythonModule().apply(context)
|
||||||
|
|
||||||
|
pip_conf = (dst / "etc/pip.conf").read_text(encoding="utf-8")
|
||||||
|
assert pip_conf == (
|
||||||
|
"[global]\n"
|
||||||
|
"index-url = https://example.invalid/simple\n"
|
||||||
|
"extra-index-url =\n"
|
||||||
|
" http://insecure.invalid/simple\n"
|
||||||
|
"trusted-host =\n"
|
||||||
|
" insecure.invalid\n"
|
||||||
|
"cert = /etc/ssl/certs/ca-certificates.crt\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_does_not_add_trusted_host_when_all_repositories_https(tmp_path) -> None:
|
||||||
|
config = Configuration.model_validate(ONE_REPO_CONFIG)
|
||||||
|
dst = tmp_path / "dst"
|
||||||
|
context = Context(config=config, dst=dst, src=None)
|
||||||
|
|
||||||
|
PythonModule().apply(context)
|
||||||
|
|
||||||
|
pip_conf = (dst / "etc/pip.conf").read_text(encoding="utf-8")
|
||||||
|
assert "trusted-host" not in pip_conf
|
||||||
|
|
||||||
|
|
||||||
def test_apply_multiple_repositories(tmp_path) -> None:
|
def test_apply_multiple_repositories(tmp_path) -> None:
|
||||||
config = Configuration.model_validate(TWO_REPOS_CONFIG)
|
config = Configuration.model_validate(TWO_REPOS_CONFIG)
|
||||||
dst = tmp_path / "dst"
|
dst = tmp_path / "dst"
|
||||||
@@ -105,6 +212,41 @@ def test_apply_multiple_repositories(tmp_path) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_sanitizes_poetry_repository_name_with_special_characters(
|
||||||
|
tmp_path,
|
||||||
|
) -> None:
|
||||||
|
data = {
|
||||||
|
"uuid": "12345678-1234-5678-1234-567812345678",
|
||||||
|
"organisation": "InterDiode",
|
||||||
|
"configurations": {
|
||||||
|
"python": {
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"name": "weird.name]here[bad",
|
||||||
|
"index-url": "https://example.invalid/simple",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
config = Configuration.model_validate(data)
|
||||||
|
dst = tmp_path / "dst"
|
||||||
|
context = Context(config=config, dst=dst, src=None)
|
||||||
|
|
||||||
|
PythonModule().apply(context)
|
||||||
|
|
||||||
|
poetry_config = (dst / "root/.config/pypoetry/config.toml").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
)
|
||||||
|
assert poetry_config == (
|
||||||
|
"[repositories.weird_name_here_bad]\n"
|
||||||
|
'url = "https://example.invalid/simple"\n'
|
||||||
|
"\n"
|
||||||
|
"[certificates.weird_name_here_bad]\n"
|
||||||
|
'cert = "/etc/ssl/certs/ca-certificates.crt"\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_apply_writes_poetry_config_for_each_configured_user(tmp_path) -> None:
|
def test_apply_writes_poetry_config_for_each_configured_user(tmp_path) -> None:
|
||||||
config = Configuration.model_validate(ONE_REPO_CONFIG)
|
config = Configuration.model_validate(ONE_REPO_CONFIG)
|
||||||
dst = tmp_path / "dst"
|
dst = tmp_path / "dst"
|
||||||
|
|||||||
+9
-18
@@ -43,23 +43,17 @@ def test_parse_passwd_skips_malformed_lines() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_has_login_shell_true_for_regular_shell() -> None:
|
def test_has_login_shell_true_for_regular_shell() -> None:
|
||||||
entry = PasswdEntry(name="alice", uid=1000, home="/home/alice", shell="/bin/bash") # noqa: B604
|
entry = PasswdEntry(name="alice", uid=1000, home="/home/alice", shell="/bin/bash")
|
||||||
assert entry.has_login_shell is True
|
assert entry.has_login_shell is True
|
||||||
|
|
||||||
|
|
||||||
def test_has_login_shell_false_for_nologin_sync_or_false() -> None:
|
def test_has_login_shell_false_for_nologin_sync_or_false() -> None:
|
||||||
nologin = PasswdEntry(
|
nologin = PasswdEntry(
|
||||||
name="daemon",
|
name="daemon", uid=1, home="/usr/sbin", shell="/usr/sbin/nologin"
|
||||||
uid=1,
|
|
||||||
home="/usr/sbin",
|
|
||||||
shell="/usr/sbin/nologin", # noqa: B604
|
|
||||||
)
|
)
|
||||||
sync = PasswdEntry(name="sync", uid=4, home="/bin", shell="/bin/sync") # noqa: B604
|
sync = PasswdEntry(name="sync", uid=4, home="/bin", shell="/bin/sync")
|
||||||
false_shell = PasswdEntry(
|
false_shell = PasswdEntry(
|
||||||
name="nobody",
|
name="nobody", uid=65534, home="/nonexistent", shell="/usr/sbin/false"
|
||||||
uid=65534,
|
|
||||||
home="/nonexistent",
|
|
||||||
shell="/usr/sbin/false", # noqa: B604
|
|
||||||
)
|
)
|
||||||
assert nologin.has_login_shell is False
|
assert nologin.has_login_shell is False
|
||||||
assert sync.has_login_shell is False
|
assert sync.has_login_shell is False
|
||||||
@@ -67,32 +61,29 @@ def test_has_login_shell_false_for_nologin_sync_or_false() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_is_regular_user_true_for_human_account() -> None:
|
def test_is_regular_user_true_for_human_account() -> None:
|
||||||
entry = PasswdEntry(name="alice", uid=1000, home="/home/alice", shell="/bin/bash") # noqa: B604
|
entry = PasswdEntry(name="alice", uid=1000, home="/home/alice", shell="/bin/bash")
|
||||||
assert entry.is_regular_user() is True
|
assert entry.is_regular_user() is True
|
||||||
|
|
||||||
|
|
||||||
def test_is_regular_user_true_for_root_despite_uid_zero() -> None:
|
def test_is_regular_user_true_for_root_despite_uid_zero() -> None:
|
||||||
entry = PasswdEntry(name="root", uid=0, home="/root", shell="/bin/bash") # noqa: B604
|
entry = PasswdEntry(name="root", uid=0, home="/root", shell="/bin/bash")
|
||||||
assert entry.is_regular_user() is True
|
assert entry.is_regular_user() is True
|
||||||
|
|
||||||
|
|
||||||
def test_is_regular_user_false_for_root_with_disabled_shell() -> None:
|
def test_is_regular_user_false_for_root_with_disabled_shell() -> None:
|
||||||
entry = PasswdEntry(name="root", uid=0, home="/root", shell="/usr/sbin/nologin") # noqa: B604
|
entry = PasswdEntry(name="root", uid=0, home="/root", shell="/usr/sbin/nologin")
|
||||||
assert entry.is_regular_user() is False
|
assert entry.is_regular_user() is False
|
||||||
|
|
||||||
|
|
||||||
def test_is_regular_user_false_for_disabled_shell_despite_high_uid() -> None:
|
def test_is_regular_user_false_for_disabled_shell_despite_high_uid() -> None:
|
||||||
entry = PasswdEntry(
|
entry = PasswdEntry(
|
||||||
name="nobody",
|
name="nobody", uid=65534, home="/nonexistent", shell="/usr/sbin/false"
|
||||||
uid=65534,
|
|
||||||
home="/nonexistent",
|
|
||||||
shell="/usr/sbin/false", # noqa: B604
|
|
||||||
)
|
)
|
||||||
assert entry.is_regular_user() is False
|
assert entry.is_regular_user() is False
|
||||||
|
|
||||||
|
|
||||||
def test_is_regular_user_honors_custom_uid_min() -> None:
|
def test_is_regular_user_honors_custom_uid_min() -> None:
|
||||||
entry = PasswdEntry(name="svc", uid=500, home="/home/svc", shell="/bin/bash") # noqa: B604
|
entry = PasswdEntry(name="svc", uid=500, home="/home/svc", shell="/bin/bash")
|
||||||
assert entry.is_regular_user(uid_min=1000) is False
|
assert entry.is_regular_user(uid_min=1000) is False
|
||||||
assert entry.is_regular_user(uid_min=100) is True
|
assert entry.is_regular_user(uid_min=100) is True
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[tox]
|
[tox]
|
||||||
env_list = py313,py314,coverage,packaging,packaging-amd64,packaging-arm64,publish,module-python,module-apt,module-yum,module-apk,module-java,module-certificates,module-php,module-npm,module-rust,module-go,module-ruby,module-nuget,config-url
|
env_list = py313,py314,coverage,packaging,packaging-amd64,packaging-arm64,publish,module-python,module-python-http,module-apt,module-apt-http,module-yum,module-yum-http,module-apk,module-apk-http,module-java,module-java-http,module-certificates,module-php,module-php-http,module-npm,module-npm-http,module-rust,module-rust-http,module-go,module-go-http,module-ruby,module-ruby-http,module-nuget,module-nuget-http,config-url
|
||||||
isolated_build = true
|
isolated_build = true
|
||||||
requires =
|
requires =
|
||||||
tox>=4
|
tox>=4
|
||||||
@@ -91,6 +91,7 @@ passenv =
|
|||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/pypi-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/pypi-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
PYPI_REPO_PORT=8443/tcp
|
PYPI_REPO_PORT=8443/tcp
|
||||||
|
PYPI_REPO_HTTP_PORT=8080/tcp
|
||||||
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/simple/idconfiguratortestpkg/ || exit 1
|
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/simple/idconfiguratortestpkg/ || exit 1
|
||||||
healthcheck_interval = 1
|
healthcheck_interval = 1
|
||||||
healthcheck_retries = 30
|
healthcheck_retries = 30
|
||||||
@@ -106,17 +107,41 @@ docker =
|
|||||||
pypi-repo
|
pypi-repo
|
||||||
allowlist_externals =
|
allowlist_externals =
|
||||||
docker
|
docker
|
||||||
|
set_env =
|
||||||
|
PYPI_REPO_SCHEME = https
|
||||||
commands =
|
commands =
|
||||||
python3 -m id_tools test render-config {tox_root}/tests/configs/Python.yaml.j2 {env_dir}/configs/Python.yaml
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Python.yaml.j2 {env_dir}/configs/Python.yaml
|
||||||
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-arg PYPI_REPO_PORT={env:PYPI_REPO_PORT} --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Python-alpine.Dockerfile -t id-configurator-python .
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-arg PYPI_REPO_SCHEME={env:PYPI_REPO_SCHEME} --build-arg PYPI_REPO_PORT={env:PYPI_REPO_PORT} --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Python-alpine.Dockerfile -t id-configurator-python .
|
||||||
docker rmi id-configurator-python
|
docker rmi id-configurator-python
|
||||||
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-arg PYPI_REPO_PORT={env:PYPI_REPO_PORT} --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Python.Dockerfile -t id-configurator-python .
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-arg PYPI_REPO_SCHEME={env:PYPI_REPO_SCHEME} --build-arg PYPI_REPO_PORT={env:PYPI_REPO_PORT} --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Python.Dockerfile -t id-configurator-python .
|
||||||
docker rmi id-configurator-python
|
docker rmi id-configurator-python
|
||||||
|
|
||||||
|
[testenv:module-python-http]
|
||||||
|
package = skip
|
||||||
|
labels = end-to-end
|
||||||
|
change_dir = {tox_root}
|
||||||
|
dependency_groups = dev
|
||||||
|
docker =
|
||||||
|
pypi-repo
|
||||||
|
allowlist_externals =
|
||||||
|
docker
|
||||||
|
description =
|
||||||
|
Same as module-python, but against a plain-HTTP index, to verify pip's
|
||||||
|
trusted-host is configured correctly for a non-HTTPS repository.
|
||||||
|
set_env =
|
||||||
|
PYPI_REPO_SCHEME = http
|
||||||
|
commands =
|
||||||
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Python.yaml.j2 {env_dir}/configs/Python.yaml
|
||||||
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-arg PYPI_REPO_SCHEME={env:PYPI_REPO_SCHEME} --build-arg PYPI_REPO_PORT={env:PYPI_REPO_HTTP_PORT} --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Python-alpine.Dockerfile -t id-configurator-python-http .
|
||||||
|
docker rmi id-configurator-python-http
|
||||||
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-arg PYPI_REPO_SCHEME={env:PYPI_REPO_SCHEME} --build-arg PYPI_REPO_PORT={env:PYPI_REPO_HTTP_PORT} --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Python.Dockerfile -t id-configurator-python-http .
|
||||||
|
docker rmi id-configurator-python-http
|
||||||
|
|
||||||
[docker:apt-repo]
|
[docker:apt-repo]
|
||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/apt-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/apt-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
APT_REPO_PORT=8443/tcp
|
APT_REPO_PORT=8443/tcp
|
||||||
|
APT_REPO_HTTP_PORT=8080/tcp
|
||||||
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/Packages || exit 1
|
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/Packages || exit 1
|
||||||
healthcheck_interval = 1
|
healthcheck_interval = 1
|
||||||
healthcheck_retries = 30
|
healthcheck_retries = 30
|
||||||
@@ -132,15 +157,37 @@ docker =
|
|||||||
apt-repo
|
apt-repo
|
||||||
allowlist_externals =
|
allowlist_externals =
|
||||||
docker
|
docker
|
||||||
|
set_env =
|
||||||
|
APT_REPO_SCHEME = https
|
||||||
commands =
|
commands =
|
||||||
python3 -m id_tools test render-config {tox_root}/tests/configs/Apt.yaml.j2 {env_dir}/configs/Apt.yaml
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Apt.yaml.j2 {env_dir}/configs/Apt.yaml
|
||||||
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Apt.Dockerfile -t id-configurator-apt .
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Apt.Dockerfile -t id-configurator-apt .
|
||||||
docker rmi id-configurator-apt
|
docker rmi id-configurator-apt
|
||||||
|
|
||||||
|
[testenv:module-apt-http]
|
||||||
|
package = skip
|
||||||
|
labels = end-to-end
|
||||||
|
change_dir = {tox_root}
|
||||||
|
dependency_groups = dev
|
||||||
|
docker =
|
||||||
|
apt-repo
|
||||||
|
allowlist_externals =
|
||||||
|
docker
|
||||||
|
description =
|
||||||
|
Same as module-apt, but against a plain-HTTP source, since apt's trust
|
||||||
|
model is the signed-by keyring, independent of transport scheme.
|
||||||
|
set_env =
|
||||||
|
APT_REPO_SCHEME = http
|
||||||
|
commands =
|
||||||
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Apt.yaml.j2 {env_dir}/configs/Apt.yaml
|
||||||
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Apt.Dockerfile -t id-configurator-apt-http .
|
||||||
|
docker rmi id-configurator-apt-http
|
||||||
|
|
||||||
[docker:yum-repo]
|
[docker:yum-repo]
|
||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/yum-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/yum-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
YUM_REPO_PORT=8443/tcp
|
YUM_REPO_PORT=8443/tcp
|
||||||
|
YUM_REPO_HTTP_PORT=8080/tcp
|
||||||
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/repodata/repomd.xml || exit 1
|
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/repodata/repomd.xml || exit 1
|
||||||
healthcheck_interval = 1
|
healthcheck_interval = 1
|
||||||
healthcheck_retries = 30
|
healthcheck_retries = 30
|
||||||
@@ -156,15 +203,37 @@ docker =
|
|||||||
yum-repo
|
yum-repo
|
||||||
allowlist_externals =
|
allowlist_externals =
|
||||||
docker
|
docker
|
||||||
|
set_env =
|
||||||
|
YUM_REPO_SCHEME = https
|
||||||
commands =
|
commands =
|
||||||
python3 -m id_tools test render-config {tox_root}/tests/configs/Yum.yaml.j2 {env_dir}/configs/Yum.yaml
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Yum.yaml.j2 {env_dir}/configs/Yum.yaml
|
||||||
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Yum.Dockerfile -t id-configurator-yum .
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Yum.Dockerfile -t id-configurator-yum .
|
||||||
docker rmi id-configurator-yum
|
docker rmi id-configurator-yum
|
||||||
|
|
||||||
|
[testenv:module-yum-http]
|
||||||
|
package = skip
|
||||||
|
labels = end-to-end
|
||||||
|
change_dir = {tox_root}
|
||||||
|
dependency_groups = dev
|
||||||
|
docker =
|
||||||
|
yum-repo
|
||||||
|
allowlist_externals =
|
||||||
|
docker
|
||||||
|
description =
|
||||||
|
Same as module-yum, but against a plain-HTTP repository, since yum/dnf's
|
||||||
|
trust model is the imported GPG key, independent of transport scheme.
|
||||||
|
set_env =
|
||||||
|
YUM_REPO_SCHEME = http
|
||||||
|
commands =
|
||||||
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Yum.yaml.j2 {env_dir}/configs/Yum.yaml
|
||||||
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Yum.Dockerfile -t id-configurator-yum-http .
|
||||||
|
docker rmi id-configurator-yum-http
|
||||||
|
|
||||||
[docker:apk-repo]
|
[docker:apk-repo]
|
||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/apk-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/apk-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
APK_REPO_PORT=8443/tcp
|
APK_REPO_PORT=8443/tcp
|
||||||
|
APK_REPO_HTTP_PORT=8080/tcp
|
||||||
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/APKINDEX.tar.gz || exit 1
|
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/APKINDEX.tar.gz || exit 1
|
||||||
healthcheck_interval = 1
|
healthcheck_interval = 1
|
||||||
healthcheck_retries = 30
|
healthcheck_retries = 30
|
||||||
@@ -189,15 +258,39 @@ description =
|
|||||||
native platform keeps them in agreement everywhere (including under
|
native platform keeps them in agreement everywhere (including under
|
||||||
QEMU emulation on non-amd64 hosts); CI runners are amd64, so this still
|
QEMU emulation on non-amd64 hosts); CI runners are amd64, so this still
|
||||||
matches the other envs there.
|
matches the other envs there.
|
||||||
|
set_env =
|
||||||
|
APK_REPO_SCHEME = https
|
||||||
commands =
|
commands =
|
||||||
python3 -m id_tools test render-config {tox_root}/tests/configs/Apk.yaml.j2 {env_dir}/configs/Apk.yaml
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Apk.yaml.j2 {env_dir}/configs/Apk.yaml
|
||||||
docker buildx build --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Apk.Dockerfile -t id-configurator-apk .
|
docker buildx build --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Apk.Dockerfile -t id-configurator-apk .
|
||||||
docker rmi id-configurator-apk
|
docker rmi id-configurator-apk
|
||||||
|
|
||||||
|
[testenv:module-apk-http]
|
||||||
|
package = skip
|
||||||
|
labels = end-to-end
|
||||||
|
change_dir = {tox_root}
|
||||||
|
dependency_groups = dev
|
||||||
|
docker =
|
||||||
|
apk-repo
|
||||||
|
allowlist_externals =
|
||||||
|
docker
|
||||||
|
description =
|
||||||
|
Same as module-apk, but against a plain-HTTP repository, since apk's
|
||||||
|
trust model is the signed index, independent of transport scheme. See
|
||||||
|
module-apk's own description for why this isn't pinned to --platform
|
||||||
|
linux/amd64 either.
|
||||||
|
set_env =
|
||||||
|
APK_REPO_SCHEME = http
|
||||||
|
commands =
|
||||||
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Apk.yaml.j2 {env_dir}/configs/Apk.yaml
|
||||||
|
docker buildx build --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Apk.Dockerfile -t id-configurator-apk-http .
|
||||||
|
docker rmi id-configurator-apk-http
|
||||||
|
|
||||||
[docker:java-repo]
|
[docker:java-repo]
|
||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/java-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/java-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
JAVA_REPO_PORT=8443/tcp
|
JAVA_REPO_PORT=8443/tcp
|
||||||
|
JAVA_REPO_HTTP_PORT=8080/tcp
|
||||||
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/org/interdiode/idconfiguratortestpkg/0.0.1/idconfiguratortestpkg-0.0.1.pom || exit 1
|
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/org/interdiode/idconfiguratortestpkg/0.0.1/idconfiguratortestpkg-0.0.1.pom || exit 1
|
||||||
healthcheck_interval = 1
|
healthcheck_interval = 1
|
||||||
healthcheck_retries = 30
|
healthcheck_retries = 30
|
||||||
@@ -213,11 +306,33 @@ docker =
|
|||||||
java-repo
|
java-repo
|
||||||
allowlist_externals =
|
allowlist_externals =
|
||||||
docker
|
docker
|
||||||
|
set_env =
|
||||||
|
JAVA_REPO_SCHEME = https
|
||||||
commands =
|
commands =
|
||||||
python3 -m id_tools test render-config {tox_root}/tests/configs/Java.yaml.j2 {env_dir}/configs/Java.yaml
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Java.yaml.j2 {env_dir}/configs/Java.yaml
|
||||||
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Java.Dockerfile -t id-configurator-java .
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-arg JAVA_REPO_SCHEME={env:JAVA_REPO_SCHEME} --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Java.Dockerfile -t id-configurator-java .
|
||||||
docker rmi id-configurator-java
|
docker rmi id-configurator-java
|
||||||
|
|
||||||
|
[testenv:module-java-http]
|
||||||
|
package = skip
|
||||||
|
labels = end-to-end
|
||||||
|
change_dir = {tox_root}
|
||||||
|
dependency_groups = dev
|
||||||
|
docker =
|
||||||
|
java-repo
|
||||||
|
allowlist_externals =
|
||||||
|
docker
|
||||||
|
description =
|
||||||
|
Same as module-java, but against a plain-HTTP repository. Leiningen is
|
||||||
|
skipped here (see Java.Dockerfile): it refuses any non-HTTPS repository
|
||||||
|
unconditionally, with no configuration able to change that.
|
||||||
|
set_env =
|
||||||
|
JAVA_REPO_SCHEME = http
|
||||||
|
commands =
|
||||||
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Java.yaml.j2 {env_dir}/configs/Java.yaml
|
||||||
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-arg JAVA_REPO_SCHEME={env:JAVA_REPO_SCHEME} --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Java.Dockerfile -t id-configurator-java-http .
|
||||||
|
docker rmi id-configurator-java-http
|
||||||
|
|
||||||
[docker:certificate-repo]
|
[docker:certificate-repo]
|
||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/certificate-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/certificate-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
@@ -251,6 +366,7 @@ commands =
|
|||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/php-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/php-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
PHP_REPO_PORT=8443/tcp
|
PHP_REPO_PORT=8443/tcp
|
||||||
|
PHP_REPO_HTTP_PORT=8080/tcp
|
||||||
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/packages.json || exit 1
|
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/packages.json || exit 1
|
||||||
healthcheck_interval = 1
|
healthcheck_interval = 1
|
||||||
healthcheck_retries = 30
|
healthcheck_retries = 30
|
||||||
@@ -266,15 +382,37 @@ docker =
|
|||||||
php-repo
|
php-repo
|
||||||
allowlist_externals =
|
allowlist_externals =
|
||||||
docker
|
docker
|
||||||
|
set_env =
|
||||||
|
PHP_REPO_SCHEME = https
|
||||||
commands =
|
commands =
|
||||||
python3 -m id_tools test render-config {tox_root}/tests/configs/Php.yaml.j2 {env_dir}/configs/Php.yaml
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Php.yaml.j2 {env_dir}/configs/Php.yaml
|
||||||
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Php.Dockerfile -t id-configurator-php .
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Php.Dockerfile -t id-configurator-php .
|
||||||
docker rmi id-configurator-php
|
docker rmi id-configurator-php
|
||||||
|
|
||||||
|
[testenv:module-php-http]
|
||||||
|
package = skip
|
||||||
|
labels = end-to-end
|
||||||
|
change_dir = {tox_root}
|
||||||
|
dependency_groups = dev
|
||||||
|
docker =
|
||||||
|
php-repo
|
||||||
|
allowlist_externals =
|
||||||
|
docker
|
||||||
|
description =
|
||||||
|
Same as module-php, but against a plain-HTTP repository, to verify
|
||||||
|
secure-http is disabled (and packagist.org too) for a non-HTTPS source.
|
||||||
|
set_env =
|
||||||
|
PHP_REPO_SCHEME = http
|
||||||
|
commands =
|
||||||
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Php.yaml.j2 {env_dir}/configs/Php.yaml
|
||||||
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Php.Dockerfile -t id-configurator-php-http .
|
||||||
|
docker rmi id-configurator-php-http
|
||||||
|
|
||||||
[docker:npm-repo]
|
[docker:npm-repo]
|
||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/npm-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/npm-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
NPM_REPO_PORT=8443/tcp
|
NPM_REPO_PORT=8443/tcp
|
||||||
|
NPM_REPO_HTTP_PORT=8080/tcp
|
||||||
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/idconfiguratortestpkg || exit 1
|
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/idconfiguratortestpkg || exit 1
|
||||||
healthcheck_interval = 1
|
healthcheck_interval = 1
|
||||||
healthcheck_retries = 30
|
healthcheck_retries = 30
|
||||||
@@ -290,15 +428,36 @@ docker =
|
|||||||
npm-repo
|
npm-repo
|
||||||
allowlist_externals =
|
allowlist_externals =
|
||||||
docker
|
docker
|
||||||
|
set_env =
|
||||||
|
NPM_REPO_SCHEME = https
|
||||||
commands =
|
commands =
|
||||||
python3 -m id_tools test render-config {tox_root}/tests/configs/Npm.yaml.j2 {env_dir}/configs/Npm.yaml
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Npm.yaml.j2 {env_dir}/configs/Npm.yaml
|
||||||
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Npm.Dockerfile -t id-configurator-npm .
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Npm.Dockerfile -t id-configurator-npm .
|
||||||
docker rmi id-configurator-npm
|
docker rmi id-configurator-npm
|
||||||
|
|
||||||
|
[testenv:module-npm-http]
|
||||||
|
package = skip
|
||||||
|
labels = end-to-end
|
||||||
|
change_dir = {tox_root}
|
||||||
|
dependency_groups = dev
|
||||||
|
docker =
|
||||||
|
npm-repo
|
||||||
|
allowlist_externals =
|
||||||
|
docker
|
||||||
|
description =
|
||||||
|
Same as module-npm, but against a plain-HTTP registry.
|
||||||
|
set_env =
|
||||||
|
NPM_REPO_SCHEME = http
|
||||||
|
commands =
|
||||||
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Npm.yaml.j2 {env_dir}/configs/Npm.yaml
|
||||||
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Npm.Dockerfile -t id-configurator-npm-http .
|
||||||
|
docker rmi id-configurator-npm-http
|
||||||
|
|
||||||
[docker:cargo-repo]
|
[docker:cargo-repo]
|
||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/cargo-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/cargo-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
CARGO_REPO_PORT=8443/tcp
|
CARGO_REPO_PORT=8443/tcp
|
||||||
|
CARGO_REPO_HTTP_PORT=8080/tcp
|
||||||
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/config.json || exit 1
|
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/config.json || exit 1
|
||||||
healthcheck_interval = 1
|
healthcheck_interval = 1
|
||||||
healthcheck_retries = 30
|
healthcheck_retries = 30
|
||||||
@@ -314,15 +473,36 @@ docker =
|
|||||||
cargo-repo
|
cargo-repo
|
||||||
allowlist_externals =
|
allowlist_externals =
|
||||||
docker
|
docker
|
||||||
|
set_env =
|
||||||
|
CARGO_REPO_SCHEME = https
|
||||||
commands =
|
commands =
|
||||||
python3 -m id_tools test render-config {tox_root}/tests/configs/Rust.yaml.j2 {env_dir}/configs/Rust.yaml
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Rust.yaml.j2 {env_dir}/configs/Rust.yaml
|
||||||
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Rust.Dockerfile -t id-configurator-rust .
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Rust.Dockerfile -t id-configurator-rust .
|
||||||
docker rmi id-configurator-rust
|
docker rmi id-configurator-rust
|
||||||
|
|
||||||
|
[testenv:module-rust-http]
|
||||||
|
package = skip
|
||||||
|
labels = end-to-end
|
||||||
|
change_dir = {tox_root}
|
||||||
|
dependency_groups = dev
|
||||||
|
docker =
|
||||||
|
cargo-repo
|
||||||
|
allowlist_externals =
|
||||||
|
docker
|
||||||
|
description =
|
||||||
|
Same as module-rust, but against a plain-HTTP sparse registry.
|
||||||
|
set_env =
|
||||||
|
CARGO_REPO_SCHEME = http
|
||||||
|
commands =
|
||||||
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Rust.yaml.j2 {env_dir}/configs/Rust.yaml
|
||||||
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Rust.Dockerfile -t id-configurator-rust-http .
|
||||||
|
docker rmi id-configurator-rust-http
|
||||||
|
|
||||||
[docker:go-repo]
|
[docker:go-repo]
|
||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/go-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/go-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
GO_REPO_PORT=8443/tcp
|
GO_REPO_PORT=8443/tcp
|
||||||
|
GO_REPO_HTTP_PORT=8080/tcp
|
||||||
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/example.invalid/idconfiguratortestpkg/@v/list || exit 1
|
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/example.invalid/idconfiguratortestpkg/@v/list || exit 1
|
||||||
healthcheck_interval = 1
|
healthcheck_interval = 1
|
||||||
healthcheck_retries = 30
|
healthcheck_retries = 30
|
||||||
@@ -338,15 +518,37 @@ docker =
|
|||||||
go-repo
|
go-repo
|
||||||
allowlist_externals =
|
allowlist_externals =
|
||||||
docker
|
docker
|
||||||
|
set_env =
|
||||||
|
GO_REPO_SCHEME = https
|
||||||
commands =
|
commands =
|
||||||
python3 -m id_tools test render-config {tox_root}/tests/configs/Go.yaml.j2 {env_dir}/configs/Go.yaml
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Go.yaml.j2 {env_dir}/configs/Go.yaml
|
||||||
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Go.Dockerfile -t id-configurator-go .
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Go.Dockerfile -t id-configurator-go .
|
||||||
docker rmi id-configurator-go
|
docker rmi id-configurator-go
|
||||||
|
|
||||||
|
[testenv:module-go-http]
|
||||||
|
package = skip
|
||||||
|
labels = end-to-end
|
||||||
|
change_dir = {tox_root}
|
||||||
|
dependency_groups = dev
|
||||||
|
docker =
|
||||||
|
go-repo
|
||||||
|
allowlist_externals =
|
||||||
|
docker
|
||||||
|
description =
|
||||||
|
Same as module-go, but against a plain-HTTP module proxy, to verify
|
||||||
|
GOINSECURE is configured correctly for a non-HTTPS GOPROXY.
|
||||||
|
set_env =
|
||||||
|
GO_REPO_SCHEME = http
|
||||||
|
commands =
|
||||||
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Go.yaml.j2 {env_dir}/configs/Go.yaml
|
||||||
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Go.Dockerfile -t id-configurator-go-http .
|
||||||
|
docker rmi id-configurator-go-http
|
||||||
|
|
||||||
[docker:ruby-repo]
|
[docker:ruby-repo]
|
||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/ruby-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/ruby-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
RUBY_REPO_PORT=8443/tcp
|
RUBY_REPO_PORT=8443/tcp
|
||||||
|
RUBY_REPO_HTTP_PORT=8080/tcp
|
||||||
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/versions || exit 1
|
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/versions || exit 1
|
||||||
healthcheck_interval = 1
|
healthcheck_interval = 1
|
||||||
healthcheck_retries = 30
|
healthcheck_retries = 30
|
||||||
@@ -362,15 +564,36 @@ docker =
|
|||||||
ruby-repo
|
ruby-repo
|
||||||
allowlist_externals =
|
allowlist_externals =
|
||||||
docker
|
docker
|
||||||
|
set_env =
|
||||||
|
RUBY_REPO_SCHEME = https
|
||||||
commands =
|
commands =
|
||||||
python3 -m id_tools test render-config {tox_root}/tests/configs/Ruby.yaml.j2 {env_dir}/configs/Ruby.yaml
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Ruby.yaml.j2 {env_dir}/configs/Ruby.yaml
|
||||||
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Ruby.Dockerfile -t id-configurator-ruby .
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Ruby.Dockerfile -t id-configurator-ruby .
|
||||||
docker rmi id-configurator-ruby
|
docker rmi id-configurator-ruby
|
||||||
|
|
||||||
|
[testenv:module-ruby-http]
|
||||||
|
package = skip
|
||||||
|
labels = end-to-end
|
||||||
|
change_dir = {tox_root}
|
||||||
|
dependency_groups = dev
|
||||||
|
docker =
|
||||||
|
ruby-repo
|
||||||
|
allowlist_externals =
|
||||||
|
docker
|
||||||
|
description =
|
||||||
|
Same as module-ruby, but against a plain-HTTP gem source.
|
||||||
|
set_env =
|
||||||
|
RUBY_REPO_SCHEME = http
|
||||||
|
commands =
|
||||||
|
python3 -m id_tools test render-config {tox_root}/tests/configs/Ruby.yaml.j2 {env_dir}/configs/Ruby.yaml
|
||||||
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/Ruby.Dockerfile -t id-configurator-ruby-http .
|
||||||
|
docker rmi id-configurator-ruby-http
|
||||||
|
|
||||||
[docker:nuget-repo]
|
[docker:nuget-repo]
|
||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/nuget-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/nuget-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
NUGET_REPO_PORT=8443/tcp
|
NUGET_REPO_PORT=8443/tcp
|
||||||
|
NUGET_REPO_HTTP_PORT=8080/tcp
|
||||||
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/index.json || exit 1
|
healthcheck_cmd = wget --no-check-certificate -qO- https://127.0.0.1:8443/index.json || exit 1
|
||||||
healthcheck_interval = 1
|
healthcheck_interval = 1
|
||||||
healthcheck_retries = 30
|
healthcheck_retries = 30
|
||||||
@@ -386,11 +609,32 @@ docker =
|
|||||||
nuget-repo
|
nuget-repo
|
||||||
allowlist_externals =
|
allowlist_externals =
|
||||||
docker
|
docker
|
||||||
|
set_env =
|
||||||
|
NUGET_REPO_SCHEME = https
|
||||||
commands =
|
commands =
|
||||||
python3 -m id_tools test render-config {tox_root}/tests/configs/NuGet.yaml.j2 {env_dir}/configs/NuGet.yaml
|
python3 -m id_tools test render-config {tox_root}/tests/configs/NuGet.yaml.j2 {env_dir}/configs/NuGet.yaml
|
||||||
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/NuGet.Dockerfile -t id-configurator-nuget .
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/NuGet.Dockerfile -t id-configurator-nuget .
|
||||||
docker rmi id-configurator-nuget
|
docker rmi id-configurator-nuget
|
||||||
|
|
||||||
|
[testenv:module-nuget-http]
|
||||||
|
package = skip
|
||||||
|
labels = end-to-end
|
||||||
|
change_dir = {tox_root}
|
||||||
|
dependency_groups = dev
|
||||||
|
docker =
|
||||||
|
nuget-repo
|
||||||
|
allowlist_externals =
|
||||||
|
docker
|
||||||
|
description =
|
||||||
|
Same as module-nuget, but against a plain-HTTP feed, to verify
|
||||||
|
allowInsecureConnections is configured correctly for a non-HTTPS source.
|
||||||
|
set_env =
|
||||||
|
NUGET_REPO_SCHEME = http
|
||||||
|
commands =
|
||||||
|
python3 -m id_tools test render-config {tox_root}/tests/configs/NuGet.yaml.j2 {env_dir}/configs/NuGet.yaml
|
||||||
|
docker buildx build --platform linux/amd64 --add-host=host.docker.internal:host-gateway --build-context generated-config={env_dir}/configs -f {tox_root}/tests/dockerfiles/NuGet.Dockerfile -t id-configurator-nuget-http .
|
||||||
|
docker rmi id-configurator-nuget-http
|
||||||
|
|
||||||
[docker:config-url-repo]
|
[docker:config-url-repo]
|
||||||
dockerfile = {tox_root}/tests/dockerfiles/repos/config-url-repo.Dockerfile
|
dockerfile = {tox_root}/tests/dockerfiles/repos/config-url-repo.Dockerfile
|
||||||
expose =
|
expose =
|
||||||
|
|||||||
@@ -1,51 +1,51 @@
|
|||||||
requires-python = ">=3.13"
|
|
||||||
revision = 3
|
|
||||||
version = 1
|
version = 1
|
||||||
|
revision = 3
|
||||||
|
requires-python = ">=3.13"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "annotated-doc"
|
name = "annotated-doc"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/5a/8e/38aa427ed5402449e226975b649c5dc73ccadfefeb95e6aecb8f8ea4b6b6/annotated_doc-0.0.5.tar.gz", hash = "sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb", size = 10758, upload-time = "2026-07-28T13:50:58.129Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.0.5"
|
version = "0.0.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5a/8e/38aa427ed5402449e226975b649c5dc73ccadfefeb95e6aecb8f8ea4b6b6/annotated_doc-0.0.5.tar.gz", hash = "sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb", size = 10758, upload-time = "2026-07-28T13:50:58.129Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/3e/30/e900b21425a860e195f32e37657aa1f7c7f2b1bfb26f03ca209b90933c06/annotated_doc-0.0.5-py3-none-any.whl", hash = "sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101", size = 5302, upload-time = "2026-07-28T13:50:57.239Z"}
|
{ url = "https://files.pythonhosted.org/packages/3e/30/e900b21425a860e195f32e37657aa1f7c7f2b1bfb26f03ca209b90933c06/annotated_doc-0.0.5-py3-none-any.whl", hash = "sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101", size = 5302, upload-time = "2026-07-28T13:50:57.239Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "annotated-types"
|
name = "annotated-types"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/5f/56/a8120250d128bed162cd73c76d45f6ef9991f3e068f62a8ee060afa3104a/annotated_types-0.8.0.tar.gz", hash = "sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7", size = 15893, upload-time = "2026-07-23T20:16:13.995Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5f/56/a8120250d128bed162cd73c76d45f6ef9991f3e068f62a8ee060afa3104a/annotated_types-0.8.0.tar.gz", hash = "sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7", size = 15893, upload-time = "2026-07-23T20:16:13.995Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0", size = 13427, upload-time = "2026-07-23T20:16:12.938Z"}
|
{ url = "https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0", size = 13427, upload-time = "2026-07-23T20:16:12.938Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cachetools"
|
name = "cachetools"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/29/2c/3f18755527b03ca9ff6be724bd5370cb777c76a87f17301377cf04a4729b/cachetools-7.2.0.tar.gz", hash = "sha256:bcac1a1b8da6909994a2957238a57b8140dab7c5c5c69a43669654fe87a33c1d", size = 41129, upload-time = "2026-09-16T20:48:27.209Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "7.2.0"
|
version = "7.2.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/29/2c/3f18755527b03ca9ff6be724bd5370cb777c76a87f17301377cf04a4729b/cachetools-7.2.0.tar.gz", hash = "sha256:bcac1a1b8da6909994a2957238a57b8140dab7c5c5c69a43669654fe87a33c1d", size = 41129, upload-time = "2026-09-16T20:48:27.209Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/cc/bb/1c6e7a89b11da19f137e4ef5a5c5fe47a5bb686449ba343944ccf8fb34b2/cachetools-7.2.0-py3-none-any.whl", hash = "sha256:3045213f186b89fdd95d94441354c4bd87c570b7a38d8c3fd1d9dd37f6dc90d8", size = 16918, upload-time = "2026-09-16T20:48:25.575Z"}
|
{ url = "https://files.pythonhosted.org/packages/cc/bb/1c6e7a89b11da19f137e4ef5a5c5fe47a5bb686449ba343944ccf8fb34b2/cachetools-7.2.0-py3-none-any.whl", hash = "sha256:3045213f186b89fdd95d94441354c4bd87c570b7a38d8c3fd1d9dd37f6dc90d8", size = 16918, upload-time = "2026-09-16T20:48:25.575Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/a3/c2/24167ea9858356b47a87a50d39908bfdb72ceeefe0041586e704e5376b3a/certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55", size = 138112, upload-time = "2026-07-22T03:35:12.644Z"}
|
version = "2026.10.19"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
version = "2026.7.22"
|
sdist = { url = "https://files.pythonhosted.org/packages/a6/bd/1436c50cc46699de0230fbaacc1d1de7bfec413176099949e9d5112e88f2/certifi-2026.10.19.tar.gz", hash = "sha256:035c1e85572b141bf1c3a3eff0e33a8eb74917522f2559075ff8d2fea780a1ae", size = 137598, upload-time = "2026-10-20T02:24:16.604Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", size = 136983, upload-time = "2026-07-22T03:35:11.276Z"}
|
{ url = "https://files.pythonhosted.org/packages/c4/51/29046e48f693c54e5b7412216d447a1d8362c9653148d98c02cdf65fa733/certifi-2026.10.19-py3-none-any.whl", hash = "sha256:42d35340cc5b9ba78e818ddbff0c5b1c2b779de448a340fd1b989f5fa8670e1b", size = 136464, upload-time = "2026-10-20T02:24:15.072Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
dependencies = [
|
|
||||||
{name = "pycparser", marker = "implementation_name != 'PyPy'"}
|
|
||||||
]
|
|
||||||
name = "cffi"
|
name = "cffi"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "2.1.1"
|
version = "2.1.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pycparser", marker = "implementation_name != 'PyPy'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/9d/f4/035513d4117049066b4779dc3b7c0c0fdad175fa13731c9f4003f1cd1478/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e", size = 194248, upload-time = "2026-08-03T21:19:59.399Z" },
|
{ url = "https://files.pythonhosted.org/packages/9d/f4/035513d4117049066b4779dc3b7c0c0fdad175fa13731c9f4003f1cd1478/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e", size = 194248, upload-time = "2026-08-03T21:19:59.399Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/76/af/2aeb4dbb5fc41a04161ae9ff1518de7cec08e164f44a8ce6a4cf7fd2cd1d/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c", size = 196908, upload-time = "2026-08-03T21:20:00.746Z" },
|
{ url = "https://files.pythonhosted.org/packages/76/af/2aeb4dbb5fc41a04161ae9ff1518de7cec08e164f44a8ce6a4cf7fd2cd1d/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c", size = 196908, upload-time = "2026-08-03T21:20:00.746Z" },
|
||||||
@@ -108,14 +108,14 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/e3/26/2cde30fdde421130bfc18f70395731a6e6b2053c6a1978a5258ff04e72fa/cffi-2.1.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5", size = 225539, upload-time = "2026-08-03T21:21:09.911Z" },
|
{ url = "https://files.pythonhosted.org/packages/e3/26/2cde30fdde421130bfc18f70395731a6e6b2053c6a1978a5258ff04e72fa/cffi-2.1.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5", size = 225539, upload-time = "2026-08-03T21:21:09.911Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6d/cd/a361394c94b2129d604bb846f624a8e88255a3ee33129c434a00d715e64f/cffi-2.1.1-cp315-cp315t-win32.whl", hash = "sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66", size = 182707, upload-time = "2026-08-03T21:21:11.226Z" },
|
{ url = "https://files.pythonhosted.org/packages/6d/cd/a361394c94b2129d604bb846f624a8e88255a3ee33129c434a00d715e64f/cffi-2.1.1-cp315-cp315t-win32.whl", hash = "sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66", size = 182707, upload-time = "2026-08-03T21:21:11.226Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9b/b5/ba2b299993c26577d529b6ae29841f9e15b9fcf004d65f423f4fcf94ade9/cffi-2.1.1-cp315-cp315t-win_amd64.whl", hash = "sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3", size = 193772, upload-time = "2026-08-03T21:21:12.39Z" },
|
{ url = "https://files.pythonhosted.org/packages/9b/b5/ba2b299993c26577d529b6ae29841f9e15b9fcf004d65f423f4fcf94ade9/cffi-2.1.1-cp315-cp315t-win_amd64.whl", hash = "sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3", size = 193772, upload-time = "2026-08-03T21:21:12.39Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/aa/29/35e016098c814cd93de9cd320c66b5bfba14dc6ecedd3cb518fa7c408c69/cffi-2.1.1-cp315-cp315t-win_arm64.whl", hash = "sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692", size = 186360, upload-time = "2026-08-03T21:21:13.636Z"}
|
{ url = "https://files.pythonhosted.org/packages/aa/29/35e016098c814cd93de9cd320c66b5bfba14dc6ecedd3cb518fa7c408c69/cffi-2.1.1-cp315-cp315t-win_arm64.whl", hash = "sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692", size = 186360, upload-time = "2026-08-03T21:21:13.636Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "charset-normalizer"
|
name = "charset-normalizer"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/33/1c/f41d4e74c28ab327ff3acd36053f7ea506c55872d7a90b0fa71aa3ab0c89/charset_normalizer-3.5.2.tar.gz", hash = "sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef", size = 172659, upload-time = "2026-09-30T04:39:23.398Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "3.5.2"
|
version = "3.5.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/33/1c/f41d4e74c28ab327ff3acd36053f7ea506c55872d7a90b0fa71aa3ab0c89/charset_normalizer-3.5.2.tar.gz", hash = "sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef", size = 172659, upload-time = "2026-09-30T04:39:23.398Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/c5/34/68292d68512768591aaff07c59bb53ee31341c87759433a859c4641a50c2/charset_normalizer-3.5.2-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5", size = 225946, upload-time = "2026-09-30T04:35:55.313Z" },
|
{ url = "https://files.pythonhosted.org/packages/c5/34/68292d68512768591aaff07c59bb53ee31341c87759433a859c4641a50c2/charset_normalizer-3.5.2-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5", size = 225946, upload-time = "2026-09-30T04:35:55.313Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e3/80/bee0b01b90ccd5322ae1d0abb33fab1bd95b7c2eadaf02aeccf22e04ee83/charset_normalizer-3.5.2-cp313-cp313-android_24_x86_64.whl", hash = "sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e", size = 238619, upload-time = "2026-09-30T04:35:56.863Z" },
|
{ url = "https://files.pythonhosted.org/packages/e3/80/bee0b01b90ccd5322ae1d0abb33fab1bd95b7c2eadaf02aeccf22e04ee83/charset_normalizer-3.5.2-cp313-cp313-android_24_x86_64.whl", hash = "sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e", size = 238619, upload-time = "2026-09-30T04:35:56.863Z" },
|
||||||
@@ -223,23 +223,23 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/31/68/fdec18a343f5fb3f310588dd478b09ac4799e0b187dbade3a8cd776f03ef/charset_normalizer-3.5.2-cp37-abi3-win32.whl", hash = "sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf", size = 174499, upload-time = "2026-09-30T04:38:47.999Z" },
|
{ url = "https://files.pythonhosted.org/packages/31/68/fdec18a343f5fb3f310588dd478b09ac4799e0b187dbade3a8cd776f03ef/charset_normalizer-3.5.2-cp37-abi3-win32.whl", hash = "sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf", size = 174499, upload-time = "2026-09-30T04:38:47.999Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9d/8a/b618149cc5207943a0242068d7a27897f56a62947b5a039085f2a22029f8/charset_normalizer-3.5.2-cp37-abi3-win_amd64.whl", hash = "sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036", size = 200092, upload-time = "2026-09-30T04:38:49.707Z" },
|
{ url = "https://files.pythonhosted.org/packages/9d/8a/b618149cc5207943a0242068d7a27897f56a62947b5a039085f2a22029f8/charset_normalizer-3.5.2-cp37-abi3-win_amd64.whl", hash = "sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036", size = 200092, upload-time = "2026-09-30T04:38:49.707Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/03/cf/4c66866fa9e2b1c78e3c911516d1de497a677b7ac60f1eceda74ce777ca3/charset_normalizer-3.5.2-cp37-abi3-win_arm64.whl", hash = "sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e", size = 294363, upload-time = "2026-09-30T04:38:51.312Z" },
|
{ url = "https://files.pythonhosted.org/packages/03/cf/4c66866fa9e2b1c78e3c911516d1de497a677b7ac60f1eceda74ce777ca3/charset_normalizer-3.5.2-cp37-abi3-win_arm64.whl", hash = "sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e", size = 294363, upload-time = "2026-09-30T04:38:51.312Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/fc/ad/d07d7862a62ffa6d79d68074d14823243dd235a77c45262acbf6adeb28bf/charset_normalizer-3.5.2-py3-none-any.whl", hash = "sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685", size = 68872, upload-time = "2026-09-30T04:39:21.828Z"}
|
{ url = "https://files.pythonhosted.org/packages/fc/ad/d07d7862a62ffa6d79d68074d14823243dd235a77c45262acbf6adeb28bf/charset_normalizer-3.5.2-py3-none-any.whl", hash = "sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685", size = 68872, upload-time = "2026-09-30T04:39:21.828Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorama"
|
name = "colorama"
|
||||||
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"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
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" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{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"}
|
{ 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" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "coverage"
|
name = "coverage"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/2f/55/d1eaf3e73781174340a00dc1ba2aee8a65f82fadb18e2797b192b6b3925b/coverage-7.16.2.tar.gz", hash = "sha256:ca64d9f1f384f151b9511bec01126072acd2f313439f8ed015a22d8790aab6fa", size = 971999, upload-time = "2026-09-27T12:29:01.118Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "7.16.2"
|
version = "7.16.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/2f/55/d1eaf3e73781174340a00dc1ba2aee8a65f82fadb18e2797b192b6b3925b/coverage-7.16.2.tar.gz", hash = "sha256:ca64d9f1f384f151b9511bec01126072acd2f313439f8ed015a22d8790aab6fa", size = 971999, upload-time = "2026-09-27T12:29:01.118Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/f0/f6/8eb4f220ef24f84fb27d852d4f9bf83e0c73ec1a4a08dd9a87e3f4529739/coverage-7.16.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1a37c6e478cf687e1aa30a593d19c92c02fad9d122b51ab73f51b8dc7a0c0fc9", size = 223993, upload-time = "2026-09-27T12:26:40.164Z" },
|
{ url = "https://files.pythonhosted.org/packages/f0/f6/8eb4f220ef24f84fb27d852d4f9bf83e0c73ec1a4a08dd9a87e3f4529739/coverage-7.16.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1a37c6e478cf687e1aa30a593d19c92c02fad9d122b51ab73f51b8dc7a0c0fc9", size = 223993, upload-time = "2026-09-27T12:26:40.164Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/40/23/d4bbaf0c154e0b0c2b5264890dbf6ef098dcb50ec8f2469be9490d191660/coverage-7.16.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0993d0e90858c03943d3cb152e068a20dd4707924deec84dd2230261baae3b1b", size = 224368, upload-time = "2026-09-27T12:26:41.762Z" },
|
{ url = "https://files.pythonhosted.org/packages/40/23/d4bbaf0c154e0b0c2b5264890dbf6ef098dcb50ec8f2469be9490d191660/coverage-7.16.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0993d0e90858c03943d3cb152e068a20dd4707924deec84dd2230261baae3b1b", size = 224368, upload-time = "2026-09-27T12:26:41.762Z" },
|
||||||
@@ -316,17 +316,17 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/28/6c/f08e8ee4293e6434035424180bef4d45e028e8ecc006c61bf9453e74405e/coverage-7.16.2-cp315-cp315t-win32.whl", hash = "sha256:251aed777c47c77aba047096d4542889db089227655711dfc2b9c54ef0e15e35", size = 226583, upload-time = "2026-09-27T12:28:53.33Z" },
|
{ url = "https://files.pythonhosted.org/packages/28/6c/f08e8ee4293e6434035424180bef4d45e028e8ecc006c61bf9453e74405e/coverage-7.16.2-cp315-cp315t-win32.whl", hash = "sha256:251aed777c47c77aba047096d4542889db089227655711dfc2b9c54ef0e15e35", size = 226583, upload-time = "2026-09-27T12:28:53.33Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f7/fd/3f939c2847f4a72c20cff8b1ac33da78ea91a2d38d9b43336e60db719103/coverage-7.16.2-cp315-cp315t-win_amd64.whl", hash = "sha256:2aca0bdfa9e91621d5b09d815357bf63def4fc0e9cb66da67bf2cf93f3b1a6f5", size = 227374, upload-time = "2026-09-27T12:28:55.158Z" },
|
{ url = "https://files.pythonhosted.org/packages/f7/fd/3f939c2847f4a72c20cff8b1ac33da78ea91a2d38d9b43336e60db719103/coverage-7.16.2-cp315-cp315t-win_amd64.whl", hash = "sha256:2aca0bdfa9e91621d5b09d815357bf63def4fc0e9cb66da67bf2cf93f3b1a6f5", size = 227374, upload-time = "2026-09-27T12:28:55.158Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/5a/35/b98cdc354c952402132e675a87f2cc3227fb68f959c84aaa491fbe15933d/coverage-7.16.2-cp315-cp315t-win_arm64.whl", hash = "sha256:b88841e654f09732804809e435b3e005a929ffd9998b872b7b213957b8759cb8", size = 227064, upload-time = "2026-09-27T12:28:57.075Z" },
|
{ url = "https://files.pythonhosted.org/packages/5a/35/b98cdc354c952402132e675a87f2cc3227fb68f959c84aaa491fbe15933d/coverage-7.16.2-cp315-cp315t-win_arm64.whl", hash = "sha256:b88841e654f09732804809e435b3e005a929ffd9998b872b7b213957b8759cb8", size = 227064, upload-time = "2026-09-27T12:28:57.075Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/3f/0c/7a64e1ac90541a8edf50daef0914848011fb057a5bf55284a4811e21939a/coverage-7.16.2-py3-none-any.whl", hash = "sha256:11d28e9123a9156cb405d8d27b44256c9a58fb5decc2073a8f17862057e3aa0f", size = 215754, upload-time = "2026-09-27T12:28:59.075Z"}
|
{ url = "https://files.pythonhosted.org/packages/3f/0c/7a64e1ac90541a8edf50daef0914848011fb057a5bf55284a4811e21939a/coverage-7.16.2-py3-none-any.whl", hash = "sha256:11d28e9123a9156cb405d8d27b44256c9a58fb5decc2073a8f17862057e3aa0f", size = 215754, upload-time = "2026-09-27T12:28:59.075Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
dependencies = [
|
|
||||||
{name = "cffi", marker = "platform_python_implementation != 'PyPy'"}
|
|
||||||
]
|
|
||||||
name = "cryptography"
|
name = "cryptography"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/9d/af/182eb91b0df3fe75c4d9f26fe70684569566745f6ba7e5c9c73a862c5252/cryptography-50.0.2.tar.gz", hash = "sha256:7b46165bb56eb4704e2eaaf86f3c940d19154535d9b0ca7d6d590b04060e00d5", size = 880623, upload-time = "2026-09-30T15:30:04.884Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "50.0.2"
|
version = "50.0.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/9d/af/182eb91b0df3fe75c4d9f26fe70684569566745f6ba7e5c9c73a862c5252/cryptography-50.0.2.tar.gz", hash = "sha256:7b46165bb56eb4704e2eaaf86f3c940d19154535d9b0ca7d6d590b04060e00d5", size = 880623, upload-time = "2026-09-30T15:30:04.884Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/e5/56/d194340cc4a57535e82e1bee9e89667ac4b7c13b5d3f59686deae3094dd5/cryptography-50.0.2-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb", size = 3914904, upload-time = "2026-09-30T14:43:44.339Z" },
|
{ url = "https://files.pythonhosted.org/packages/e5/56/d194340cc4a57535e82e1bee9e89667ac4b7c13b5d3f59686deae3094dd5/cryptography-50.0.2-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb", size = 3914904, upload-time = "2026-09-30T14:43:44.339Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d9/69/c9bd862c3bf43d6399c433caf002df16e2dffd4be49bdf515cda38038711/cryptography-50.0.2-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:79def8d059362e7831389ed3be0ecdf58a89386e1271e35dd9f5af84e81bffd0", size = 4731146, upload-time = "2026-09-30T14:43:47.113Z" },
|
{ url = "https://files.pythonhosted.org/packages/d9/69/c9bd862c3bf43d6399c433caf002df16e2dffd4be49bdf515cda38038711/cryptography-50.0.2-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:79def8d059362e7831389ed3be0ecdf58a89386e1271e35dd9f5af84e81bffd0", size = 4731146, upload-time = "2026-09-30T14:43:47.113Z" },
|
||||||
@@ -379,52 +379,52 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/40/cf/6b5c8e2fd9202d98988ab7cb5cc5c991704c4ad55f492ff408e4969f83f1/cryptography-50.0.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:1981f1db4630889b9ef7803fadef12b056f428cb6b85c27ba57b774793b6093c", size = 4780973, upload-time = "2026-09-30T15:29:41.251Z" },
|
{ url = "https://files.pythonhosted.org/packages/40/cf/6b5c8e2fd9202d98988ab7cb5cc5c991704c4ad55f492ff408e4969f83f1/cryptography-50.0.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:1981f1db4630889b9ef7803fadef12b056f428cb6b85c27ba57b774793b6093c", size = 4780973, upload-time = "2026-09-30T15:29:41.251Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/10/bf/8d6ebc7dded797bd0f0160d52188021211f011a2b164ef0ae1dac4587465/cryptography-50.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7a8701d6b584d76e909e3d305b7d126b41439876a5aaf76cddc67fc230eafa2e", size = 4897738, upload-time = "2026-09-30T15:29:43.106Z" },
|
{ url = "https://files.pythonhosted.org/packages/10/bf/8d6ebc7dded797bd0f0160d52188021211f011a2b164ef0ae1dac4587465/cryptography-50.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7a8701d6b584d76e909e3d305b7d126b41439876a5aaf76cddc67fc230eafa2e", size = 4897738, upload-time = "2026-09-30T15:29:43.106Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d4/aa/f3f6e0de7e6253b8baa8b2d8fb9d50924fa75cee3d4624bd4bc1208ee923/cryptography-50.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ce47f66801c20ec6c6632453bb5960fe38939e9306970b48b3a5a26de7745d94", size = 5058280, upload-time = "2026-09-30T15:29:44.827Z" },
|
{ url = "https://files.pythonhosted.org/packages/d4/aa/f3f6e0de7e6253b8baa8b2d8fb9d50924fa75cee3d4624bd4bc1208ee923/cryptography-50.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ce47f66801c20ec6c6632453bb5960fe38939e9306970b48b3a5a26de7745d94", size = 5058280, upload-time = "2026-09-30T15:29:44.827Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/f6/b6/a1faf3a27ae9405fb34b1713cc73b2d8a26b04d5c561578fa2e6ef3e5bb9/cryptography-50.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:4e81d95e5bafc2d6e34e4bed780e53e4d5b9a2f928573428aa4d35fbec1eb0de", size = 3854095, upload-time = "2026-09-30T15:29:46.782Z"}
|
{ url = "https://files.pythonhosted.org/packages/f6/b6/a1faf3a27ae9405fb34b1713cc73b2d8a26b04d5c561578fa2e6ef3e5bb9/cryptography-50.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:4e81d95e5bafc2d6e34e4bed780e53e4d5b9a2f928573428aa4d35fbec1eb0de", size = 3854095, upload-time = "2026-09-30T15:29:46.782Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "distlib"
|
name = "distlib"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/c9/02/bd72be9134d25ed783ecbbc38a539ffaefbf90c78418c7fb7229600dbac7/distlib-0.4.3.tar.gz", hash = "sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed", size = 615141, upload-time = "2026-06-12T08:04:52.847Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/c9/02/bd72be9134d25ed783ecbbc38a539ffaefbf90c78418c7fb7229600dbac7/distlib-0.4.3.tar.gz", hash = "sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed", size = 615141, upload-time = "2026-06-12T08:04:52.847Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/02/08/9c41fb51ab5b43eb21674aff13df270e8ba6c4b29c8624e328dc7a9482af/distlib-0.4.3-py2.py3-none-any.whl", hash = "sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b", size = 470628, upload-time = "2026-06-12T08:04:50.506Z"}
|
{ url = "https://files.pythonhosted.org/packages/02/08/9c41fb51ab5b43eb21674aff13df270e8ba6c4b29c8624e328dc7a9482af/distlib-0.4.3-py2.py3-none-any.whl", hash = "sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b", size = 470628, upload-time = "2026-06-12T08:04:50.506Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "docker"
|
||||||
|
version = "7.2.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
||||||
{ name = "requests" },
|
{ name = "requests" },
|
||||||
{name = "urllib3"}
|
{ name = "urllib3" },
|
||||||
]
|
]
|
||||||
name = "docker"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/88/7f/731ff914b0255d3d065f45fd4e626d4b8c95dbcbaada049f337a6ac16410/docker-7.2.0.tar.gz", hash = "sha256:cebb93773d334f778e023a7ee352a8d6e13ab1bd3b863a4d4a59dec897df43ac", size = 118731, upload-time = "2026-07-09T14:53:46.39Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/88/7f/731ff914b0255d3d065f45fd4e626d4b8c95dbcbaada049f337a6ac16410/docker-7.2.0.tar.gz", hash = "sha256:cebb93773d334f778e023a7ee352a8d6e13ab1bd3b863a4d4a59dec897df43ac", size = 118731, upload-time = "2026-07-09T14:53:46.39Z" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "7.2.0"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/75/23/529140fe1aab80fc6992f93a706deec709140a6397439139a054e1515c45/docker-7.2.0-py3-none-any.whl", hash = "sha256:a3f45fdeb9165e2d25d9a1d02ddf3bc70fb572cf5ebbf9b58558c22caf29b71f", size = 148775, upload-time = "2026-07-09T14:53:45.224Z"}
|
{ url = "https://files.pythonhosted.org/packages/75/23/529140fe1aab80fc6992f93a706deec709140a6397439139a054e1515c45/docker-7.2.0-py3-none-any.whl", hash = "sha256:a3f45fdeb9165e2d25d9a1d02ddf3bc70fb572cf5ebbf9b58558c22caf29b71f", size = 148775, upload-time = "2026-07-09T14:53:45.224Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filelock"
|
name = "filelock"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/4b/51/a182494d1d8dde1240bff84dda57d48165d982e59582ce8f167e8e3d7628/filelock-4.0.10.tar.gz", hash = "sha256:00d6a81f976a6332551c2c10f39e12b4abb7e01c64d4c497b81a615bc9186f1f", size = 252487, upload-time = "2026-10-03T23:40:48.884Z"}
|
version = "4.0.11"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
version = "4.0.10"
|
sdist = { url = "https://files.pythonhosted.org/packages/d8/9c/925c4f62920e4200d573d2bfe5cfd1b993134c3aee5f9bd3b7c55e20297e/filelock-4.0.11.tar.gz", hash = "sha256:9dc453a1edd25626a6fc97c2cb1bd9f7e46345843d40b3181c071761fb9a5f7a", size = 253844, upload-time = "2026-10-05T00:57:32.47Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/5b/2a/4b1ea3f2180be251a5cff1e70c8a5b7994ffa5c8eab8937901f8a9db58fe/filelock-4.0.10-py3-none-any.whl", hash = "sha256:698048d158dc3c9e18cc5e88b3efdd4bd0e77d76686b22adb4511cc4b2c2f0db", size = 111193, upload-time = "2026-10-03T23:40:47.334Z"}
|
{ url = "https://files.pythonhosted.org/packages/4a/4d/2983a9fc0a412a09151299d1ec9eb7511e3d577f7213e19395fabebf9db6/filelock-4.0.11-py3-none-any.whl", hash = "sha256:1cbdc4ace7fb11d2f6d073f5c3d91537a23b3d58d2bf2fdffc12c6d717a589c6", size = 111688, upload-time = "2026-10-05T00:57:30.896Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "id-configurator"
|
||||||
|
version = "2026.10.9"
|
||||||
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "cryptography" },
|
{ name = "cryptography" },
|
||||||
{ name = "pydantic" },
|
{ name = "pydantic" },
|
||||||
{ name = "pyjks" },
|
{ name = "pyjks" },
|
||||||
{ name = "pyyaml" },
|
{ name = "pyyaml" },
|
||||||
{name = "typer"}
|
{ name = "typer" },
|
||||||
]
|
]
|
||||||
name = "id-configurator"
|
|
||||||
source = {editable = "."}
|
|
||||||
version = "2026.10.3"
|
|
||||||
|
|
||||||
[package.dev-dependencies]
|
[package.dev-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
@@ -432,11 +432,11 @@ dev = [
|
|||||||
{ name = "tox" },
|
{ name = "tox" },
|
||||||
{ name = "tox-docker" },
|
{ name = "tox-docker" },
|
||||||
{ name = "tox-uv" },
|
{ name = "tox-uv" },
|
||||||
{name = "typer"}
|
{ name = "typer" },
|
||||||
]
|
]
|
||||||
test = [
|
test = [
|
||||||
{ name = "pytest" },
|
{ name = "pytest" },
|
||||||
{name = "pytest-cov"}
|
{ name = "pytest-cov" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
@@ -445,7 +445,7 @@ requires-dist = [
|
|||||||
{ name = "pydantic", specifier = ">=2.13.4" },
|
{ name = "pydantic", specifier = ">=2.13.4" },
|
||||||
{ name = "pyjks", specifier = ">=20.0.0" },
|
{ name = "pyjks", specifier = ">=20.0.0" },
|
||||||
{ name = "pyyaml", specifier = ">=6.0.3" },
|
{ name = "pyyaml", specifier = ">=6.0.3" },
|
||||||
{name = "typer", specifier = ">=0.27.1"}
|
{ name = "typer", specifier = ">=0.27.1" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata.requires-dev]
|
[package.metadata.requires-dev]
|
||||||
@@ -454,69 +454,69 @@ dev = [
|
|||||||
{ name = "tox", specifier = ">=4.60.1" },
|
{ name = "tox", specifier = ">=4.60.1" },
|
||||||
{ name = "tox-docker", specifier = ">=5.0.0" },
|
{ name = "tox-docker", specifier = ">=5.0.0" },
|
||||||
{ name = "tox-uv", specifier = ">=1.36.0" },
|
{ name = "tox-uv", specifier = ">=1.36.0" },
|
||||||
{name = "typer", specifier = ">=0.27.1"}
|
{ name = "typer", specifier = ">=0.27.1" },
|
||||||
]
|
]
|
||||||
test = [
|
test = [
|
||||||
{ name = "pytest", specifier = ">=9.1.1" },
|
{ name = "pytest", specifier = ">=9.1.1" },
|
||||||
{name = "pytest-cov", specifier = ">=7.1.0"}
|
{ name = "pytest-cov", specifier = ">=7.1.0" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/f5/08/8eea9d4b8302028f3abb2c0813953f7aec26d33b7a8960ed760e65ff29fa/idna-3.20.tar.gz", hash = "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", size = 216463, upload-time = "2026-09-17T14:11:04.752Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "3.20"
|
version = "3.20"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f5/08/8eea9d4b8302028f3abb2c0813953f7aec26d33b7a8960ed760e65ff29fa/idna-3.20.tar.gz", hash = "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", size = 216463, upload-time = "2026-09-17T14:11:04.752Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/58/a2/bb081bab032533a855d44de1d56f8e8426114ff1ba5d1f07a438a0a654f8/idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c", size = 69583, upload-time = "2026-09-17T14:11:03.168Z"}
|
{ url = "https://files.pythonhosted.org/packages/58/a2/bb081bab032533a855d44de1d56f8e8426114ff1ba5d1f07a438a0a654f8/idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c", size = 69583, upload-time = "2026-09-17T14:11:03.168Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iniconfig"
|
name = "iniconfig"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z"}
|
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "javaobj-py3"
|
name = "javaobj-py3"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/6e/a4/a0140d76c62effc710aa180c657792236d10e43d3f993b71bafc3036fea1/javaobj_py3-0.6.1.tar.gz", hash = "sha256:088ff086c6aa2912f342754c43b0ca3a504fb869bb5e6f13395131e87744ef3c", size = 113555, upload-time = "2026-08-12T16:51:05.39Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/6e/a4/a0140d76c62effc710aa180c657792236d10e43d3f993b71bafc3036fea1/javaobj_py3-0.6.1.tar.gz", hash = "sha256:088ff086c6aa2912f342754c43b0ca3a504fb869bb5e6f13395131e87744ef3c", size = 113555, upload-time = "2026-08-12T16:51:05.39Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/20/97/62180aa88dc4719116128a3c2fe22a962cbf69256d517f376565a38467a7/javaobj_py3-0.6.1-py2.py3-none-any.whl", hash = "sha256:da97c61cb050bad37cca00523b1a617cc26ed2b698b6322cbc118820a4f52b30", size = 94957, upload-time = "2026-08-12T16:51:04.022Z"}
|
{ url = "https://files.pythonhosted.org/packages/20/97/62180aa88dc4719116128a3c2fe22a962cbf69256d517f376565a38467a7/javaobj_py3-0.6.1-py2.py3-none-any.whl", hash = "sha256:da97c61cb050bad37cca00523b1a617cc26ed2b698b6322cbc118820a4f52b30", size = 94957, upload-time = "2026-08-12T16:51:04.022Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
dependencies = [
|
|
||||||
{name = "markupsafe"}
|
|
||||||
]
|
|
||||||
name = "jinja2"
|
name = "jinja2"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "3.1.6"
|
version = "3.1.6"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "markupsafe" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z"}
|
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
dependencies = [
|
|
||||||
{name = "mdurl"}
|
|
||||||
]
|
|
||||||
name = "markdown-it-py"
|
name = "markdown-it-py"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "4.2.0"
|
version = "4.2.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "mdurl" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z"}
|
{ url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "markupsafe"
|
name = "markupsafe"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/38/9b/e422a865e1d5d57d0e509b4e0bf1c1a70a7f6382c29a5aa428df994c8bc8/markupsafe-3.0.4.tar.gz", hash = "sha256:2e9ad7dd851bf45fab9f75cbff4cb493fee9979e8d8c7c9c3ee119022518edd6", size = 153777, upload-time = "2026-10-02T23:07:22.29Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "3.0.4"
|
version = "3.0.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/38/9b/e422a865e1d5d57d0e509b4e0bf1c1a70a7f6382c29a5aa428df994c8bc8/markupsafe-3.0.4.tar.gz", hash = "sha256:2e9ad7dd851bf45fab9f75cbff4cb493fee9979e8d8c7c9c3ee119022518edd6", size = 153777, upload-time = "2026-10-02T23:07:22.29Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/6d/18/4bc5ba32499e87bb2b0ef5b3a9bb9c00a131fa961ddf0be548cb550f548b/markupsafe-3.0.4-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:de8b364c423ef0a4bad9069657d617f9a5d2b2062457a89b1fa16ee199c399c1", size = 12786, upload-time = "2026-10-02T23:05:08.709Z" },
|
{ url = "https://files.pythonhosted.org/packages/6d/18/4bc5ba32499e87bb2b0ef5b3a9bb9c00a131fa961ddf0be548cb550f548b/markupsafe-3.0.4-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:de8b364c423ef0a4bad9069657d617f9a5d2b2062457a89b1fa16ee199c399c1", size = 12786, upload-time = "2026-10-02T23:05:08.709Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/4e/6f/17f0c099bf25f3e31e63cc19244d9f6af861a9a4ab778c203997903cfdd0/markupsafe-3.0.4-cp313-cp313-android_24_x86_64.whl", hash = "sha256:34bdde374c5932765d7dc685c4a1d191a3207852d67e8e0a9eb6ea85156181f1", size = 12510, upload-time = "2026-10-02T23:05:09.93Z" },
|
{ url = "https://files.pythonhosted.org/packages/4e/6f/17f0c099bf25f3e31e63cc19244d9f6af861a9a4ab778c203997903cfdd0/markupsafe-3.0.4-cp313-cp313-android_24_x86_64.whl", hash = "sha256:34bdde374c5932765d7dc685c4a1d191a3207852d67e8e0a9eb6ea85156181f1", size = 12510, upload-time = "2026-10-02T23:05:09.93Z" },
|
||||||
@@ -607,128 +607,133 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/d7/93/2cbd5628435afb6f541bbaced4bce0c2edac4b09a142e6e928b8b0da9858/markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:b91cc9d336957239ff200f30097e6fea2dc6d6fb3c81e853eaa09eac904fd894", size = 23712, upload-time = "2026-10-02T23:06:51.759Z" },
|
{ url = "https://files.pythonhosted.org/packages/d7/93/2cbd5628435afb6f541bbaced4bce0c2edac4b09a142e6e928b8b0da9858/markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:b91cc9d336957239ff200f30097e6fea2dc6d6fb3c81e853eaa09eac904fd894", size = 23712, upload-time = "2026-10-02T23:06:51.759Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/81/99/157e10966b033b363aeda5263e82596ee232a0b1d082fdbf90aa417ff083/markupsafe-3.0.4-cp315-cp315t-win32.whl", hash = "sha256:e49fb0d1ce92cfa0cb198cc5b1b11cdf9d0638658e2a2db2687e39db7c87fc78", size = 14300, upload-time = "2026-10-02T23:06:53.241Z" },
|
{ url = "https://files.pythonhosted.org/packages/81/99/157e10966b033b363aeda5263e82596ee232a0b1d082fdbf90aa417ff083/markupsafe-3.0.4-cp315-cp315t-win32.whl", hash = "sha256:e49fb0d1ce92cfa0cb198cc5b1b11cdf9d0638658e2a2db2687e39db7c87fc78", size = 14300, upload-time = "2026-10-02T23:06:53.241Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/33/05/55884815414c9706a23deca150b72c25a62109e65b0b6ce232077802c719/markupsafe-3.0.4-cp315-cp315t-win_amd64.whl", hash = "sha256:4f6e0852a0283b1b1fd776eeb7b766a5f440b3e2bd31ab51af3b400585f3965c", size = 14522, upload-time = "2026-10-02T23:06:54.729Z" },
|
{ url = "https://files.pythonhosted.org/packages/33/05/55884815414c9706a23deca150b72c25a62109e65b0b6ce232077802c719/markupsafe-3.0.4-cp315-cp315t-win_amd64.whl", hash = "sha256:4f6e0852a0283b1b1fd776eeb7b766a5f440b3e2bd31ab51af3b400585f3965c", size = 14522, upload-time = "2026-10-02T23:06:54.729Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/92/f9/ecbde7149e95b8a0f18e16d5d747f7dc06049d5da2e4f77f6f5e4a1f46a8/markupsafe-3.0.4-cp315-cp315t-win_arm64.whl", hash = "sha256:39dbacefc411633db5b4378b066a9aca70a3d7e2922c9e578d825f844026eeba", size = 14417, upload-time = "2026-10-02T23:06:56.246Z"}
|
{ url = "https://files.pythonhosted.org/packages/92/f9/ecbde7149e95b8a0f18e16d5d747f7dc06049d5da2e4f77f6f5e4a1f46a8/markupsafe-3.0.4-cp315-cp315t-win_arm64.whl", hash = "sha256:39dbacefc411633db5b4378b066a9aca70a3d7e2922c9e578d825f844026eeba", size = 14417, upload-time = "2026-10-02T23:06:56.246Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mdurl"
|
name = "mdurl"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z"}
|
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
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"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "26.3"
|
version = "26.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
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" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{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"}
|
{ 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" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "platformdirs"
|
name = "platformdirs"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/42/23/4a86fc741c38c5b69792a4ef954b281afa69bea9f083f881de1b0d23bc07/platformdirs-4.12.3.tar.gz", hash = "sha256:427fc0bb321ae0c5b037fa03238ca74820437be162e78b4848c4d4055b9b766c", size = 59538, upload-time = "2026-10-03T23:40:46.595Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "4.12.3"
|
version = "4.12.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/42/23/4a86fc741c38c5b69792a4ef954b281afa69bea9f083f881de1b0d23bc07/platformdirs-4.12.3.tar.gz", hash = "sha256:427fc0bb321ae0c5b037fa03238ca74820437be162e78b4848c4d4055b9b766c", size = 59538, upload-time = "2026-10-03T23:40:46.595Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/c5/9b/6ce1ead737fe496611bda600c263b9a11ae7bd8f41bb13f9bd7e0a2c37a4/platformdirs-4.12.3-py3-none-any.whl", hash = "sha256:080f3b39423b5abfca9a23d84c4e9795f54d395cd8459867a8ded44084fcd5f8", size = 32493, upload-time = "2026-10-03T23:40:45.104Z"}
|
{ url = "https://files.pythonhosted.org/packages/c5/9b/6ce1ead737fe496611bda600c263b9a11ae7bd8f41bb13f9bd7e0a2c37a4/platformdirs-4.12.3-py3-none-any.whl", hash = "sha256:080f3b39423b5abfca9a23d84c4e9795f54d395cd8459867a8ded44084fcd5f8", size = 32493, upload-time = "2026-10-03T23:40:45.104Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pluggy"
|
name = "pluggy"
|
||||||
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"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
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" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{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"}
|
{ 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" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyasn1"
|
name = "pyasn1"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/a4/9a/23310166d960def5897e91fe20e5b724601b02a22e84ba1f94232c0b7f67/pyasn1-0.6.4.tar.gz", hash = "sha256:9c447d8431c947fe4c8febc4ed9e760bc29011a5b01e5c74b67025bd9fb8ce81", size = 151262, upload-time = "2026-07-09T01:12:33.988Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.6.4"
|
version = "0.6.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/a4/9a/23310166d960def5897e91fe20e5b724601b02a22e84ba1f94232c0b7f67/pyasn1-0.6.4.tar.gz", hash = "sha256:9c447d8431c947fe4c8febc4ed9e760bc29011a5b01e5c74b67025bd9fb8ce81", size = 151262, upload-time = "2026-07-09T01:12:33.988Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/9a/3b/6163796d69c3977d1e4287bea4a6979161cbbdd170ebb430511e8e1999ce/pyasn1-0.6.4-py3-none-any.whl", hash = "sha256:deda9277cfd454080ec40b207fb6df82206a3a2688735233cdcd8d3d565f088b", size = 84410, upload-time = "2026-07-09T01:12:32.92Z"}
|
{ url = "https://files.pythonhosted.org/packages/9a/3b/6163796d69c3977d1e4287bea4a6979161cbbdd170ebb430511e8e1999ce/pyasn1-0.6.4-py3-none-any.whl", hash = "sha256:deda9277cfd454080ec40b207fb6df82206a3a2688735233cdcd8d3d565f088b", size = 84410, upload-time = "2026-07-09T01:12:32.92Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
dependencies = [
|
|
||||||
{name = "pyasn1"}
|
|
||||||
]
|
|
||||||
name = "pyasn1-modules"
|
name = "pyasn1-modules"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pyasn1" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z"}
|
{ url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pycparser"
|
name = "pycparser"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "3.0"
|
version = "3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z"}
|
{ url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pycryptodomex"
|
name = "pycryptodomex"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/c9/85/e24bf90972a30b0fcd16c73009add1d7d7cd9140c2498a68252028899e41/pycryptodomex-3.23.0.tar.gz", hash = "sha256:71909758f010c82bc99b0abf4ea12012c98962fbf0583c2164f8b84533c2e4da", size = 4922157, upload-time = "2025-05-17T17:23:41.434Z"}
|
version = "3.24.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
version = "3.23.0"
|
sdist = { url = "https://files.pythonhosted.org/packages/4c/25/214ea825a9031f5af2c8b2506ee16701a2560d4712165dd00098dd527bcb/pycryptodomex-3.24.0.tar.gz", hash = "sha256:0428f19f13452c6b89bbaf2c530f84f369873811dfa77f0cee0da4f40fb0474f", size = 4933136, upload-time = "2026-10-04T17:41:08.988Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/2e/00/10edb04777069a42490a38c137099d4b17ba6e36a4e6e28bdc7470e9e853/pycryptodomex-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:7b37e08e3871efe2187bc1fd9320cc81d87caf19816c648f24443483005ff886", size = 2498764, upload-time = "2025-05-17T17:22:21.453Z"},
|
{ url = "https://files.pythonhosted.org/packages/0f/52/5235086483b462600958549b27683ccffbb4941ba512934efc5a14b71a39/pycryptodomex-3.24.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:abf768c285d289c4a0e0678f055663162c9d6257c79f5904fbd2692ade94da1c", size = 2475900, upload-time = "2026-10-04T17:39:26.374Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/6b/3f/2872a9c2d3a27eac094f9ceaa5a8a483b774ae69018040ea3240d5b11154/pycryptodomex-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:91979028227543010d7b2ba2471cf1d1e398b3f183cb105ac584df0c36dac28d", size = 1643012, upload-time = "2025-05-17T17:22:23.702Z"},
|
{ url = "https://files.pythonhosted.org/packages/9e/cd/eeed4b1a1eda71a78defe2c04ff37909461f9c04cd4bde23011d4350cbfb/pycryptodomex-3.24.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c2f42f24d7112ebb93d3aed581d011c82c20101da7d7a6248145c530e99bd2eb", size = 1643488, upload-time = "2026-10-04T17:39:28.545Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/70/af/774c2e2b4f6570fbf6a4972161adbb183aeeaa1863bde31e8706f123bf92/pycryptodomex-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8962204c47464d5c1c4038abeadd4514a133b28748bcd9fa5b6d62e3cec6fa", size = 2187643, upload-time = "2025-05-17T17:22:26.37Z"},
|
{ url = "https://files.pythonhosted.org/packages/18/d2/22005d736858dddd3f7a5ddaf4a91dbb89292f0d9c503a9c13b1bb2ecfb8/pycryptodomex-3.24.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e42a2e9531c40315290278d9eee93ea5031eda3c83969f5709ada51a1c7491b4", size = 2194768, upload-time = "2026-10-04T17:39:31.713Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/de/a3/71065b24cb889d537954cedc3ae5466af00a2cabcff8e29b73be047e9a19/pycryptodomex-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a33986a0066860f7fcf7c7bd2bc804fa90e434183645595ae7b33d01f3c91ed8", size = 2273762, upload-time = "2025-05-17T17:22:28.313Z"},
|
{ url = "https://files.pythonhosted.org/packages/19/c4/c350bb48207ae2a6cca02eb45a2dafc3f2d0196b5b33b556cc9b6815e8cc/pycryptodomex-3.24.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c7055400f773856cd219680d15525c6fb147237534cbe5394a5f92f57f7efaed", size = 2280612, upload-time = "2026-10-04T17:39:34.828Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/c9/0b/ff6f43b7fbef4d302c8b981fe58467b8871902cdc3eb28896b52421422cc/pycryptodomex-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7947ab8d589e3178da3d7cdeabe14f841b391e17046954f2fbcd941705762b5", size = 2313012, upload-time = "2025-05-17T17:22:30.57Z"},
|
{ url = "https://files.pythonhosted.org/packages/fe/56/539e213fbd572f8e95cdef5a46b0c327c7b2412107c3dba73913cfd20753/pycryptodomex-3.24.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e8a7463d346015b42a0fb9c9179ebb7cccfd86bf40199c6796b546ac7be0b85c", size = 2186291, upload-time = "2026-10-04T17:39:38.184Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/02/de/9d4772c0506ab6da10b41159493657105d3f8bb5c53615d19452afc6b315/pycryptodomex-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c25e30a20e1b426e1f0fa00131c516f16e474204eee1139d1603e132acffc314", size = 2186856, upload-time = "2025-05-17T17:22:32.819Z"},
|
{ url = "https://files.pythonhosted.org/packages/9b/f3/f8e73be610ef576c6ca98a78c8450a72f12c178bc89d3e94068e48115c97/pycryptodomex-3.24.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f96e10f0edff9d4b6b253e0a78f7c819749521d3ffe6af0139e08fcd35384405", size = 2278371, upload-time = "2026-10-04T17:39:41.539Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/28/ad/8b30efcd6341707a234e5eba5493700a17852ca1ac7a75daa7945fcf6427/pycryptodomex-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:da4fa650cef02db88c2b98acc5434461e027dce0ae8c22dd5a69013eaf510006", size = 2347523, upload-time = "2025-05-17T17:22:35.386Z"},
|
{ url = "https://files.pythonhosted.org/packages/16/bd/99c89964c5017488992f412f8d645923d8ef996c7f35fc76b7fe019620e1/pycryptodomex-3.24.0-cp313-cp313t-win32.whl", hash = "sha256:3b6276fe007464502df796710fb57dcfeb813b6ccac0eabaf85100be1ad358f2", size = 1792741, upload-time = "2026-10-04T17:39:44.173Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/0f/02/16868e9f655b7670dbb0ac4f2844145cbc42251f916fc35c414ad2359849/pycryptodomex-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:58b851b9effd0d072d4ca2e4542bf2a4abcf13c82a29fd2c93ce27ee2a2e9462", size = 2272825, upload-time = "2025-05-17T17:22:37.632Z"},
|
{ url = "https://files.pythonhosted.org/packages/ca/d5/5a1e469c7eab20c21090d396342894d2f0e25d429eb4df2d9174a03cb226/pycryptodomex-3.24.0-cp313-cp313t-win_amd64.whl", hash = "sha256:88d37b28b450c06a03bd5570467c601fe8c7dbe493ca39771716f56fdbe35d6e", size = 1825623, upload-time = "2026-10-04T17:39:46.422Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/ca/18/4ca89ac737230b52ac8ffaca42f9c6f1fd07c81a6cd821e91af79db60632/pycryptodomex-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:a9d446e844f08299236780f2efa9898c818fe7e02f17263866b8550c7d5fb328", size = 1772078, upload-time = "2025-05-17T17:22:40Z"},
|
{ url = "https://files.pythonhosted.org/packages/1b/fb/1ca14c7e5318125aff23cd19886a62c8eb9015caa373b5834216c60260a5/pycryptodomex-3.24.0-cp313-cp313t-win_arm64.whl", hash = "sha256:e635c7ac056f2a47d79e2bf7042fb3fc6d175f47796a954388a3cec1f2e082a4", size = 1759392, upload-time = "2026-10-04T17:39:48.676Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/73/34/13e01c322db027682e00986873eca803f11c56ade9ba5bbf3225841ea2d4/pycryptodomex-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:bc65bdd9fc8de7a35a74cab1c898cab391a4add33a8fe740bda00f5976ca4708", size = 1803656, upload-time = "2025-05-17T17:22:42.139Z"},
|
{ url = "https://files.pythonhosted.org/packages/a0/dd/8f2d18986f752ceb245d4c3aeb0b13e9ed329d64434969981f0746b5b2ff/pycryptodomex-3.24.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:f6af77f15a91bb6c16607067cfd201330cf5dfefe1c715e955be1fb06d368613", size = 2476818, upload-time = "2026-10-04T17:39:51.311Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/54/68/9504c8796b1805d58f4425002bcca20f12880e6fa4dc2fc9a668705c7a08/pycryptodomex-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:c885da45e70139464f082018ac527fdaad26f1657a99ee13eecdce0f0ca24ab4", size = 1707172, upload-time = "2025-05-17T17:22:44.704Z"},
|
{ url = "https://files.pythonhosted.org/packages/8a/64/6bc2394a249d1c7ba330d192e4bf22d7e5a8caf28ef1dd346b8b847b91b3/pycryptodomex-3.24.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:582efdf767d72c12538949b876a64b9a7af30f2cff063c06dd63ece32c4e5c1d", size = 1645659, upload-time = "2026-10-04T17:39:53.936Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/dd/9c/1a8f35daa39784ed8adf93a694e7e5dc15c23c741bbda06e1d45f8979e9e/pycryptodomex-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:06698f957fe1ab229a99ba2defeeae1c09af185baa909a31a5d1f9d42b1aaed6", size = 2499240, upload-time = "2025-05-17T17:22:46.953Z"},
|
{ url = "https://files.pythonhosted.org/packages/46/36/f720afe32331ebf200bc37d335120f74da371969722d3c188fac757a8a71/pycryptodomex-3.24.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be79564e05ed620a63f353ea50e0d474eb598f70cda1b28c2ca8e9e2f02c139", size = 2194769, upload-time = "2026-10-04T17:39:57.357Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/7a/62/f5221a191a97157d240cf6643747558759126c76ee92f29a3f4aee3197a5/pycryptodomex-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b2c2537863eccef2d41061e82a881dcabb04944c5c06c5aa7110b577cc487545", size = 1644042, upload-time = "2025-05-17T17:22:49.098Z"},
|
{ url = "https://files.pythonhosted.org/packages/05/ac/d0c3b629a9e91c9dee019fa59cdf9617b84b0d11909541e1d6c79b24637c/pycryptodomex-3.24.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb393480b5845ef4acbc9f713e4c473ad08be81bc3cdb5ef017cd02bdafd36e1", size = 2280609, upload-time = "2026-10-04T17:39:59.915Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/8c/fd/5a054543c8988d4ed7b612721d7e78a4b9bf36bc3c5ad45ef45c22d0060e/pycryptodomex-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43c446e2ba8df8889e0e16f02211c25b4934898384c1ec1ec04d7889c0333587", size = 2186227, upload-time = "2025-05-17T17:22:51.139Z"},
|
{ url = "https://files.pythonhosted.org/packages/5f/0e/e64276b7f3dbe9aeabd9c80dfff10bc97740ad8e24892eb6b0e3cbdcd549/pycryptodomex-3.24.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c7b8ad51baf3505dd3d94ec974855359d15769e45c58c2b89c6d4612b1f7ed94", size = 2186290, upload-time = "2026-10-04T17:40:02.856Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/c8/a9/8862616a85cf450d2822dbd4fff1fcaba90877907a6ff5bc2672cafe42f8/pycryptodomex-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f489c4765093fb60e2edafdf223397bc716491b2b69fe74367b70d6999257a5c", size = 2272578, upload-time = "2025-05-17T17:22:53.676Z"},
|
{ url = "https://files.pythonhosted.org/packages/42/2f/b72cc71bff456971e24e886f1824d2efef7b25fbd806eb821b107f8253e6/pycryptodomex-3.24.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7ffcedf4210d8c206fe9852ccde9f78ec9ce35e8039f0a989900ffe710e7a5db", size = 2278371, upload-time = "2026-10-04T17:40:06.135Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/46/9f/bda9c49a7c1842820de674ab36c79f4fbeeee03f8ff0e4f3546c3889076b/pycryptodomex-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdc69d0d3d989a1029df0eed67cc5e8e5d968f3724f4519bd03e0ec68df7543c", size = 2312166, upload-time = "2025-05-17T17:22:56.585Z"},
|
{ url = "https://files.pythonhosted.org/packages/70/b0/9d0f0d4d6236f986c942d2933d4a5cbc209ebac1ea7d4c74b6e306efb439/pycryptodomex-3.24.0-cp314-cp314t-win32.whl", hash = "sha256:8d6c5e01e4fb1ddd20cc24d4d8706643dd78b5279453dabcf10ba4e0683bf9b2", size = 1808717, upload-time = "2026-10-04T17:40:09.172Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/03/cc/870b9bf8ca92866ca0186534801cf8d20554ad2a76ca959538041b7a7cf4/pycryptodomex-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6bbcb1dd0f646484939e142462d9e532482bc74475cecf9c4903d4e1cd21f003", size = 2185467, upload-time = "2025-05-17T17:22:59.237Z"},
|
{ url = "https://files.pythonhosted.org/packages/8f/99/55c75d5c8c0e3c966c6f639e3b2556c54b0172501f7377cff2aa570447c7/pycryptodomex-3.24.0-cp314-cp314t-win_amd64.whl", hash = "sha256:c55e6c42f9eb43d90c15792bf69bc09cb3e13a5e55a30eecb555695a02b0d4c0", size = 1842528, upload-time = "2026-10-04T17:40:12.033Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/96/e3/ce9348236d8e669fea5dd82a90e86be48b9c341210f44e25443162aba187/pycryptodomex-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:8a4fcd42ccb04c31268d1efeecfccfd1249612b4de6374205376b8f280321744", size = 2346104, upload-time = "2025-05-17T17:23:02.112Z"},
|
{ url = "https://files.pythonhosted.org/packages/18/3d/2cdbda0eacc9875c5db5cede94389f8ca4a6a4bccbbbc74f47f8fa4f0c6c/pycryptodomex-3.24.0-cp314-cp314t-win_arm64.whl", hash = "sha256:6a62122fb4c85befcc01ec3a1ae5b2ba81689481aba1d383b4e21e34f18900dd", size = 1777885, upload-time = "2026-10-04T17:40:14.361Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/a5/e9/e869bcee87beb89040263c416a8a50204f7f7a83ac11897646c9e71e0daf/pycryptodomex-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:55ccbe27f049743a4caf4f4221b166560d3438d0b1e5ab929e07ae1702a4d6fd", size = 2271038, upload-time = "2025-05-17T17:23:04.872Z"},
|
{ url = "https://files.pythonhosted.org/packages/bc/fd/b9186cea5e823f91f40904373cff30cdaea5dfe1863b4be0ed3bf51e4db6/pycryptodomex-3.24.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:ef2bd306328a8447d4d2af6037efddd67ef16630876ed3ec84babd16ca558941", size = 2476748, upload-time = "2026-10-04T17:40:17.326Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/8d/67/09ee8500dd22614af5fbaa51a4aee6e342b5fa8aecf0a6cb9cbf52fa6d45/pycryptodomex-3.23.0-cp37-abi3-win32.whl", hash = "sha256:189afbc87f0b9f158386bf051f720e20fa6145975f1e76369303d0f31d1a8d7c", size = 1771969, upload-time = "2025-05-17T17:23:07.115Z"},
|
{ url = "https://files.pythonhosted.org/packages/65/c4/bf354a7c435da08ba9905a302dce8fac57a33b2ab1e51c78542b698b4b89/pycryptodomex-3.24.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:42c8221e3a4ca04b070cb388fca004815f6544951bfb2cc6c7958e293b7caf64", size = 1644339, upload-time = "2026-10-04T17:40:19.872Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/69/96/11f36f71a865dd6df03716d33bd07a67e9d20f6b8d39820470b766af323c/pycryptodomex-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:52e5ca58c3a0b0bd5e100a9fbc8015059b05cffc6c66ce9d98b4b45e023443b9", size = 1803124, upload-time = "2025-05-17T17:23:09.267Z"},
|
{ url = "https://files.pythonhosted.org/packages/7b/ea/158d0ea838c92ba5d5081ce0f08e4af40d7278f7609ca007fca4d010aa4d/pycryptodomex-3.24.0-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:da9996407d03684221a4e1603b70fad97d8772185e5f75addcd97fcbc4c3281f", size = 2193232, upload-time = "2026-10-04T17:40:22.957Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/f9/93/45c1cdcbeb182ccd2e144c693eaa097763b08b38cded279f0053ed53c553/pycryptodomex-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:02d87b80778c171445d67e23d1caef279bf4b25c3597050ccd2e13970b57fd51", size = 1707161, upload-time = "2025-05-17T17:23:11.414Z"}
|
{ url = "https://files.pythonhosted.org/packages/c8/9f/376b705a536c65fe41806babe5cdcfb076273a0d72dfbbb92073d3d9b10c/pycryptodomex-3.24.0-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:556e063b52f338bd924fe5c40692cc1f50cb0453bd1d6580b7ffff2eade1a894", size = 2279395, upload-time = "2026-10-04T17:40:25.777Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d4/72/a0726c7165ba84d66923c3e5d5411c5abec9a9a4c1759a664e5cf8806a79/pycryptodomex-3.24.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b6690bfae043c81108e28e31dc7e3afa8cb1b1eb0ba590fdbff2b66e4c6913e7", size = 2184779, upload-time = "2026-10-04T17:40:28.813Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/39/51/c5b9d8fc84d5cf67091a007b476e24f634252fb314472e27a58f3bd97458/pycryptodomex-3.24.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5fa46af1281be707e0ec5878aea0f77d58d8d4b465f63f7385a71ae0080bfff9", size = 2276914, upload-time = "2026-10-04T17:40:31.23Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c4/28/26f6d1b4257911bdab1c66c2a80e1193131bd8c02fa9ac04453cd45233c1/pycryptodomex-3.24.0-cp37-abi3-win32.whl", hash = "sha256:fab40542a863cc142a763aa92630d613925fe3e937bea3ba5fb735e0c42d4f96", size = 1792631, upload-time = "2026-10-04T17:40:33.61Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4d/91/fa406bbeea093b53d314dfb0fd186658a69a398b73a3a609636b8402b5c3/pycryptodomex-3.24.0-cp37-abi3-win_amd64.whl", hash = "sha256:55f22d72250d7923aac3c2442ec6a1dd8774d2efa3bdcb0f68d5e137d372268e", size = 1825514, upload-time = "2026-10-04T17:40:36.059Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/10/b0/c53c7ac97c5deb721aa4f940309802c71ff5ac2fdeac473ce96754c69e5b/pycryptodomex-3.24.0-cp37-abi3-win_arm64.whl", hash = "sha256:908f92fbc307b642b65580d0295698f423b057018d87ae43d441f1d1a00674a2", size = 1759397, upload-time = "2026-10-04T17:40:38.641Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "pydantic"
|
||||||
|
version = "2.13.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "annotated-types" },
|
{ name = "annotated-types" },
|
||||||
{ name = "pydantic-core" },
|
{ name = "pydantic-core" },
|
||||||
{ name = "typing-extensions" },
|
{ name = "typing-extensions" },
|
||||||
{name = "typing-inspection"}
|
{ name = "typing-inspection" },
|
||||||
]
|
]
|
||||||
name = "pydantic"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/53/ef/fc4f868f4e2cee79f863883abffceff107875f569b848507319842d2a681/pydantic-2.13.5.tar.gz", hash = "sha256:51a9c5f7b2f8e636f04c6cada605d9b6a3bf1348fdf945a3d8869b19bba0ee08", size = 845750, upload-time = "2026-08-28T14:04:00.916Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/53/ef/fc4f868f4e2cee79f863883abffceff107875f569b848507319842d2a681/pydantic-2.13.5.tar.gz", hash = "sha256:51a9c5f7b2f8e636f04c6cada605d9b6a3bf1348fdf945a3d8869b19bba0ee08", size = 845750, upload-time = "2026-08-28T14:04:00.916Z" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "2.13.5"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/eb/47/c95ffc2009878c7aac0c5e08528022dcb885933252a88b5f170058014464/pydantic-2.13.5-py3-none-any.whl", hash = "sha256:346a034f080da3755d8e9cb5e00e8b07de1d39e4f6e2c87d8ab7cafa0b269a73", size = 472589, upload-time = "2026-08-28T14:03:59.136Z"}
|
{ url = "https://files.pythonhosted.org/packages/eb/47/c95ffc2009878c7aac0c5e08528022dcb885933252a88b5f170058014464/pydantic-2.13.5-py3-none-any.whl", hash = "sha256:346a034f080da3755d8e9cb5e00e8b07de1d39e4f6e2c87d8ab7cafa0b269a73", size = 472589, upload-time = "2026-08-28T14:03:59.136Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
dependencies = [
|
|
||||||
{name = "typing-extensions"}
|
|
||||||
]
|
|
||||||
name = "pydantic-core"
|
name = "pydantic-core"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/af/f9/8a06bea35ef8daf588f707784c973a7046e0034c8d8cfb08828eeffb8b75/pydantic_core-2.46.5.tar.gz", hash = "sha256:10416c15b8839ecc4ef4d0885da76da6fd0f67333a0eb8aff6d93c4b8f2910fc", size = 472262, upload-time = "2026-08-28T10:01:31.677Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "2.46.5"
|
version = "2.46.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/af/f9/8a06bea35ef8daf588f707784c973a7046e0034c8d8cfb08828eeffb8b75/pydantic_core-2.46.5.tar.gz", hash = "sha256:10416c15b8839ecc4ef4d0885da76da6fd0f67333a0eb8aff6d93c4b8f2910fc", size = 472262, upload-time = "2026-08-28T10:01:31.677Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/f5/37/5abe39a8372a61d3dc3c1338fc504281c01b32fdb3169cd7187153b56d3e/pydantic_core-2.46.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:b7ca9034437b6022f941f4857459562ee00a560b97e7cce8a0ec5a74fc6766e0", size = 2075885, upload-time = "2026-08-28T09:58:47.856Z" },
|
{ url = "https://files.pythonhosted.org/packages/f5/37/5abe39a8372a61d3dc3c1338fc504281c01b32fdb3169cd7187153b56d3e/pydantic_core-2.46.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:b7ca9034437b6022f941f4857459562ee00a560b97e7cce8a0ec5a74fc6766e0", size = 2075885, upload-time = "2026-08-28T09:58:47.856Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/21/43/6323b1f8b217780454c61304bcd2b38ae4762f50754414124603ccc90bb2/pydantic_core-2.46.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f332f0e72a5a0400141f830744e141bf9f97917878dbe968669e8a7fefea78ff", size = 1922768, upload-time = "2026-08-28T09:58:49.58Z" },
|
{ url = "https://files.pythonhosted.org/packages/21/43/6323b1f8b217780454c61304bcd2b38ae4762f50754414124603ccc90bb2/pydantic_core-2.46.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f332f0e72a5a0400141f830744e141bf9f97917878dbe968669e8a7fefea78ff", size = 1922768, upload-time = "2026-08-28T09:58:49.58Z" },
|
||||||
@@ -774,92 +779,92 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/cd/94/5a81583660c175c59d49ffb09f4b3a44debeaf86a19fca664ae1cdd9ee32/pydantic_core-2.46.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:ff218293c9c806138dca139765e3b067621be52bcd93cdc14c7711be7ddc90a9", size = 2335210, upload-time = "2026-08-28T10:00:10.177Z" },
|
{ url = "https://files.pythonhosted.org/packages/cd/94/5a81583660c175c59d49ffb09f4b3a44debeaf86a19fca664ae1cdd9ee32/pydantic_core-2.46.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:ff218293c9c806138dca139765e3b067621be52bcd93cdc14c7711be7ddc90a9", size = 2335210, upload-time = "2026-08-28T10:00:10.177Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/5a/9f/5d685c2693b972d1a59c998586e8823712b66603aeff47ee60a4bdaafd37/pydantic_core-2.46.5-cp314-cp314t-win32.whl", hash = "sha256:97cf3eb53a8cccacf9d46686a0926186c9bfb5574f2ed66d3639d5fe117cd3a9", size = 1921180, upload-time = "2026-08-28T10:00:12.35Z" },
|
{ url = "https://files.pythonhosted.org/packages/5a/9f/5d685c2693b972d1a59c998586e8823712b66603aeff47ee60a4bdaafd37/pydantic_core-2.46.5-cp314-cp314t-win32.whl", hash = "sha256:97cf3eb53a8cccacf9d46686a0926186c9bfb5574f2ed66d3639d5fe117cd3a9", size = 1921180, upload-time = "2026-08-28T10:00:12.35Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/70/12/5c94ee16d65a37a15f9e869f5e6256df111154491173801a4c5e800ab548/pydantic_core-2.46.5-cp314-cp314t-win_amd64.whl", hash = "sha256:d2f9fc07a8042a8f95925b35c4f04f469707c981fc33245b6ca187cf5d2dd290", size = 2020515, upload-time = "2026-08-28T10:00:14.774Z" },
|
{ url = "https://files.pythonhosted.org/packages/70/12/5c94ee16d65a37a15f9e869f5e6256df111154491173801a4c5e800ab548/pydantic_core-2.46.5-cp314-cp314t-win_amd64.whl", hash = "sha256:d2f9fc07a8042a8f95925b35c4f04f469707c981fc33245b6ca187cf5d2dd290", size = 2020515, upload-time = "2026-08-28T10:00:14.774Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/63/19/67830dda664e6bdf9285ee2e40f355d0d7d6b92aa0c42e8d217bb8d33d36/pydantic_core-2.46.5-cp314-cp314t-win_arm64.whl", hash = "sha256:acf8a67ba51f4ca9ddbd0e6b3000a65ac51ab734661778b3e7ba64d99a710f2f", size = 1989276, upload-time = "2026-08-28T10:00:16.984Z"}
|
{ url = "https://files.pythonhosted.org/packages/63/19/67830dda664e6bdf9285ee2e40f355d0d7d6b92aa0c42e8d217bb8d33d36/pydantic_core-2.46.5-cp314-cp314t-win_arm64.whl", hash = "sha256:acf8a67ba51f4ca9ddbd0e6b3000a65ac51ab734661778b3e7ba64d99a710f2f", size = 1989276, upload-time = "2026-08-28T10:00:16.984Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pygments"
|
name = "pygments"
|
||||||
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"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "2.21.0"
|
version = "2.21.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
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" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{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"}
|
{ 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" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "pyjks"
|
||||||
|
version = "20.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "javaobj-py3" },
|
{ name = "javaobj-py3" },
|
||||||
{ name = "pyasn1" },
|
{ name = "pyasn1" },
|
||||||
{ name = "pyasn1-modules" },
|
{ name = "pyasn1-modules" },
|
||||||
{ name = "pycryptodomex" },
|
{ name = "pycryptodomex" },
|
||||||
{name = "twofish"}
|
{ name = "twofish" },
|
||||||
]
|
]
|
||||||
name = "pyjks"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/9a/3d/69e49f948f4daa09d27ac3c5378d44107e1bf98b3b5c0f847121c3773945/pyjks-20.0.0.tar.gz", hash = "sha256:0378cec15fb11b2ed27ba54dad9fd987d48e6f62f49fcff138f5f7a8b312b044", size = 25695, upload-time = "2020-04-19T01:37:26.52Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/9a/3d/69e49f948f4daa09d27ac3c5378d44107e1bf98b3b5c0f847121c3773945/pyjks-20.0.0.tar.gz", hash = "sha256:0378cec15fb11b2ed27ba54dad9fd987d48e6f62f49fcff138f5f7a8b312b044", size = 25695, upload-time = "2020-04-19T01:37:26.52Z" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "20.0.0"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/28/46/e1f2c679d9c6c76a5fda4eb99922a51141803089bf58e77c74a1fe6f9033/pyjks-20.0.0-py2.py3-none-any.whl", hash = "sha256:394dee142ecff6b1adc36f64356e5584732f1859575aa03b9cf5d5541a9e3460", size = 45253, upload-time = "2020-04-19T01:37:28.789Z"}
|
{ url = "https://files.pythonhosted.org/packages/28/46/e1f2c679d9c6c76a5fda4eb99922a51141803089bf58e77c74a1fe6f9033/pyjks-20.0.0-py2.py3-none-any.whl", hash = "sha256:394dee142ecff6b1adc36f64356e5584732f1859575aa03b9cf5d5541a9e3460", size = 45253, upload-time = "2020-04-19T01:37:28.789Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
dependencies = [
|
|
||||||
{name = "packaging"}
|
|
||||||
]
|
|
||||||
name = "pyproject-api"
|
name = "pyproject-api"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/51/24/757e066eafeeb91ac4887c2edb9c0ac5eb2d5420f836897443577719647f/pyproject_api-1.11.3.tar.gz", hash = "sha256:4ca2f09f628d86ae019d7c701ebb65ee667efc28261f8b9ee3bd55bf0985712c", size = 24944, upload-time = "2026-10-03T23:39:02.985Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "1.11.3"
|
version = "1.11.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "packaging" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/51/24/757e066eafeeb91ac4887c2edb9c0ac5eb2d5420f836897443577719647f/pyproject_api-1.11.3.tar.gz", hash = "sha256:4ca2f09f628d86ae019d7c701ebb65ee667efc28261f8b9ee3bd55bf0985712c", size = 24944, upload-time = "2026-10-03T23:39:02.985Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/92/14/8475adf84dbb57bb2a7c44c32fc9aafcf8c56b85618e24e2de3734ea1fc6/pyproject_api-1.11.3-py3-none-any.whl", hash = "sha256:d258c7aa390962bb942e5e4f9e66ceeb475e7b79e1cdc49cc7baa524547a64a7", size = 13546, upload-time = "2026-10-03T23:39:01.507Z"}
|
{ url = "https://files.pythonhosted.org/packages/92/14/8475adf84dbb57bb2a7c44c32fc9aafcf8c56b85618e24e2de3734ea1fc6/pyproject_api-1.11.3-py3-none-any.whl", hash = "sha256:d258c7aa390962bb942e5e4f9e66ceeb475e7b79e1cdc49cc7baa524547a64a7", size = 13546, upload-time = "2026-10-03T23:39:01.507Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "pytest"
|
||||||
|
version = "9.1.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
{ name = "iniconfig" },
|
{ name = "iniconfig" },
|
||||||
{ name = "packaging" },
|
{ name = "packaging" },
|
||||||
{ name = "pluggy" },
|
{ name = "pluggy" },
|
||||||
{name = "pygments"}
|
{ name = "pygments" },
|
||||||
]
|
]
|
||||||
name = "pytest"
|
|
||||||
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" }
|
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" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "9.1.1"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{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"}
|
{ 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" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "pytest-cov"
|
||||||
|
version = "7.1.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "coverage" },
|
{ name = "coverage" },
|
||||||
{ name = "pluggy" },
|
{ name = "pluggy" },
|
||||||
{name = "pytest"}
|
{ name = "pytest" },
|
||||||
]
|
]
|
||||||
name = "pytest-cov"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "7.1.0"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z"}
|
{ url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
dependencies = [
|
|
||||||
{name = "filelock"}
|
|
||||||
]
|
|
||||||
name = "python-discovery"
|
name = "python-discovery"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/0c/57/250bd238b966cece44328235eb85290045d059265fdaf7527a3a958123db/python_discovery-1.6.1.tar.gz", hash = "sha256:cf87d3627dfb4412437fdd5b13eae402607722998d21567993aedbc59b23c15e", size = 84338, upload-time = "2026-09-18T01:31:53.971Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "1.6.1"
|
version = "1.6.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "filelock" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/0c/57/250bd238b966cece44328235eb85290045d059265fdaf7527a3a958123db/python_discovery-1.6.1.tar.gz", hash = "sha256:cf87d3627dfb4412437fdd5b13eae402607722998d21567993aedbc59b23c15e", size = 84338, upload-time = "2026-09-18T01:31:53.971Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/16/7d/e9ffbadfbf89c93848412d04594135c4ae8c1d37d9e053b9c3ed718fabc4/python_discovery-1.6.1-py3-none-any.whl", hash = "sha256:d43fcdef879fe795352bd13ccf8d185ba5a9f86f36cfcd00529f596e737442b3", size = 38664, upload-time = "2026-09-18T01:31:52.448Z"}
|
{ url = "https://files.pythonhosted.org/packages/16/7d/e9ffbadfbf89c93848412d04594135c4ae8c1d37d9e053b9c3ed718fabc4/python_discovery-1.6.1-py3-none-any.whl", hash = "sha256:d43fcdef879fe795352bd13ccf8d185ba5a9f86f36cfcd00529f596e737442b3", size = 38664, upload-time = "2026-09-18T01:31:52.448Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pywin32"
|
name = "pywin32"
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "312"
|
version = "312"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/2d/41/12fbfd7f36ed2146d8bc9de96c2741296bf0d490b98508496cff322e274c/pywin32-312-cp313-cp313-win32.whl", hash = "sha256:7a27df850933d16a8eabfbaeb73d52b273e2da667f80d70b01a89d1f6828d02c", size = 6370184, upload-time = "2026-06-04T07:49:36.253Z" },
|
{ url = "https://files.pythonhosted.org/packages/2d/41/12fbfd7f36ed2146d8bc9de96c2741296bf0d490b98508496cff322e274c/pywin32-312-cp313-cp313-win32.whl", hash = "sha256:7a27df850933d16a8eabfbaeb73d52b273e2da667f80d70b01a89d1f6828d02c", size = 6370184, upload-time = "2026-06-04T07:49:36.253Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ba/db/36a78e3403099d31d9746d13fdcde5accc43c1155f375a34d15983a479a7/pywin32-312-cp313-cp313-win_amd64.whl", hash = "sha256:c53e878d15a1c44788082bfe712a905433473aa38f86375b7cf8b45e3acbaaf9", size = 6914298, upload-time = "2026-06-04T07:49:38.876Z" },
|
{ url = "https://files.pythonhosted.org/packages/ba/db/36a78e3403099d31d9746d13fdcde5accc43c1155f375a34d15983a479a7/pywin32-312-cp313-cp313-win_amd64.whl", hash = "sha256:c53e878d15a1c44788082bfe712a905433473aa38f86375b7cf8b45e3acbaaf9", size = 6914298, upload-time = "2026-06-04T07:49:38.876Z" },
|
||||||
@@ -869,14 +874,14 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/a4/0e/73f6d6800b4f27655abd9e9f6aaeaefcddb2b946e4674efa2bab184a7f7b/pywin32-312-cp314-cp314-win_arm64.whl", hash = "sha256:9fce94568364e0155e6dfb781ac5d95903be8baf28670632beab1b523f300daa", size = 6839598, upload-time = "2026-06-04T07:49:47.613Z" },
|
{ url = "https://files.pythonhosted.org/packages/a4/0e/73f6d6800b4f27655abd9e9f6aaeaefcddb2b946e4674efa2bab184a7f7b/pywin32-312-cp314-cp314-win_arm64.whl", hash = "sha256:9fce94568364e0155e6dfb781ac5d95903be8baf28670632beab1b523f300daa", size = 6839598, upload-time = "2026-06-04T07:49:47.613Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/eb/61/caa39686032d2ebdd04ff0ab5cbe163126c0066d98e00c9018646e42393b/pywin32-312-cp315-cp315-win32.whl", hash = "sha256:5c1fbe4a937a73ae9297384a3da38518cbc694c68ad8a809b2e19acd350f03ed", size = 6471159, upload-time = "2026-06-04T07:49:50.035Z" },
|
{ url = "https://files.pythonhosted.org/packages/eb/61/caa39686032d2ebdd04ff0ab5cbe163126c0066d98e00c9018646e42393b/pywin32-312-cp315-cp315-win32.whl", hash = "sha256:5c1fbe4a937a73ae9297384a3da38518cbc694c68ad8a809b2e19acd350f03ed", size = 6471159, upload-time = "2026-06-04T07:49:50.035Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/0f/cd/7e1de64a4a6f69c04214169657ccab0d93a670ea50e35eb8f489d7378249/pywin32-312-cp315-cp315-win_amd64.whl", hash = "sha256:c2f03a0f73f804a13c2735b99392b0cd426bb4f2c4d0178e5ac966a0f21618d5", size = 7025293, upload-time = "2026-06-04T07:49:54.857Z" },
|
{ url = "https://files.pythonhosted.org/packages/0f/cd/7e1de64a4a6f69c04214169657ccab0d93a670ea50e35eb8f489d7378249/pywin32-312-cp315-cp315-win_amd64.whl", hash = "sha256:c2f03a0f73f804a13c2735b99392b0cd426bb4f2c4d0178e5ac966a0f21618d5", size = 7025293, upload-time = "2026-06-04T07:49:54.857Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/23/ed/4532e9388e65fa16b46776ef47ad631a64eda1631884488af707666350ed/pywin32-312-cp315-cp315-win_arm64.whl", hash = "sha256:a8597d28f267b39074aef51fa593530082b39cbe5a074226096857b1fed2dfb9", size = 6840337, upload-time = "2026-06-04T07:49:57.531Z"}
|
{ url = "https://files.pythonhosted.org/packages/23/ed/4532e9388e65fa16b46776ef47ad631a64eda1631884488af707666350ed/pywin32-312-cp315-cp315-win_arm64.whl", hash = "sha256:a8597d28f267b39074aef51fa593530082b39cbe5a074226096857b1fed2dfb9", size = 6840337, upload-time = "2026-06-04T07:49:57.531Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyyaml"
|
name = "pyyaml"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "6.0.3"
|
version = "6.0.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" },
|
{ url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" },
|
{ url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" },
|
||||||
@@ -905,56 +910,59 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" },
|
{ url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" },
|
{ url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" },
|
{ url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z"}
|
{ url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "requests"
|
||||||
|
version = "2.34.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "certifi" },
|
{ name = "certifi" },
|
||||||
{ name = "charset-normalizer" },
|
{ name = "charset-normalizer" },
|
||||||
{ name = "idna" },
|
{ name = "idna" },
|
||||||
{name = "urllib3"}
|
{ name = "urllib3" },
|
||||||
]
|
]
|
||||||
name = "requests"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "2.34.2"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z"}
|
{ url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "rich"
|
||||||
|
version = "15.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "markdown-it-py" },
|
{ name = "markdown-it-py" },
|
||||||
{name = "pygments"}
|
{ name = "pygments" },
|
||||||
]
|
]
|
||||||
name = "rich"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "15.0.0"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z"}
|
{ url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shellingham"
|
name = "shellingham"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "1.5.4"
|
version = "1.5.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z"}
|
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tomli-w"
|
name = "tomli-w"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z"}
|
{ url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "tox"
|
||||||
|
version = "4.64.8"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "cachetools" },
|
{ name = "cachetools" },
|
||||||
{ name = "colorama" },
|
{ name = "colorama" },
|
||||||
@@ -965,110 +973,107 @@ dependencies = [
|
|||||||
{ name = "pyproject-api" },
|
{ name = "pyproject-api" },
|
||||||
{ name = "python-discovery" },
|
{ name = "python-discovery" },
|
||||||
{ name = "tomli-w" },
|
{ name = "tomli-w" },
|
||||||
{name = "virtualenv"}
|
{ name = "virtualenv" },
|
||||||
]
|
]
|
||||||
name = "tox"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/11/33/e8f6282e5ced7b01abd968706758014df0b602c622df2c0c61c148921800/tox-4.64.8.tar.gz", hash = "sha256:8d54028cd31f5c8b3dc319e8c2346d720a1ed066aadf3325fd80e9fd3d233825", size = 326058, upload-time = "2026-10-03T23:39:00.492Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/11/33/e8f6282e5ced7b01abd968706758014df0b602c622df2c0c61c148921800/tox-4.64.8.tar.gz", hash = "sha256:8d54028cd31f5c8b3dc319e8c2346d720a1ed066aadf3325fd80e9fd3d233825", size = 326058, upload-time = "2026-10-03T23:39:00.492Z" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "4.64.8"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/5d/cd/f8c1bf8ade3eb15b92e651aa28ec88a64aab45b7115d3269d65459931add/tox-4.64.8-py3-none-any.whl", hash = "sha256:011d8384b649d24505a3477cc79c603d079da53e220593e4cfe4a28fcdc73db2", size = 235967, upload-time = "2026-10-03T23:38:58.822Z"}
|
{ url = "https://files.pythonhosted.org/packages/5d/cd/f8c1bf8ade3eb15b92e651aa28ec88a64aab45b7115d3269d65459931add/tox-4.64.8-py3-none-any.whl", hash = "sha256:011d8384b649d24505a3477cc79c603d079da53e220593e4cfe4a28fcdc73db2", size = 235967, upload-time = "2026-10-03T23:38:58.822Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "tox-docker"
|
||||||
|
version = "5.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "docker" },
|
{ name = "docker" },
|
||||||
{name = "tox"}
|
{ name = "tox" },
|
||||||
]
|
]
|
||||||
name = "tox-docker"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/de/3c/dcec11dadd48a8f2ba276cd499a4db46a0c70388e0505dae46730a185a35/tox_docker-5.0.0.tar.gz", hash = "sha256:3cbfe70713910b9dbb9f74e20a5c42f19da42d375bac7d6a3ccc11aed0738d7a", size = 19779, upload-time = "2024-05-25T12:50:22.173Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/de/3c/dcec11dadd48a8f2ba276cd499a4db46a0c70388e0505dae46730a185a35/tox_docker-5.0.0.tar.gz", hash = "sha256:3cbfe70713910b9dbb9f74e20a5c42f19da42d375bac7d6a3ccc11aed0738d7a", size = 19779, upload-time = "2024-05-25T12:50:22.173Z" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "5.0.0"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/fc/98/82381ccd7adf9b1d4b488199b916f0b77068e449b7186f8aeeb9f5264f1e/tox_docker-5.0.0-py3-none-any.whl", hash = "sha256:7dd7293ea286dff422eab6c23a70652147b275eb436c02e97a90ac59ba41f8a8", size = 29561, upload-time = "2024-05-25T12:50:20.636Z"}
|
{ url = "https://files.pythonhosted.org/packages/fc/98/82381ccd7adf9b1d4b488199b916f0b77068e449b7186f8aeeb9f5264f1e/tox_docker-5.0.0-py3-none-any.whl", hash = "sha256:7dd7293ea286dff422eab6c23a70652147b275eb436c02e97a90ac59ba41f8a8", size = 29561, upload-time = "2024-05-25T12:50:20.636Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "tox-uv"
|
||||||
|
version = "1.36.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "tox-uv-bare" },
|
{ name = "tox-uv-bare" },
|
||||||
{name = "uv"}
|
{ name = "uv" },
|
||||||
]
|
]
|
||||||
name = "tox-uv"
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "1.36.1"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/19/ef/06e0f151d1ebb544bcf27bf8a6914bdc7d9434689278c669efb3c73a8ed5/tox_uv-1.36.1-py3-none-any.whl", hash = "sha256:6996cb49d0b6b838ae015b76611770595cb6f658a27e2a9661766148194c18bd", size = 6567, upload-time = "2026-10-01T23:51:58.511Z"}
|
{ url = "https://files.pythonhosted.org/packages/19/ef/06e0f151d1ebb544bcf27bf8a6914bdc7d9434689278c669efb3c73a8ed5/tox_uv-1.36.1-py3-none-any.whl", hash = "sha256:6996cb49d0b6b838ae015b76611770595cb6f658a27e2a9661766148194c18bd", size = 6567, upload-time = "2026-10-01T23:51:58.511Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "tox-uv-bare"
|
||||||
|
version = "1.36.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "packaging" },
|
{ name = "packaging" },
|
||||||
{name = "tox"}
|
{ name = "tox" },
|
||||||
]
|
]
|
||||||
name = "tox-uv-bare"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/42/c1/1f5b4ff553013dfd418485cb9359cf305e7f47b946e02a36f4a4c279ac21/tox_uv_bare-1.36.1.tar.gz", hash = "sha256:33a08e4205c63811dd76590590718539fe87dcadda5882f164f747bd5db31a2c", size = 32648, upload-time = "2026-10-01T23:52:01.302Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/42/c1/1f5b4ff553013dfd418485cb9359cf305e7f47b946e02a36f4a4c279ac21/tox_uv_bare-1.36.1.tar.gz", hash = "sha256:33a08e4205c63811dd76590590718539fe87dcadda5882f164f747bd5db31a2c", size = 32648, upload-time = "2026-10-01T23:52:01.302Z" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "1.36.1"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/04/64/ed9b351f7ce794df36923fcde243e90cef07f103ea0c24ae4557e9736b7e/tox_uv_bare-1.36.1-py3-none-any.whl", hash = "sha256:de41cf5450b8f37837fd68834dfebef59939cd10fde030e498cd9a48db19f1e8", size = 22469, upload-time = "2026-10-01T23:51:59.906Z"}
|
{ url = "https://files.pythonhosted.org/packages/04/64/ed9b351f7ce794df36923fcde243e90cef07f103ea0c24ae4557e9736b7e/tox_uv_bare-1.36.1-py3-none-any.whl", hash = "sha256:de41cf5450b8f37837fd68834dfebef59939cd10fde030e498cd9a48db19f1e8", size = 22469, upload-time = "2026-10-01T23:51:59.906Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "twofish"
|
name = "twofish"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/82/b4/9eb026a8e62a04512435d3de25c93f7bda51c8b8c7991c1c0be70b5115a6/twofish-0.3.0.tar.gz", hash = "sha256:b09d8bb50d33b23ff34cafb1f9209f858f752935c6a5c901efb92a41acb830fa", size = 26039, upload-time = "2013-11-15T20:37:59.634Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/82/b4/9eb026a8e62a04512435d3de25c93f7bda51c8b8c7991c1c0be70b5115a6/twofish-0.3.0.tar.gz", hash = "sha256:b09d8bb50d33b23ff34cafb1f9209f858f752935c6a5c901efb92a41acb830fa", size = 26039, upload-time = "2013-11-15T20:37:59.634Z" }
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "typer"
|
||||||
|
version = "0.27.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "annotated-doc" },
|
{ name = "annotated-doc" },
|
||||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
{ name = "rich" },
|
{ name = "rich" },
|
||||||
{name = "shellingham"}
|
{ name = "shellingham" },
|
||||||
]
|
]
|
||||||
name = "typer"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/16/f7/57713ba479fd405eb76de31404b2c744c289e336b2d999511ebf51e496f7/typer-0.27.2.tar.gz", hash = "sha256:269b7eb9d3c202ca84b4bc9618cb04ebb43d3d4d1e567e4c768607232c05f945", size = 204045, upload-time = "2026-08-28T10:26:55.046Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/16/f7/57713ba479fd405eb76de31404b2c744c289e336b2d999511ebf51e496f7/typer-0.27.2.tar.gz", hash = "sha256:269b7eb9d3c202ca84b4bc9618cb04ebb43d3d4d1e567e4c768607232c05f945", size = 204045, upload-time = "2026-08-28T10:26:55.046Z" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.27.2"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/dc/bf/205d0004930ede8f542fb58f601526fccf4ae7626075ca1e6c4de5d3d652/typer-0.27.2-py3-none-any.whl", hash = "sha256:b3a5fc4342d5fc8fda8fc3010b1cf117e9249aab7fae800c2eff62fd3842d97d", size = 123130, upload-time = "2026-08-28T10:26:53.752Z"}
|
{ url = "https://files.pythonhosted.org/packages/dc/bf/205d0004930ede8f542fb58f601526fccf4ae7626075ca1e6c4de5d3d652/typer-0.27.2-py3-none-any.whl", hash = "sha256:b3a5fc4342d5fc8fda8fc3010b1cf117e9249aab7fae800c2eff62fd3842d97d", size = 123130, upload-time = "2026-08-28T10:26:53.752Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
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"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "4.16.0"
|
version = "4.16.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
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" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{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"}
|
{ 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" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
dependencies = [
|
|
||||||
{name = "typing-extensions"}
|
|
||||||
]
|
|
||||||
name = "typing-inspection"
|
name = "typing-inspection"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/a3/26/b09b8010994eccc3c09092e6b34058f36a460eea2d4c3e8b910c695975a0/typing_inspection-0.4.4.tar.gz", hash = "sha256:547274fa6b0a561ccf549cc9524b999a578e737d015d8709d021f9d0d13bea47", size = 76928, upload-time = "2026-08-12T12:37:25.997Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/a3/26/b09b8010994eccc3c09092e6b34058f36a460eea2d4c3e8b910c695975a0/typing_inspection-0.4.4.tar.gz", hash = "sha256:547274fa6b0a561ccf549cc9524b999a578e737d015d8709d021f9d0d13bea47", size = 76928, upload-time = "2026-08-12T12:37:25.997Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/67/81/4add07e5172b7ac40d8ed5ff580409a7801a4fe26d529bdd915401dabfbe/typing_inspection-0.4.4-py3-none-any.whl", hash = "sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147", size = 14750, upload-time = "2026-08-12T12:37:24.648Z"}
|
{ url = "https://files.pythonhosted.org/packages/67/81/4add07e5172b7ac40d8ed5ff580409a7801a4fe26d529bdd915401dabfbe/typing_inspection-0.4.4-py3-none-any.whl", hash = "sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147", size = 14750, upload-time = "2026-08-12T12:37:24.648Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "urllib3"
|
name = "urllib3"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "2.8.0"
|
version = "2.8.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z"}
|
{ url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uv"
|
name = "uv"
|
||||||
sdist = {url = "https://files.pythonhosted.org/packages/6d/f5/34435c1d9ee52d38bda1d7d2948d8ef48a9ac9ec79e6fbfd81ced8b0ad19/uv-0.12.23.tar.gz", hash = "sha256:e952162a5be6847deaccf3fd5b41a628506fd9ff1ea4363b8c975bd6f927d832", size = 7197708, upload-time = "2026-10-03T17:33:01.864Z"}
|
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "0.12.23"
|
version = "0.12.23"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/6d/f5/34435c1d9ee52d38bda1d7d2948d8ef48a9ac9ec79e6fbfd81ced8b0ad19/uv-0.12.23.tar.gz", hash = "sha256:e952162a5be6847deaccf3fd5b41a628506fd9ff1ea4363b8c975bd6f927d832", size = 7197708, upload-time = "2026-10-03T17:33:01.864Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/7c/af/ed4bcd2fbebe19d613412d02053af44809d02a1204cb6cf0a7a9af7a02fa/uv-0.12.23-py3-none-linux_armv6l.whl", hash = "sha256:8f021dfbe5b6081021dd47fd8372cfba386fc5d39161e73d4f33cff90ce1760c", size = 22770792, upload-time = "2026-10-03T17:31:15.723Z" },
|
{ url = "https://files.pythonhosted.org/packages/7c/af/ed4bcd2fbebe19d613412d02053af44809d02a1204cb6cf0a7a9af7a02fa/uv-0.12.23-py3-none-linux_armv6l.whl", hash = "sha256:8f021dfbe5b6081021dd47fd8372cfba386fc5d39161e73d4f33cff90ce1760c", size = 22770792, upload-time = "2026-10-03T17:31:15.723Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/01/15/a2514d061b92d4b7c0ebefc3da51f3ff5a528e9f4c067ea2cf48c5573e5a/uv-0.12.23-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4951286e68f116fa41897ecf8e248cc2836cb013be6d4f37afae4049f9ef4df7", size = 21459315, upload-time = "2026-10-03T17:31:18.824Z" },
|
{ url = "https://files.pythonhosted.org/packages/01/15/a2514d061b92d4b7c0ebefc3da51f3ff5a528e9f4c067ea2cf48c5573e5a/uv-0.12.23-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4951286e68f116fa41897ecf8e248cc2836cb013be6d4f37afae4049f9ef4df7", size = 21459315, upload-time = "2026-10-03T17:31:18.824Z" },
|
||||||
@@ -1087,21 +1092,21 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/71/b7/340260cf1a92017b271869764a68d9a019d796c4a7fa80c6c1bbcf5721eb/uv-0.12.23-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:11d18c1589d7907376b4f3fa31028e46cc609ac4b7d83eabc2b04cd8ca1433cc", size = 23541384, upload-time = "2026-10-03T17:31:52.416Z" },
|
{ url = "https://files.pythonhosted.org/packages/71/b7/340260cf1a92017b271869764a68d9a019d796c4a7fa80c6c1bbcf5721eb/uv-0.12.23-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:11d18c1589d7907376b4f3fa31028e46cc609ac4b7d83eabc2b04cd8ca1433cc", size = 23541384, upload-time = "2026-10-03T17:31:52.416Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/77/76/3a7ab3ab0bd8ab107b50fe981a3198188c8260e9b17b629e64899eca709b/uv-0.12.23-py3-none-win32.whl", hash = "sha256:f05c5ad8d6cb4b2659cb6368ed02c067539415b24a2b69effd8ada576fdbf303", size = 20101333, upload-time = "2026-10-03T17:31:54.811Z" },
|
{ url = "https://files.pythonhosted.org/packages/77/76/3a7ab3ab0bd8ab107b50fe981a3198188c8260e9b17b629e64899eca709b/uv-0.12.23-py3-none-win32.whl", hash = "sha256:f05c5ad8d6cb4b2659cb6368ed02c067539415b24a2b69effd8ada576fdbf303", size = 20101333, upload-time = "2026-10-03T17:31:54.811Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/af/fd/816f4e8a76197312ec8037369e5b5c8a5ebde7aa118b6250259e031d3444/uv-0.12.23-py3-none-win_amd64.whl", hash = "sha256:fb8a4117a5224d73abe2204a1e744ae34b544f1b9a0b761576851deaa7215c12", size = 18138726, upload-time = "2026-10-03T17:31:57.498Z" },
|
{ url = "https://files.pythonhosted.org/packages/af/fd/816f4e8a76197312ec8037369e5b5c8a5ebde7aa118b6250259e031d3444/uv-0.12.23-py3-none-win_amd64.whl", hash = "sha256:fb8a4117a5224d73abe2204a1e744ae34b544f1b9a0b761576851deaa7215c12", size = 18138726, upload-time = "2026-10-03T17:31:57.498Z" },
|
||||||
{url = "https://files.pythonhosted.org/packages/d9/74/1906f7f3f785fcf37a72b371d4ab58ec7193c5760923136cca1376209bc8/uv-0.12.23-py3-none-win_arm64.whl", hash = "sha256:9a65258535db432df51ca7d26338c01431820b94b634762f5718fc55895f974e", size = 19208424, upload-time = "2026-10-03T17:31:59.726Z"}
|
{ url = "https://files.pythonhosted.org/packages/d9/74/1906f7f3f785fcf37a72b371d4ab58ec7193c5760923136cca1376209bc8/uv-0.12.23-py3-none-win_arm64.whl", hash = "sha256:9a65258535db432df51ca7d26338c01431820b94b634762f5718fc55895f974e", size = 19208424, upload-time = "2026-10-03T17:31:59.726Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
name = "virtualenv"
|
||||||
|
version = "21.14.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "distlib" },
|
{ name = "distlib" },
|
||||||
{ name = "filelock" },
|
{ name = "filelock" },
|
||||||
{ name = "packaging" },
|
{ name = "packaging" },
|
||||||
{ name = "platformdirs" },
|
{ name = "platformdirs" },
|
||||||
{name = "python-discovery"}
|
{ name = "python-discovery" },
|
||||||
]
|
]
|
||||||
name = "virtualenv"
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/c4/f9/f323b3b6058cff3853b31cf6a49c0425ed797bf9611572ec10d065e08bac/virtualenv-21.14.5.tar.gz", hash = "sha256:c4cb6c13e46b57225a999c7e22a09b163393878facc7ac4c059a57f46faa1647", size = 5467127, upload-time = "2026-10-02T17:42:25.613Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/c4/f9/f323b3b6058cff3853b31cf6a49c0425ed797bf9611572ec10d065e08bac/virtualenv-21.14.5.tar.gz", hash = "sha256:c4cb6c13e46b57225a999c7e22a09b163393878facc7ac4c059a57f46faa1647", size = 5467127, upload-time = "2026-10-02T17:42:25.613Z" }
|
||||||
source = {registry = "https://pypi.org/simple"}
|
|
||||||
version = "21.14.5"
|
|
||||||
wheels = [
|
wheels = [
|
||||||
{url = "https://files.pythonhosted.org/packages/df/93/084f10ebbecdedf7902ed68fbecc903f0e9c5742155bfffb05eccbc071da/virtualenv-21.14.5-py3-none-any.whl", hash = "sha256:b0651e0174982bba17cc6f0aaa2ef496730cb85a3f35eb5d1119d1c904f7d1da", size = 5487482, upload-time = "2026-10-02T17:42:23.38Z"}
|
{ url = "https://files.pythonhosted.org/packages/df/93/084f10ebbecdedf7902ed68fbecc903f0e9c5742155bfffb05eccbc071da/virtualenv-21.14.5-py3-none-any.whl", hash = "sha256:b0651e0174982bba17cc6f0aaa2ef496730cb85a3f35eb5d1119d1c904f7d1da", size = 5487482, upload-time = "2026-10-02T17:42:23.38Z" },
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user