From 3eaebda418139178fea311eba5893e173fe61b4d Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Wed, 15 Jan 2025 13:38:37 -0500 Subject: [PATCH 01/16] Re organize CLI tools into separate packages --- cli/admin/README.md | 1 + cli/admin/jumpstarter_admin_cli/__init__.py | 23 ++ .../admin/jumpstarter_admin_cli}/create.py | 13 +- .../jumpstarter_admin_cli}/create_test.py | 0 .../admin/jumpstarter_admin_cli}/delete.py | 13 +- .../jumpstarter_admin_cli}/delete_test.py | 0 .../admin/jumpstarter_admin_cli}/get.py | 23 +- .../admin/jumpstarter_admin_cli}/get_test.py | 0 .../jumpstarter_admin_cli}/import_res.py | 9 +- .../jumpstarter_admin_cli}/import_res_test.py | 0 .../admin/jumpstarter_admin_cli}/install.py | 4 +- cli/admin/pyproject.toml | 48 ++++ cli/client/README.md | 1 + cli/client/jumpstarter_client_cli/__init__.py | 29 +++ .../jumpstarter_client_cli/client_config.py | 121 +++++++++ .../jumpstarter_client_cli/client_shell.py | 2 +- .../jumpstarter_client_cli}/client_test.py | 2 +- .../client/jumpstarter_client_cli}/j.py | 0 .../client/jumpstarter_client_cli}/lease.py | 3 +- cli/client/pyproject.toml | 47 ++++ cli/common/README.md | 1 + .../jumpstarter_cli_common}/__init__.py | 5 +- .../common/jumpstarter_cli_common}/alias.py | 14 +- .../common/jumpstarter_cli_common}/k8s.py | 0 .../common/jumpstarter_cli_common}/opt.py | 0 .../common/jumpstarter_cli_common}/table.py | 0 .../common/jumpstarter_cli_common}/time.py | 0 .../common/jumpstarter_cli_common}/version.py | 2 +- cli/common/pyproject.toml | 42 +++ cli/exporter/README.md | 1 + .../jumpstarter_exporter_cli/__init__.py | 29 +++ .../jumpstarter_exporter_cli/exporter.py | 59 +++++ .../exporter_config.py | 64 +++++ .../exporter_test.py | 2 +- cli/exporter/pyproject.toml | 46 ++++ cli/jmp/README.md | 1 + cli/jmp/jumpstarter_cli/__init__.py | 18 ++ cli/jmp/jumpstarter_cli/__main__.py | 6 + cli/jmp/pyproject.toml | 51 ++++ jumpstarter/__main__.py | 6 - jumpstarter/cli/__init__.py | 0 jumpstarter/cli/client.py | 239 ------------------ jumpstarter/cli/exporter.py | 132 ---------- jumpstarter/cli/jmp.py | 32 --- pyproject.toml | 11 +- uv.lock | 209 +++++++++++++-- 46 files changed, 831 insertions(+), 478 deletions(-) create mode 100644 cli/admin/README.md create mode 100644 cli/admin/jumpstarter_admin_cli/__init__.py rename {jumpstarter/cli => cli/admin/jumpstarter_admin_cli}/create.py (99%) rename {jumpstarter/cli => cli/admin/jumpstarter_admin_cli}/create_test.py (100%) rename {jumpstarter/cli => cli/admin/jumpstarter_admin_cli}/delete.py (98%) rename {jumpstarter/cli => cli/admin/jumpstarter_admin_cli}/delete_test.py (100%) rename {jumpstarter/cli => cli/admin/jumpstarter_admin_cli}/get.py (99%) rename {jumpstarter/cli => cli/admin/jumpstarter_admin_cli}/get_test.py (100%) rename {jumpstarter/cli => cli/admin/jumpstarter_admin_cli}/import_res.py (96%) rename {jumpstarter/cli => cli/admin/jumpstarter_admin_cli}/import_res_test.py (100%) rename {jumpstarter/cli => cli/admin/jumpstarter_admin_cli}/install.py (97%) create mode 100644 cli/admin/pyproject.toml create mode 100644 cli/client/README.md create mode 100644 cli/client/jumpstarter_client_cli/__init__.py create mode 100644 cli/client/jumpstarter_client_cli/client_config.py rename jumpstarter/cli/shell.py => cli/client/jumpstarter_client_cli/client_shell.py (95%) rename {jumpstarter/cli => cli/client/jumpstarter_client_cli}/client_test.py (98%) rename {jumpstarter/cli => cli/client/jumpstarter_client_cli}/j.py (100%) rename {jumpstarter/cli => cli/client/jumpstarter_client_cli}/lease.py (96%) create mode 100644 cli/client/pyproject.toml create mode 100644 cli/common/README.md rename {jumpstarter/cli/util => cli/common/jumpstarter_cli_common}/__init__.py (77%) rename {jumpstarter/cli/util => cli/common/jumpstarter_cli_common}/alias.py (78%) rename {jumpstarter/cli/util => cli/common/jumpstarter_cli_common}/k8s.py (100%) rename {jumpstarter/cli/util => cli/common/jumpstarter_cli_common}/opt.py (100%) rename {jumpstarter/cli/util => cli/common/jumpstarter_cli_common}/table.py (100%) rename {jumpstarter/cli/util => cli/common/jumpstarter_cli_common}/time.py (100%) rename {jumpstarter/cli => cli/common/jumpstarter_cli_common}/version.py (92%) create mode 100644 cli/common/pyproject.toml create mode 100644 cli/exporter/README.md create mode 100644 cli/exporter/jumpstarter_exporter_cli/__init__.py create mode 100644 cli/exporter/jumpstarter_exporter_cli/exporter.py create mode 100644 cli/exporter/jumpstarter_exporter_cli/exporter_config.py rename {jumpstarter/cli => cli/exporter/jumpstarter_exporter_cli}/exporter_test.py (97%) create mode 100644 cli/exporter/pyproject.toml create mode 100644 cli/jmp/README.md create mode 100644 cli/jmp/jumpstarter_cli/__init__.py create mode 100644 cli/jmp/jumpstarter_cli/__main__.py create mode 100644 cli/jmp/pyproject.toml delete mode 100644 jumpstarter/__main__.py delete mode 100644 jumpstarter/cli/__init__.py delete mode 100644 jumpstarter/cli/client.py delete mode 100644 jumpstarter/cli/exporter.py delete mode 100644 jumpstarter/cli/jmp.py diff --git a/cli/admin/README.md b/cli/admin/README.md new file mode 100644 index 000000000..912d85bfd --- /dev/null +++ b/cli/admin/README.md @@ -0,0 +1 @@ +# Jumpstarter Admin CLI \ No newline at end of file diff --git a/cli/admin/jumpstarter_admin_cli/__init__.py b/cli/admin/jumpstarter_admin_cli/__init__.py new file mode 100644 index 000000000..be376e61a --- /dev/null +++ b/cli/admin/jumpstarter_admin_cli/__init__.py @@ -0,0 +1,23 @@ +import asyncclick as click + +from jumpstarter_cli_common import AliasedGroup, version +from .create import create +from .delete import delete +from .get import get +from .import_res import import_res +from .install import install + + +@click.group(cls=AliasedGroup) +def admin(): + """Jumpstarter Kubernetes cluster admin CLI tool""" + +admin.add_command(get) +admin.add_command(create) +admin.add_command(delete) +admin.add_command(install) +admin.add_command(import_res) +admin.add_command(version) + +if __name__ == "__main__": + admin() diff --git a/jumpstarter/cli/create.py b/cli/admin/jumpstarter_admin_cli/create.py similarity index 99% rename from jumpstarter/cli/create.py rename to cli/admin/jumpstarter_admin_cli/create.py index 751f67944..71516d28c 100644 --- a/jumpstarter/cli/create.py +++ b/cli/admin/jumpstarter_admin_cli/create.py @@ -2,13 +2,7 @@ from typing import Optional import asyncclick as click -from kubernetes_asyncio.client.exceptions import ApiException -from kubernetes_asyncio.config.config_exception import ConfigException - -from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 -from jumpstarter.k8s import ClientsV1Alpha1Api, ExportersV1Alpha1Api - -from .util import ( +from jumpstarter_cli_common import ( AliasedGroup, handle_k8s_api_exception, handle_k8s_config_exception, @@ -17,6 +11,11 @@ opt_log_level, opt_namespace, ) +from kubernetes_asyncio.client.exceptions import ApiException +from kubernetes_asyncio.config.config_exception import ConfigException + +from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 +from jumpstarter.k8s import ClientsV1Alpha1Api, ExportersV1Alpha1Api @click.group(cls=AliasedGroup) diff --git a/jumpstarter/cli/create_test.py b/cli/admin/jumpstarter_admin_cli/create_test.py similarity index 100% rename from jumpstarter/cli/create_test.py rename to cli/admin/jumpstarter_admin_cli/create_test.py diff --git a/jumpstarter/cli/delete.py b/cli/admin/jumpstarter_admin_cli/delete.py similarity index 98% rename from jumpstarter/cli/delete.py rename to cli/admin/jumpstarter_admin_cli/delete.py index ae8852a22..dcd08c30d 100644 --- a/jumpstarter/cli/delete.py +++ b/cli/admin/jumpstarter_admin_cli/delete.py @@ -2,13 +2,7 @@ from typing import Optional import asyncclick as click -from kubernetes_asyncio.client.exceptions import ApiException -from kubernetes_asyncio.config.config_exception import ConfigException - -from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 -from jumpstarter.k8s import ClientsV1Alpha1Api, ExportersV1Alpha1Api - -from .util import ( +from jumpstarter_cli_common import ( AliasedGroup, handle_k8s_api_exception, handle_k8s_config_exception, @@ -17,6 +11,11 @@ opt_log_level, opt_namespace, ) +from kubernetes_asyncio.client.exceptions import ApiException +from kubernetes_asyncio.config.config_exception import ConfigException + +from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 +from jumpstarter.k8s import ClientsV1Alpha1Api, ExportersV1Alpha1Api @click.group(cls=AliasedGroup) diff --git a/jumpstarter/cli/delete_test.py b/cli/admin/jumpstarter_admin_cli/delete_test.py similarity index 100% rename from jumpstarter/cli/delete_test.py rename to cli/admin/jumpstarter_admin_cli/delete_test.py diff --git a/jumpstarter/cli/get.py b/cli/admin/jumpstarter_admin_cli/get.py similarity index 99% rename from jumpstarter/cli/get.py rename to cli/admin/jumpstarter_admin_cli/get.py index a48a2e3df..60c1955fd 100644 --- a/jumpstarter/cli/get.py +++ b/cli/admin/jumpstarter_admin_cli/get.py @@ -2,6 +2,17 @@ from typing import Optional import asyncclick as click +from jumpstarter_cli_common import ( + AliasedGroup, + handle_k8s_api_exception, + handle_k8s_config_exception, + make_table, + opt_context, + opt_kubeconfig, + opt_log_level, + opt_namespace, + time_since, +) from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.config.config_exception import ConfigException @@ -14,18 +25,6 @@ V1Alpha1Lease, ) -from .util import ( - AliasedGroup, - handle_k8s_api_exception, - handle_k8s_config_exception, - make_table, - opt_context, - opt_kubeconfig, - opt_log_level, - opt_namespace, - time_since, -) - @click.group(cls=AliasedGroup) @opt_log_level diff --git a/jumpstarter/cli/get_test.py b/cli/admin/jumpstarter_admin_cli/get_test.py similarity index 100% rename from jumpstarter/cli/get_test.py rename to cli/admin/jumpstarter_admin_cli/get_test.py diff --git a/jumpstarter/cli/import_res.py b/cli/admin/jumpstarter_admin_cli/import_res.py similarity index 96% rename from jumpstarter/cli/import_res.py rename to cli/admin/jumpstarter_admin_cli/import_res.py index 77853d058..79c9ec726 100644 --- a/jumpstarter/cli/import_res.py +++ b/cli/admin/jumpstarter_admin_cli/import_res.py @@ -1,6 +1,13 @@ from typing import Optional import asyncclick as click +from jumpstarter_cli_common import ( + handle_k8s_api_exception, + handle_k8s_config_exception, + opt_context, + opt_kubeconfig, + opt_namespace, +) from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.config.config_exception import ConfigException @@ -11,8 +18,6 @@ from jumpstarter.config.exporter import ExporterConfigV1Alpha1 from jumpstarter.k8s import ClientsV1Alpha1Api, ExportersV1Alpha1Api -from .util import handle_k8s_api_exception, handle_k8s_config_exception, opt_context, opt_kubeconfig, opt_namespace - @click.group("import") def import_res(): diff --git a/jumpstarter/cli/import_res_test.py b/cli/admin/jumpstarter_admin_cli/import_res_test.py similarity index 100% rename from jumpstarter/cli/import_res_test.py rename to cli/admin/jumpstarter_admin_cli/import_res_test.py diff --git a/jumpstarter/cli/install.py b/cli/admin/jumpstarter_admin_cli/install.py similarity index 97% rename from jumpstarter/cli/install.py rename to cli/admin/jumpstarter_admin_cli/install.py index 9bf5ab73b..270c37f9d 100644 --- a/jumpstarter/cli/install.py +++ b/cli/admin/jumpstarter_admin_cli/install.py @@ -1,12 +1,10 @@ from typing import Literal, Optional import asyncclick as click +from jumpstarter_cli_common import get_client_version, opt_context, opt_kubeconfig from jumpstarter.k8s import get_ip_address, helm_installed, install_helm_chart -from .util import opt_context, opt_kubeconfig -from .version import get_client_version - def get_chart_version() -> str: client_version = get_client_version() diff --git a/cli/admin/pyproject.toml b/cli/admin/pyproject.toml new file mode 100644 index 000000000..d031b1e03 --- /dev/null +++ b/cli/admin/pyproject.toml @@ -0,0 +1,48 @@ +[project] +name = "jumpstarter-admin-cli" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Nick Cao", email = "ncao@redhat.com" }, + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "jumpstarter-cli-common", + "kubernetes>=31.0.0", + "kubernetes-asyncio>=31.1.0", + "asyncclick>=8.1.7.2", +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "pytest-cov>=5.0.0", +] + +[tool.uv.sources] +jumpstarter-cli-common = { workspace = true } + +[project.scripts] +jmp-admin = "jumpstarter_admin_cli:admin" + +[tool.hatch.build.targets.wheel] +packages = ["jumpstarter_admin_cli"] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/cli/client/README.md b/cli/client/README.md new file mode 100644 index 000000000..947a5b210 --- /dev/null +++ b/cli/client/README.md @@ -0,0 +1 @@ +# Jumpstarter Client CLI \ No newline at end of file diff --git a/cli/client/jumpstarter_client_cli/__init__.py b/cli/client/jumpstarter_client_cli/__init__.py new file mode 100644 index 000000000..7812d3d8e --- /dev/null +++ b/cli/client/jumpstarter_client_cli/__init__.py @@ -0,0 +1,29 @@ +import asyncclick as click +from jumpstarter_cli_common import AliasedGroup, version + +from jumpstarter.common.utils import env + +from .client_config import create_client_config, delete_client_config, list_client_configs, use_client_config +from .client_shell import client_shell +from .lease import lease + + +@click.group(cls=AliasedGroup) +def client(): + """Jumpstarter client CLI tool""" + +def j(): + with env() as client: + client.cli()(standalone_mode=False) + + +client.add_command(create_client_config) +client.add_command(delete_client_config) +client.add_command(list_client_configs) +client.add_command(use_client_config) +client.add_command(lease) +client.add_command(client_shell) +client.add_command(version) + +if __name__ == "__main__": + client() diff --git a/cli/client/jumpstarter_client_cli/client_config.py b/cli/client/jumpstarter_client_cli/client_config.py new file mode 100644 index 000000000..5a08aa25f --- /dev/null +++ b/cli/client/jumpstarter_client_cli/client_config.py @@ -0,0 +1,121 @@ +from typing import Optional + +import asyncclick as click +from jumpstarter_cli_common import make_table + +from jumpstarter.config import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, UserConfigV1Alpha1 + + +@click.command("create-config", short_help="Create a client config.") +@click.argument("name") +@click.option( + "-o", + "--out", + type=click.Path(dir_okay=False, resolve_path=True, writable=True), + help="Specify an output file for the client config.", +) +@click.option( + "-e", + "--endpoint", + type=str, + help="Enter the Jumpstarter service endpoint.", + prompt="Enter a valid Jumpstarter service endpoint", +) +@click.option( + "-t", + "--token", + type=str, + help="A valid Jumpstarter auth token generated by the Jumpstarter service.", + prompt="Enter a Jumpstarter auth token (hidden)", + hide_input=True, +) +@click.option( + "-a", + "--allow", + type=str, + help="A comma-separated list of driver client packages to load.", + prompt="Enter a comma-separated list of allowed driver packages (optional)", + default="", +) +@click.option("--unsafe", is_flag=True, help="Should all driver client packages be allowed to load (UNSAFE!).") +def create_client_config( + name: str, + endpoint: str, + token: str, + allow: str, + unsafe: bool, + out: Optional[str], +): + """Create a Jumpstarter client configuration.""" + if out is None and ClientConfigV1Alpha1.exists(name): + raise click.ClickException(f"A client with the name '{name}' already exists.") + + config = ClientConfigV1Alpha1( + name=name, + endpoint=endpoint, + token=token, + drivers=ClientConfigV1Alpha1Drivers(allow=allow.split(","), unsafe=unsafe), + ) + ClientConfigV1Alpha1.save(config, out) + + # If this is the only client config, set it as default + if out is None and len(ClientConfigV1Alpha1.list()) == 1: + user_config = UserConfigV1Alpha1.load_or_create() + user_config.config.current_client = config + UserConfigV1Alpha1.save(user_config) + + +def set_next_client(name: str): + user_config = UserConfigV1Alpha1.load() if UserConfigV1Alpha1.exists() else None + if ( + user_config is not None + and user_config.config.current_client is not None + and user_config.config.current_client.name == name + ): + for c in ClientConfigV1Alpha1.list(): + if c.name != name: + # Use the next available client config + user_config.use_client(c.name) + return + # Otherwise, set client to none + user_config.use_client(None) + + +@click.command("delete-config", short_help="Delete a client config.") +@click.argument("name", type=str) +def delete_client_config(name: str): + """Delete a Jumpstarter client configuration.""" + set_next_client(name) + ClientConfigV1Alpha1.delete(name) + + +@click.command("list-configs", short_help="List available client configurations.") +def list_client_configs(): + # Allow listing if there is no user config defined + current_name = None + if UserConfigV1Alpha1.exists(): + current_client = UserConfigV1Alpha1.load().config.current_client + current_name = current_client.name if current_client is not None else None + + configs = ClientConfigV1Alpha1.list() + + columns = ["CURRENT", "NAME", "ENDPOINT", "PATH"] + + def make_row(c: ClientConfigV1Alpha1): + return { + "CURRENT": "*" if current_name == c.name else "", + "NAME": c.name, + "ENDPOINT": c.endpoint, + "PATH": str(c.path), + } + + rows = list(map(make_row, configs)) + click.echo(make_table(columns, rows)) + + +@click.command("use-config", short_help="Select the current client config.") +@click.argument("name", type=str) +def use_client_config(name: str): + """Select the current Jumpstarter client configuration to use.""" + user_config = UserConfigV1Alpha1.load_or_create() + user_config.use_client(name) diff --git a/jumpstarter/cli/shell.py b/cli/client/jumpstarter_client_cli/client_shell.py similarity index 95% rename from jumpstarter/cli/shell.py rename to cli/client/jumpstarter_client_cli/client_shell.py index ef5aa7ca5..ec5c11857 100644 --- a/jumpstarter/cli/shell.py +++ b/cli/client/jumpstarter_client_cli/client_shell.py @@ -12,7 +12,7 @@ @click.argument("name", type=str, default="") @click.option("-l", "--label", "labels", type=(str, str), multiple=True) @click.option("-n", "--lease", "lease_name", type=str) -def shell(name: str, labels, lease_name): +def client_shell(name: str, labels, lease_name): """Spawns a shell connecting to a leased remote exporter""" if name: config = ClientConfigV1Alpha1.load(name) diff --git a/jumpstarter/cli/client_test.py b/cli/client/jumpstarter_client_cli/client_test.py similarity index 98% rename from jumpstarter/cli/client_test.py rename to cli/client/jumpstarter_client_cli/client_test.py index f560dd663..a869c4bd9 100644 --- a/jumpstarter/cli/client_test.py +++ b/cli/client/jumpstarter_client_cli/client_test.py @@ -3,7 +3,7 @@ from jumpstarter.config import ClientConfigV1Alpha1, UserConfigV1Alpha1 -from .client import client +from .client_config import client @pytest.fixture diff --git a/jumpstarter/cli/j.py b/cli/client/jumpstarter_client_cli/j.py similarity index 100% rename from jumpstarter/cli/j.py rename to cli/client/jumpstarter_client_cli/j.py diff --git a/jumpstarter/cli/lease.py b/cli/client/jumpstarter_client_cli/lease.py similarity index 96% rename from jumpstarter/cli/lease.py rename to cli/client/jumpstarter_client_cli/lease.py index 956dda56f..24b20ed1f 100644 --- a/jumpstarter/cli/lease.py +++ b/cli/client/jumpstarter_client_cli/lease.py @@ -1,12 +1,11 @@ import asyncclick as click +from jumpstarter_cli_common import AliasedGroup from jumpstarter.config import ( ClientConfigV1Alpha1, UserConfigV1Alpha1, ) -from .util import AliasedGroup - @click.group(cls=AliasedGroup, short_help="") def lease(): diff --git a/cli/client/pyproject.toml b/cli/client/pyproject.toml new file mode 100644 index 000000000..51bc5302d --- /dev/null +++ b/cli/client/pyproject.toml @@ -0,0 +1,47 @@ +[project] +name = "jumpstarter-client-cli" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Nick Cao", email = "ncao@redhat.com" }, + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "jumpstarter-cli-common", + "asyncclick>=8.1.7.2", +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "pytest-cov>=5.0.0", +] + +[tool.uv.sources] +jumpstarter-cli-common = { workspace = true } + +[project.scripts] +jmp-client = "jumpstarter_client_cli:client" +j = "jumpstarter_client_cli:j" + +[tool.hatch.build.targets.wheel] +packages = ["jumpstarter_client_cli"] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/cli/common/README.md b/cli/common/README.md new file mode 100644 index 000000000..7527686f9 --- /dev/null +++ b/cli/common/README.md @@ -0,0 +1 @@ +# Jumpstarter CLI Common Utils \ No newline at end of file diff --git a/jumpstarter/cli/util/__init__.py b/cli/common/jumpstarter_cli_common/__init__.py similarity index 77% rename from jumpstarter/cli/util/__init__.py rename to cli/common/jumpstarter_cli_common/__init__.py index a2e83e35f..25c96f8a2 100644 --- a/jumpstarter/cli/util/__init__.py +++ b/cli/common/jumpstarter_cli_common/__init__.py @@ -3,6 +3,7 @@ from .opt import opt_context, opt_kubeconfig, opt_log_level, opt_namespace from .table import make_table from .time import time_since +from .version import get_client_version, version __all__ = [ "AliasedGroup", @@ -13,5 +14,7 @@ "opt_namespace", "time_since", "handle_k8s_api_exception", - "handle_k8s_config_exception" + "handle_k8s_config_exception", + "version", + "get_client_version" ] diff --git a/jumpstarter/cli/util/alias.py b/cli/common/jumpstarter_cli_common/alias.py similarity index 78% rename from jumpstarter/cli/util/alias.py rename to cli/common/jumpstarter_cli_common/alias.py index 04550b6dc..88c68a6a7 100644 --- a/jumpstarter/cli/util/alias.py +++ b/cli/common/jumpstarter_cli_common/alias.py @@ -7,11 +7,19 @@ class AliasedGroup(click.Group): common_aliases: dict[str, list[str]] = { "remove": ["rm"], "list": ["ls"], - "create": ["cr"], + "create": ["c"], + "import": ["i"], + "get": ["g"], + "admin": ["a"], + "create-config": ["cc"], + "delete-config": ["dc"], + "edit-config": ["ec"], + "list-configs": ["lc"], + "use-config": ["uc"], "move": ["mv"], "config": ["conf"], - "delete": ["del"], - "shell": ["sh"], + "delete": ["del", "d"], + "shell": ["sh", "s"], "exporter": ["exporters", "e"], "client": ["clients", "c"], "lease": ["leases", "l"], diff --git a/jumpstarter/cli/util/k8s.py b/cli/common/jumpstarter_cli_common/k8s.py similarity index 100% rename from jumpstarter/cli/util/k8s.py rename to cli/common/jumpstarter_cli_common/k8s.py diff --git a/jumpstarter/cli/util/opt.py b/cli/common/jumpstarter_cli_common/opt.py similarity index 100% rename from jumpstarter/cli/util/opt.py rename to cli/common/jumpstarter_cli_common/opt.py diff --git a/jumpstarter/cli/util/table.py b/cli/common/jumpstarter_cli_common/table.py similarity index 100% rename from jumpstarter/cli/util/table.py rename to cli/common/jumpstarter_cli_common/table.py diff --git a/jumpstarter/cli/util/time.py b/cli/common/jumpstarter_cli_common/time.py similarity index 100% rename from jumpstarter/cli/util/time.py rename to cli/common/jumpstarter_cli_common/time.py diff --git a/jumpstarter/cli/version.py b/cli/common/jumpstarter_cli_common/version.py similarity index 92% rename from jumpstarter/cli/version.py rename to cli/common/jumpstarter_cli_common/version.py index 8448740e7..0d78ef945 100644 --- a/jumpstarter/cli/version.py +++ b/cli/common/jumpstarter_cli_common/version.py @@ -11,7 +11,7 @@ def get_client_version(): def get_cli_path(): - """Get the path of the current Jumpstarter binary""" + """Get the path of the current Jumpstarter CLI binary""" return os.path.dirname(os.path.dirname(os.path.abspath(__file__))) diff --git a/cli/common/pyproject.toml b/cli/common/pyproject.toml new file mode 100644 index 000000000..56b55b1f2 --- /dev/null +++ b/cli/common/pyproject.toml @@ -0,0 +1,42 @@ +[project] +name = "jumpstarter-cli-common" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Nick Cao", email = "ncao@redhat.com" }, + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "asyncclick>=8.1.7.2", +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "pytest-cov>=5.0.0", +] + +[tool.uv.sources] +jumpstarter-cli-common = { workspace = true } + +[tool.hatch.build.targets.wheel] +packages = ["jumpstarter_cli_common"] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/cli/exporter/README.md b/cli/exporter/README.md new file mode 100644 index 000000000..6f2310302 --- /dev/null +++ b/cli/exporter/README.md @@ -0,0 +1 @@ +# Jumpstarter Exporter CLI \ No newline at end of file diff --git a/cli/exporter/jumpstarter_exporter_cli/__init__.py b/cli/exporter/jumpstarter_exporter_cli/__init__.py new file mode 100644 index 000000000..e75d71678 --- /dev/null +++ b/cli/exporter/jumpstarter_exporter_cli/__init__.py @@ -0,0 +1,29 @@ +import logging +from typing import Optional + +import asyncclick as click +from jumpstarter_cli_common import AliasedGroup, opt_log_level, version + +from .exporter import exporter_shell, run_exporter +from .exporter_config import create_exporter_config, delete_exporter_config, edit_exporter_config, list_exporter_configs + + +@click.group(cls=AliasedGroup) +@opt_log_level +def exporter(log_level: Optional[str]): + """Jumpstarter exporter CLI tool""" + if log_level: + logging.basicConfig(level=log_level.upper()) + else: + logging.basicConfig(level=logging.INFO) + +exporter.add_command(create_exporter_config) +exporter.add_command(delete_exporter_config) +exporter.add_command(edit_exporter_config) +exporter.add_command(list_exporter_configs) +exporter.add_command(run_exporter) +exporter.add_command(exporter_shell) +exporter.add_command(version) + +if __name__ == "__main__": + exporter() diff --git a/cli/exporter/jumpstarter_exporter_cli/exporter.py b/cli/exporter/jumpstarter_exporter_cli/exporter.py new file mode 100644 index 000000000..945587535 --- /dev/null +++ b/cli/exporter/jumpstarter_exporter_cli/exporter.py @@ -0,0 +1,59 @@ +import sys +import traceback +from pathlib import Path + +import asyncclick as click + +from jumpstarter.common.utils import launch_shell +from jumpstarter.config.exporter import ExporterConfigV1Alpha1 + +arg_alias = click.argument("alias", default="default") + +opt_config_path = click.option( + "-c", "--config", "config_path", type=click.Path(exists=True), help="Path of exporter config, overrides ALIAS" +) + + +async def _serve_with_exc_handling(exporter): + result = 0 + try: + await exporter.serve() + except* Exception as excgroup: + print(f"Exception while serving on the exporter: {excgroup.exceptions}", file=sys.stderr) + for exc in excgroup.exceptions: + traceback.print_exception(type(exc), exc, exc.__traceback__, file=sys.stderr) + result = 1 + return result + + +@click.command("run") +@arg_alias +@opt_config_path +async def run_exporter(alias, config_path): + """Run an exporter locally.""" + try: + if config_path: + config = ExporterConfigV1Alpha1.load_path(Path(config_path)) + else: + config = ExporterConfigV1Alpha1.load(alias) + except FileNotFoundError as err: + raise click.ClickException(f'exporter "{alias}" does not exist') from err + + return await _serve_with_exc_handling(config) + +@click.command("shell") +@arg_alias +@opt_config_path +def exporter_shell(alias, config_path): + """Spawns a shell connecting to a transient exporter""" + try: + if config_path: + config = ExporterConfigV1Alpha1.load_path(Path(config_path)) + else: + config = ExporterConfigV1Alpha1.load(alias) + except FileNotFoundError as err: + raise click.ClickException(f'exporter "{alias}" does not exist') from err + + with config.serve_unix() as path: + # SAFETY: the exporter config is local thus considered trusted + launch_shell(path, allow=[], unsafe=True) diff --git a/cli/exporter/jumpstarter_exporter_cli/exporter_config.py b/cli/exporter/jumpstarter_exporter_cli/exporter_config.py new file mode 100644 index 000000000..6283f6098 --- /dev/null +++ b/cli/exporter/jumpstarter_exporter_cli/exporter_config.py @@ -0,0 +1,64 @@ +import asyncclick as click +from jumpstarter_cli_common import make_table + +from jumpstarter.config.exporter import ExporterConfigV1Alpha1 + +arg_alias = click.argument("alias", default="default") + + +@click.command("create-config") +@click.option("--endpoint", prompt=True) +@click.option("--token", prompt=True) +@arg_alias +def create_exporter_config(alias, endpoint, token): + """Create an exporter config.""" + try: + ExporterConfigV1Alpha1.load(alias) + except FileNotFoundError: + pass + else: + raise click.ClickException(f'exporter "{alias}" exists') + + config = ExporterConfigV1Alpha1( + alias=alias, + endpoint=endpoint, + token=token, + ) + ExporterConfigV1Alpha1.save(config) + + +@click.command("delete-config") +@arg_alias +def delete_exporter_config(alias): + """Delete an exporter config.""" + try: + ExporterConfigV1Alpha1.load(alias) + except FileNotFoundError as err: + raise click.ClickException(f'exporter "{alias}" does not exist') from err + ExporterConfigV1Alpha1.delete(alias) + + +@click.command("edit-config") +@arg_alias +def edit_exporter_config(alias): + """Edit an exporter config.""" + try: + config = ExporterConfigV1Alpha1.load(alias) + except FileNotFoundError as err: + raise click.ClickException(f'exporter "{alias}" does not exist') from err + click.edit(filename=config.path) + + +@click.command("list-configs") +def list_exporter_configs(): + """List exporter configs.""" + exporters = ExporterConfigV1Alpha1.list() + columns = ["ALIAS", "PATH"] + rows = [ + { + "ALIAS": exporter.alias, + "PATH": str(exporter.path), + } + for exporter in exporters + ] + click.echo(make_table(columns, rows)) diff --git a/jumpstarter/cli/exporter_test.py b/cli/exporter/jumpstarter_exporter_cli/exporter_test.py similarity index 97% rename from jumpstarter/cli/exporter_test.py rename to cli/exporter/jumpstarter_exporter_cli/exporter_test.py index f7717121a..e940690c3 100644 --- a/jumpstarter/cli/exporter_test.py +++ b/cli/exporter/jumpstarter_exporter_cli/exporter_test.py @@ -3,7 +3,7 @@ from jumpstarter.config.exporter import ExporterConfigV1Alpha1 -from .exporter import exporter +from .exporter_config import exporter @pytest.fixture diff --git a/cli/exporter/pyproject.toml b/cli/exporter/pyproject.toml new file mode 100644 index 000000000..0e5c87d27 --- /dev/null +++ b/cli/exporter/pyproject.toml @@ -0,0 +1,46 @@ +[project] +name = "jumpstarter-exporter-cli" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Nick Cao", email = "ncao@redhat.com" }, + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "jumpstarter-cli-common", + "asyncclick>=8.1.7.2", +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "pytest-cov>=5.0.0", +] + +[project.scripts] +jmp-client = "jumpstarter_exporter_cli:exporter" + +[tool.uv.sources] +jumpstarter-cli-common = { workspace = true } + +[tool.hatch.build.targets.wheel] +packages = ["jumpstarter_exporter_cli"] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/cli/jmp/README.md b/cli/jmp/README.md new file mode 100644 index 000000000..105e567fb --- /dev/null +++ b/cli/jmp/README.md @@ -0,0 +1 @@ +# The Jumpstarter CLI \ No newline at end of file diff --git a/cli/jmp/jumpstarter_cli/__init__.py b/cli/jmp/jumpstarter_cli/__init__.py new file mode 100644 index 000000000..42f8ba05f --- /dev/null +++ b/cli/jmp/jumpstarter_cli/__init__.py @@ -0,0 +1,18 @@ +import asyncclick as click +from jumpstarter_admin_cli import admin +from jumpstarter_cli_common import AliasedGroup, version +from jumpstarter_client_cli import client +from jumpstarter_exporter_cli import exporter + + +@click.group(cls=AliasedGroup) +def jmp(): + """The Jumpstarter CLI""" + +jmp.add_command(client) +jmp.add_command(exporter) +jmp.add_command(admin) +jmp.add_command(version) + +if __name__ == "__main__": + jmp() diff --git a/cli/jmp/jumpstarter_cli/__main__.py b/cli/jmp/jumpstarter_cli/__main__.py new file mode 100644 index 000000000..95a4f5ac9 --- /dev/null +++ b/cli/jmp/jumpstarter_cli/__main__.py @@ -0,0 +1,6 @@ +"""Allow running Jumpstarter through `python -m jumpstarter-cli`.""" + +from . import jmp + +if __name__ == "__main__": + jmp(prog_name="jmp") diff --git a/cli/jmp/pyproject.toml b/cli/jmp/pyproject.toml new file mode 100644 index 000000000..eeaf576bf --- /dev/null +++ b/cli/jmp/pyproject.toml @@ -0,0 +1,51 @@ +[project] +name = "jumpstarter-cli" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Nick Cao", email = "ncao@redhat.com" }, + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "jumpstarter-cli-common", + "jumpstarter-client-cli", + "jumpstarter-admin-cli", + "jumpstarter-exporter-cli" +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "pytest-cov>=5.0.0", +] + +[project.scripts] +jmp = "jumpstarter_cli:jmp" + +[tool.uv.sources] +jumpstarter-cli-common = { workspace = true } +jumpstarter-admin-cli = { workspace = true } +jumpstarter-client-cli = { workspace = true } +jumpstarter-exporter-cli = { workspace = true } + +[tool.hatch.build.targets.wheel] +packages = ["jumpstarter_cli"] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/jumpstarter/__main__.py b/jumpstarter/__main__.py deleted file mode 100644 index d7892b385..000000000 --- a/jumpstarter/__main__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Allow running Jumpstarter through `python -m jumpstarter`.""" - -from jumpstarter.cli.jmp import jmp - -if __name__ == "__main__": - jmp(prog_name="jmp") diff --git a/jumpstarter/cli/__init__.py b/jumpstarter/cli/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/jumpstarter/cli/client.py b/jumpstarter/cli/client.py deleted file mode 100644 index 65f39dd18..000000000 --- a/jumpstarter/cli/client.py +++ /dev/null @@ -1,239 +0,0 @@ -import logging -from typing import Optional - -import asyncclick as click - -from jumpstarter.common import MetadataFilter -from jumpstarter.common.utils import launch_shell -from jumpstarter.config import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, UserConfigV1Alpha1 - -from .util import AliasedGroup, make_table -from .version import version - - -@click.group(cls=AliasedGroup, short_help="Manage and interact with clients.") -def client(): - logging.basicConfig(level=logging.INFO) - - -@client.group(short_help="Managed leases held by client.") -def lease(): - pass - -@lease.command("request") -@click.option("-l", "--label", "labels", type=(str, str), multiple=True) -@click.argument("name", type=str, default="") -def lease_request(name, labels): - """Request an exporter lease from the jumpstarter controller. - -The result of this command will be a lease ID that can be used to -connect to the remote exporter. - -This is useful for multi-step workflows where you want to hold a lease -for a specific exporter while performing multiple operations, or for -CI environments where one step will request the lease and other steps -will perform operations on the leased exporter. - -Example: - -.. code-block:: bash - - $ JMP_LEASE=$(jmp lease request -l label match) - $ jmp shell - $$ j --help - $$ exit - $ jmp lease release -l "${JMP_LEASE}" - -""" - try: - if name: - config = ClientConfigV1Alpha1.load(name) - else: - config = UserConfigV1Alpha1.load_or_create().config.current_client - if not config: - raise ValueError("No client specified") - lease = config.request_lease(metadata_filter=MetadataFilter(labels=dict(labels))) - print(lease.name) - except ValueError as e: - raise click.ClickException(str(e)) from e - except Exception as e: - raise e - -@lease.command("list") -@click.argument("name", type=str, default="") -def lease_list(name): - if name: - config = ClientConfigV1Alpha1.load(name) - else: - config = UserConfigV1Alpha1.load_or_create().config.current_client - if not config: - raise click.ClickException("no client specified") - - for lease in config.list_leases(): - print(lease) - - -@lease.command("release") -@click.argument("name", type=str, default="") -@click.option("-l", "--lease", "lease", type=str, default="") -@click.option("--all", "all_leases", is_flag=True) -def lease_release(name, lease, all_leases): - if name: - config = ClientConfigV1Alpha1.load(name) - else: - config = UserConfigV1Alpha1.load_or_create().config.current_client - if not config: - raise click.ClickException("no client specified") - - if all_leases: - for lease in config.list_leases(): - config.release_lease(lease) - else: - if not lease: - raise click.ClickException("no lease specified") - config.release_lease(lease) - - -@click.command("create", short_help="Create a client configuration.") -@click.argument("name") -@click.option( - "-o", - "--out", - type=click.Path(dir_okay=False, resolve_path=True, writable=True), - help="Specify an output file for the client config.", -) -@click.option( - "-e", - "--endpoint", - type=str, - help="Enter the Jumpstarter service endpoint.", - prompt="Enter a valid Jumpstarter service endpoint", -) -@click.option( - "-t", - "--token", - type=str, - help="A valid Jumpstarter auth token generated by the Jumpstarter service.", - prompt="Enter a Jumpstarter auth token (hidden)", - hide_input=True, -) -@click.option( - "-a", - "--allow", - type=str, - help="A comma-separated list of driver client packages to load.", - prompt="Enter a comma-separated list of allowed driver packages (optional)", - default="", -) -@click.option("--unsafe", is_flag=True, help="Should all driver client packages be allowed to load (UNSAFE!).") -def client_create( - name: str, - endpoint: str, - token: str, - allow: str, - unsafe: bool, - out: Optional[str], -): - """Create a Jumpstarter client configuration.""" - if out is None and ClientConfigV1Alpha1.exists(name): - raise click.ClickException(f"A client with the name '{name}' already exists.") - - config = ClientConfigV1Alpha1( - name=name, - endpoint=endpoint, - token=token, - drivers=ClientConfigV1Alpha1Drivers(allow=allow.split(","), unsafe=unsafe), - ) - ClientConfigV1Alpha1.save(config, out) - - # If this is the only client config, set it as default - if out is None and len(ClientConfigV1Alpha1.list()) == 1: - user_config = UserConfigV1Alpha1.load_or_create() - user_config.config.current_client = config - UserConfigV1Alpha1.save(user_config) - - -def set_next_client(name: str): - user_config = UserConfigV1Alpha1.load() if UserConfigV1Alpha1.exists() else None - if ( - user_config is not None - and user_config.config.current_client is not None - and user_config.config.current_client.name == name - ): - for c in ClientConfigV1Alpha1.list(): - if c.name != name: - # Use the next available client config - user_config.use_client(c.name) - return - # Otherwise, set client to none - user_config.use_client(None) - - -@click.command("delete", short_help="Delete a client configuration.") -@click.argument("name", type=str) -def client_delete(name: str): - """Delete a Jumpstarter client configuration.""" - set_next_client(name) - ClientConfigV1Alpha1.delete(name) - - -@click.command("list", short_help="List available client configurations.") -def client_list(): - # Allow listing if there is no user config defined - current_name = None - if UserConfigV1Alpha1.exists(): - current_client = UserConfigV1Alpha1.load().config.current_client - current_name = current_client.name if current_client is not None else None - - configs = ClientConfigV1Alpha1.list() - - columns = ["CURRENT", "NAME", "ENDPOINT", "PATH"] - - def make_row(c: ClientConfigV1Alpha1): - return { - "CURRENT": "*" if current_name == c.name else "", - "NAME": c.name, - "ENDPOINT": c.endpoint, - "PATH": str(c.path), - } - - rows = list(map(make_row, configs)) - click.echo(make_table(columns, rows)) - - -@click.command("use", short_help="Select the current client configuration.") -@click.argument("name", type=str) -def client_use(name: str): - """Select the current Jumpstarter client configuration to use.""" - user_config = UserConfigV1Alpha1.load_or_create() - user_config.use_client(name) - - -@click.command("shell", short_help="Spawns a shell connecting to a leased remote exporter") -@click.argument("name", type=str, default="") -@click.option("-l", "--label", "labels", type=(str, str), multiple=True) -@click.option("-n", "--lease", "lease_name", type=str) -def client_shell(name: str, labels, lease_name): - """Spawns a shell connecting to a leased remote exporter""" - if name: - config = ClientConfigV1Alpha1.load(name) - else: - config = UserConfigV1Alpha1.load_or_create().config.current_client - if not config: - raise ValueError("no client specified") - - with config.lease(metadata_filter=MetadataFilter(labels=dict(labels)), lease_name=lease_name) as lease: - with lease.serve_unix() as path: - launch_shell(path, config.drivers.allow, config.drivers.unsafe) - - -client.add_command(client_create) -client.add_command(client_delete) -client.add_command(client_list) -client.add_command(client_use) -client.add_command(client_shell) -client.add_command(version) - - -if __name__ == "__main__": - client() diff --git a/jumpstarter/cli/exporter.py b/jumpstarter/cli/exporter.py deleted file mode 100644 index 6bf8c8df6..000000000 --- a/jumpstarter/cli/exporter.py +++ /dev/null @@ -1,132 +0,0 @@ -import logging -import sys -import traceback -from pathlib import Path -from typing import Optional - -import asyncclick as click - -from jumpstarter.common.utils import launch_shell -from jumpstarter.config.exporter import ExporterConfigV1Alpha1 - -from .util import AliasedGroup, make_table, opt_log_level - -arg_alias = click.argument("alias", default="default") - -opt_config_path = click.option( - "-c", "--config", "config_path", type=click.Path(exists=True), help="Path of exporter config, overrides ALIAS" -) - -@click.group(cls=AliasedGroup) -@opt_log_level -def exporter(log_level: Optional[str]): - """Manage and run exporters""" - if log_level: - logging.basicConfig(level=log_level.upper()) - else: - logging.basicConfig(level=logging.INFO) - - -@exporter.command -@click.option("--endpoint", prompt=True) -@click.option("--token", prompt=True) -@arg_alias -def create(alias, endpoint, token): - """Create exporter""" - try: - ExporterConfigV1Alpha1.load(alias) - except FileNotFoundError: - pass - else: - raise click.ClickException(f'exporter "{alias}" exists') - - config = ExporterConfigV1Alpha1( - alias=alias, - endpoint=endpoint, - token=token, - ) - ExporterConfigV1Alpha1.save(config) - - -@exporter.command -@arg_alias -def delete(alias): - """Delete exporter""" - try: - ExporterConfigV1Alpha1.load(alias) - except FileNotFoundError as err: - raise click.ClickException(f'exporter "{alias}" does not exist') from err - ExporterConfigV1Alpha1.delete(alias) - - -@exporter.command -@arg_alias -def edit(alias): - """Edit exporter""" - try: - config = ExporterConfigV1Alpha1.load(alias) - except FileNotFoundError as err: - raise click.ClickException(f'exporter "{alias}" does not exist') from err - click.edit(filename=config.path) - - -@exporter.command -def list(): - """List exporters""" - exporters = ExporterConfigV1Alpha1.list() - columns = ["ALIAS", "PATH"] - rows = [ - { - "ALIAS": exporter.alias, - "PATH": str(exporter.path), - } - for exporter in exporters - ] - click.echo(make_table(columns, rows)) - - -async def _serve_with_exc_handling(exporter): - result = 0 - try: - await exporter.serve() - except* Exception as excgroup: - print(f"Exception while serving on the exporter: {excgroup.exceptions}", file=sys.stderr) - for exc in excgroup.exceptions: - traceback.print_exception(type(exc), exc, exc.__traceback__, file=sys.stderr) - result = 1 - return result - - -@exporter.command -@arg_alias -@opt_config_path -async def run(alias, config_path): - """Run exporter""" - try: - if config_path: - config = ExporterConfigV1Alpha1.load_path(Path(config_path)) - else: - config = ExporterConfigV1Alpha1.load(alias) - except FileNotFoundError as err: - raise click.ClickException(f'exporter "{alias}" does not exist') from err - - return await _serve_with_exc_handling(config) - - -@exporter.command -@arg_alias -@opt_config_path -def shell(alias, config_path): - """Spawns a shell connecting to a transient exporter""" - try: - if config_path: - config = ExporterConfigV1Alpha1.load_path(Path(config_path)) - else: - config = ExporterConfigV1Alpha1.load(alias) - except FileNotFoundError as err: - raise click.ClickException(f'exporter "{alias}" does not exist') from err - - with config.serve_unix() as path: - # SAFETY: the exporter config is local thus considered trusted - launch_shell(path, allow=[], unsafe=True) - diff --git a/jumpstarter/cli/jmp.py b/jumpstarter/cli/jmp.py deleted file mode 100644 index 29021ddd7..000000000 --- a/jumpstarter/cli/jmp.py +++ /dev/null @@ -1,32 +0,0 @@ -import asyncclick as click - -from .client import client -from .create import create -from .delete import delete -from .exporter import exporter -from .get import get -from .import_res import import_res -from .install import install -from .lease import lease -from .shell import shell -from .util import AliasedGroup -from .version import version - - -@click.group(cls=AliasedGroup) -def jmp(): - """The Jumpstarter CLI""" - -jmp.add_command(client) -jmp.add_command(exporter) -jmp.add_command(lease) -jmp.add_command(shell) -jmp.add_command(get) -jmp.add_command(create) -jmp.add_command(delete) -jmp.add_command(install) -jmp.add_command(import_res) -jmp.add_command(version) - -if __name__ == "__main__": - jmp() diff --git a/pyproject.toml b/pyproject.toml index 5287a4f0a..6eae78956 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,10 +23,7 @@ dependencies = [ "wsproto>=1.2.0", "fabric>=3.2.2", "grpcio>=1.66.1", - "protobuf>=5.28.0", - "kubernetes>=31.0.0", - "kubernetes-asyncio>=31.1.0", - "asyncclick>=8.1.7.2", + "protobuf>=5.28.0" ] [dependency-groups] @@ -53,10 +50,6 @@ dev = [ "esbonio>=0.16.5", ] -[project.scripts] -jmp = "jumpstarter.cli.jmp:jmp" -j = "jumpstarter.cli.j:main" - [tool.hatch.version] source = "vcs" @@ -68,7 +61,7 @@ Homepage = "https://jumpstarter.dev" source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" [tool.uv.workspace] -members = ["contrib/drivers/*", "contrib/libs/*", "examples/*"] +members = ["contrib/drivers/*", "contrib/libs/*", "examples/*", "cli/*"] [tool.uv.sources] jumpstarter = { workspace = true } diff --git a/uv.lock b/uv.lock index fe50d9c33..7fc084a77 100644 --- a/uv.lock +++ b/uv.lock @@ -8,6 +8,10 @@ resolution-markers = [ [manifest] members = [ "jumpstarter", + "jumpstarter-admin-cli", + "jumpstarter-cli", + "jumpstarter-cli-common", + "jumpstarter-client-cli", "jumpstarter-driver-can", "jumpstarter-driver-dutlink", "jumpstarter-driver-http", @@ -17,6 +21,7 @@ members = [ "jumpstarter-driver-ustreamer", "jumpstarter-example-automotive", "jumpstarter-example-soc-pytest", + "jumpstarter-exporter-cli", "jumpstarter-imagehash", ] @@ -129,15 +134,16 @@ wheels = [ [[package]] name = "asyncclick" -version = "8.1.7.2" +version = "8.1.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "colorama", marker = "platform_system == 'Windows'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5e/bf/59d836c3433d7aa07f76c2b95c4eb763195ea8a5d7f9ad3311ed30c2af61/asyncclick-8.1.7.2.tar.gz", hash = "sha256:219ea0f29ccdc1bb4ff43bcab7ce0769ac6d48a04f997b43ec6bee99a222daa0", size = 349073 } +sdist = { url = "https://files.pythonhosted.org/packages/cb/b5/e1e5fdf1c1bb7e6e614987c120a98d9324bf8edfaa5f5cd16a6235c9d91b/asyncclick-8.1.8.tar.gz", hash = "sha256:0f0eb0f280e04919d67cf71b9fcdfb4db2d9ff7203669c40284485c149578e4c", size = 232900 } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/6e/9acdbb25733e1de411663b59abe521bec738e72fe4e85843f6ff8b212832/asyncclick-8.1.7.2-py3-none-any.whl", hash = "sha256:1ab940b04b22cb89b5b400725132b069d01b0c3472a9702c7a2c9d5d007ded02", size = 99191 }, + { url = "https://files.pythonhosted.org/packages/14/cc/a436f0fc2d04e57a0697e0f87a03b9eaed03ad043d2d5f887f8eebcec95f/asyncclick-8.1.8-py3-none-any.whl", hash = "sha256:eb1ccb44bc767f8f0695d592c7806fdf5bd575605b4ee246ffd5fadbcfdbd7c6", size = 99093 }, + { url = "https://files.pythonhosted.org/packages/92/c4/ae9e9d25522c6dc96ff167903880a0fe94d7bd31ed999198ee5017d977ed/asyncclick-8.1.8.0-py3-none-any.whl", hash = "sha256:be146a2d8075d4fe372ff4e877f23c8b5af269d16705c1948123b9415f6fd678", size = 99115 }, ] [[package]] @@ -572,16 +578,16 @@ wheels = [ [[package]] name = "google-auth" -version = "2.36.0" +version = "2.37.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cachetools" }, { name = "pyasn1-modules" }, { name = "rsa" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6a/71/4c5387d8a3e46e3526a8190ae396659484377a73b33030614dd3b28e7ded/google_auth-2.36.0.tar.gz", hash = "sha256:545e9618f2df0bcbb7dcbc45a546485b1212624716975a1ea5ae8149ce769ab1", size = 268336 } +sdist = { url = "https://files.pythonhosted.org/packages/46/af/b25763b9d35dfc2c6f9c3ec34d8d3f1ba760af3a7b7e8d5c5f0579522c45/google_auth-2.37.0.tar.gz", hash = "sha256:0054623abf1f9c83492c63d3f47e77f0a544caa3d40b2d98e099a611c2dd5d00", size = 268878 } wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/9a/3d5087d27865c2f0431b942b5c4500b7d1b744dd3262fdc973a4c39d099e/google_auth-2.36.0-py2.py3-none-any.whl", hash = "sha256:51a15d47028b66fd36e5c64a82d2d57480075bccc7da37cde257fc94177a61fb", size = 209519 }, + { url = "https://files.pythonhosted.org/packages/8d/8d/4d5d5f9f500499f7bd4c93903b43e8d6976f3fc6f064637ded1a85d09b07/google_auth-2.37.0-py2.py3-none-any.whl", hash = "sha256:42664f18290a6be591be5329a96fe30184be1a1badb7292a7f686a9659de9ca0", size = 209829 }, ] [[package]] @@ -734,17 +740,14 @@ wheels = [ [[package]] name = "jumpstarter" -version = "0.5.1.dev83+gc751a6a.d20250109" +version = "0.5.1.dev93+gb7ef843.d20250115" source = { editable = "." } dependencies = [ { name = "aiohttp" }, { name = "anyio" }, - { name = "asyncclick" }, { name = "fabric" }, { name = "grpcio" }, { name = "httpx" }, - { name = "kubernetes" }, - { name = "kubernetes-asyncio" }, { name = "opendal" }, { name = "pexpect" }, { name = "protobuf" }, @@ -783,12 +786,9 @@ docs = [ requires-dist = [ { name = "aiohttp", specifier = ">=3.10.5" }, { name = "anyio", specifier = ">=4.4.0,!=4.6.2" }, - { name = "asyncclick", specifier = ">=8.1.7.2" }, { name = "fabric", specifier = ">=3.2.2" }, { name = "grpcio", specifier = ">=1.66.1" }, { name = "httpx", specifier = ">=0.27.0" }, - { name = "kubernetes", specifier = ">=31.0.0" }, - { name = "kubernetes-asyncio", specifier = ">=31.1.0" }, { name = "opendal", specifier = ">=0.45.8" }, { name = "pexpect", specifier = ">=4.9.0" }, { name = "protobuf", specifier = ">=5.28.0" }, @@ -823,6 +823,144 @@ docs = [ { name = "sphinxcontrib-mermaid", specifier = ">=0.9.2" }, ] +[[package]] +name = "jumpstarter-admin-cli" +version = "0.5.1.dev93+gb7ef843.d20250115" +source = { editable = "cli/admin" } +dependencies = [ + { name = "asyncclick" }, + { name = "jumpstarter" }, + { name = "jumpstarter-cli-common" }, + { name = "kubernetes" }, + { name = "kubernetes-asyncio" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-anyio" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "asyncclick", specifier = ">=8.1.7.2" }, + { name = "jumpstarter", editable = "." }, + { name = "jumpstarter-cli-common", editable = "cli/common" }, + { name = "kubernetes", specifier = ">=31.0.0" }, + { name = "kubernetes-asyncio", specifier = ">=31.1.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-anyio", specifier = ">=0.0.0" }, + { name = "pytest-asyncio", specifier = ">=0.0.0" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + +[[package]] +name = "jumpstarter-cli" +version = "0.5.1.dev93+gb7ef843.d20250115" +source = { editable = "cli/jmp" } +dependencies = [ + { name = "jumpstarter" }, + { name = "jumpstarter-admin-cli" }, + { name = "jumpstarter-cli-common" }, + { name = "jumpstarter-client-cli" }, + { name = "jumpstarter-exporter-cli" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-anyio" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "jumpstarter", editable = "." }, + { name = "jumpstarter-admin-cli", editable = "cli/admin" }, + { name = "jumpstarter-cli-common", editable = "cli/common" }, + { name = "jumpstarter-client-cli", editable = "cli/client" }, + { name = "jumpstarter-exporter-cli", editable = "cli/exporter" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-anyio", specifier = ">=0.0.0" }, + { name = "pytest-asyncio", specifier = ">=0.0.0" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + +[[package]] +name = "jumpstarter-cli-common" +version = "0.5.1.dev93+gb7ef843.d20250115" +source = { editable = "cli/common" } +dependencies = [ + { name = "asyncclick" }, + { name = "jumpstarter" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-anyio" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "asyncclick", specifier = ">=8.1.7.2" }, + { name = "jumpstarter", editable = "." }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-anyio", specifier = ">=0.0.0" }, + { name = "pytest-asyncio", specifier = ">=0.0.0" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + +[[package]] +name = "jumpstarter-client-cli" +version = "0.5.1.dev93+gb7ef843.d20250115" +source = { editable = "cli/client" } +dependencies = [ + { name = "asyncclick" }, + { name = "jumpstarter" }, + { name = "jumpstarter-cli-common" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-anyio" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "asyncclick", specifier = ">=8.1.7.2" }, + { name = "jumpstarter", editable = "." }, + { name = "jumpstarter-cli-common", editable = "cli/common" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-anyio", specifier = ">=0.0.0" }, + { name = "pytest-asyncio", specifier = ">=0.0.0" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + [[package]] name = "jumpstarter-driver-can" version = "0.5.1.dev16+gc1f555c.d20241209" @@ -1056,6 +1194,39 @@ requires-dist = [ { name = "pytest", specifier = ">=8.3.2" }, ] +[[package]] +name = "jumpstarter-exporter-cli" +version = "0.5.1.dev93+gb7ef843.d20250115" +source = { editable = "cli/exporter" } +dependencies = [ + { name = "asyncclick" }, + { name = "jumpstarter" }, + { name = "jumpstarter-cli-common" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-anyio" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "asyncclick", specifier = ">=8.1.7.2" }, + { name = "jumpstarter", editable = "." }, + { name = "jumpstarter-cli-common", editable = "cli/common" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-anyio", specifier = ">=0.0.0" }, + { name = "pytest-asyncio", specifier = ">=0.0.0" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + [[package]] name = "jumpstarter-imagehash" version = "0.5.1.dev16+gc1f555c.d20241209" @@ -1107,7 +1278,7 @@ wheels = [ [[package]] name = "kubernetes-asyncio" -version = "31.1.0" +version = "32.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -1117,9 +1288,9 @@ dependencies = [ { name = "six" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0a/dc/4ca52809f3b662df8c5e6058b0beb489d8d6426d5c189c28ec5a3168fdd4/kubernetes_asyncio-31.1.0.tar.gz", hash = "sha256:00128a96eb0284de0cbee53bd2fe044593f2e1547c48d09901cddf9258adfd88", size = 962239 } +sdist = { url = "https://files.pythonhosted.org/packages/c5/5f/b90d537f7f7f05bd2038a3084f63148748b176d93e20abdef987d0025f16/kubernetes_asyncio-32.0.0.tar.gz", hash = "sha256:77f28a026aff8a40fd34a7ebad9f3813dcb7e549c7240275fc4bfbff0a6b49d0", size = 1025641 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a8/2a/93b7a49598d660e259d0db8dd92b97e99910d5e7a349a8995797dd49be9d/kubernetes_asyncio-31.1.0-py3-none-any.whl", hash = "sha256:76898fea5dee601b209fefeae4ecee2fb20bfe3ebf872b5ff37c96230fbda6cc", size = 1902366 }, + { url = "https://files.pythonhosted.org/packages/d6/d0/046ab1a8edad497d134432565fc7710fc3134eeb2f08ec147a08d1509f06/kubernetes_asyncio-32.0.0-py3-none-any.whl", hash = "sha256:f9baa8f73c182948e063bb9448d8e614f73df4aae52d28f173a3a1c2b77fbfb4", size = 1972671 }, ] [[package]] @@ -1929,11 +2100,11 @@ wheels = [ [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } wheels = [ - { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 }, + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, ] [[package]] From af267a81cb3deb14d255e2340489e74cb50a3134 Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Tue, 21 Jan 2025 17:23:58 -0500 Subject: [PATCH 02/16] Re-organize all modules into packages and fix tests --- .gitignore | 3 + contrib/README.md => CONTRIB.md | 0 Makefile | 17 +- .../create_driver.sh | 5 +- .../driver/.gitignore.tmpl | 0 .../driver/README.md.tmpl | 0 .../driver/examples/exporter.yaml.tmpl | 0 .../jumpstarter_driver/__init__.py.tmpl | 0 .../driver/jumpstarter_driver/client.py.tmpl | 0 .../driver/jumpstarter_driver/driver.py.tmpl | 0 .../jumpstarter_driver/driver_test.py.tmpl | 0 .../driver/pyproject.toml.tmpl | 2 +- buf.gen.yaml | 4 +- cli/jmp/pyproject.toml | 51 - contrib/drivers/http/.gitignore | 3 - contrib/drivers/http/.python-version | 1 - contrib/drivers/http/uv.lock | 927 ------------------ contrib/drivers/tftp/.gitignore | 3 - contrib/drivers/tftp/.python-version | 1 - contrib/drivers/tftp/uv.lock | 921 ----------------- examples/soc-pytest/pyproject.toml | 4 - jumpstarter/client/adapters/__init__.py | 8 - packages/jumpstarter/README.md | 1 + .../jumpstarter/conftest.py | 10 +- .../jumpstarter}/client/__init__.py | 0 .../jumpstarter/client/adapters.py | 0 .../jumpstarter/jumpstarter}/client/base.py | 3 +- .../jumpstarter/jumpstarter}/client/client.py | 7 +- .../jumpstarter/jumpstarter}/client/core.py | 3 +- .../jumpstarter/jumpstarter}/client/lease.py | 3 +- .../jumpstarter}/common/__init__.py | 0 .../jumpstarter}/common/condition.py | 2 +- .../jumpstarter/jumpstarter}/common/grpc.py | 0 .../jumpstarter}/common/importlib.py | 0 .../jumpstarter}/common/importlib_test.py | 0 .../jumpstarter}/common/metadata.py | 0 .../jumpstarter}/common/resources.py | 0 .../jumpstarter/jumpstarter}/common/serde.py | 0 .../jumpstarter}/common/streams.py | 5 +- .../jumpstarter}/common/tempfile.py | 0 .../jumpstarter/jumpstarter}/common/utils.py | 0 .../jumpstarter}/config/__init__.py | 0 .../jumpstarter/jumpstarter}/config/client.py | 5 +- .../jumpstarter/jumpstarter}/config/common.py | 0 .../jumpstarter/jumpstarter}/config/env.py | 0 .../jumpstarter}/config/exporter.py | 5 +- .../jumpstarter}/config/exporter_test.py | 15 +- .../jumpstarter/jumpstarter}/config/tls.py | 0 .../jumpstarter/jumpstarter}/config/user.py | 0 .../jumpstarter}/driver/__init__.py | 0 .../jumpstarter/jumpstarter}/driver/base.py | 7 +- .../jumpstarter}/driver/decorators.py | 0 .../jumpstarter}/driver/decorators_test.py | 0 .../jumpstarter}/exporter/__init__.py | 0 .../jumpstarter}/exporter/exporter.py | 3 +- .../jumpstarter}/exporter/session.py | 3 +- .../jumpstarter}/streams/__init__.py | 2 - .../jumpstarter}/streams/aiohttp.py | 0 .../jumpstarter}/streams/blocking.py | 0 .../jumpstarter}/streams/common.py | 0 .../jumpstarter}/streams/metadata.py | 0 .../jumpstarter}/streams/progress.py | 0 .../jumpstarter}/streams/router.py | 3 +- .../jumpstarter}/pyproject.toml | 33 +- .../jumpstarter_cli}/README.md | 0 .../jumpstarter_cli/__init__.py | 6 +- .../jumpstarter_cli/__main__.py | 0 .../jumpstarter_cli/cli_test.py | 18 + packages/jumpstarter_cli/pyproject.toml | 43 + .../jumpstarter_cli_admin}/README.md | 0 .../jumpstarter_cli_admin}/__init__.py | 2 +- .../jumpstarter_cli_admin}/create.py | 10 +- .../jumpstarter_cli_admin}/create_test.py | 5 +- .../jumpstarter_cli_admin}/delete.py | 10 +- .../jumpstarter_cli_admin}/delete_test.py | 5 +- .../jumpstarter_cli_admin}/get.py | 14 +- .../jumpstarter_cli_admin}/get_test.py | 2 +- .../jumpstarter_cli_admin}/import_res.py | 20 +- .../jumpstarter_cli_admin}/import_res_test.py | 2 +- .../jumpstarter_cli_admin}/install.py | 3 +- .../jumpstarter_cli_admin}/k8s.py | 0 .../jumpstarter_cli_admin}/pyproject.toml | 15 +- .../jumpstarter_cli_client}/README.md | 0 .../jumpstarter_cli_client}/__init__.py | 3 +- .../jumpstarter_cli_client}/client_config.py | 3 +- .../jumpstarter_cli_client}/client_shell.py | 1 - .../jumpstarter_cli_client}/client_test.py | 21 +- .../jumpstarter_cli_client}/j.py | 0 .../jumpstarter_cli_client}/lease.py | 3 +- .../jumpstarter_cli_client}/pyproject.toml | 12 +- .../jumpstarter_cli_common}/README.md | 0 .../jumpstarter_cli_common/__init__.py | 3 - .../jumpstarter_cli_common/alias.py | 0 .../jumpstarter_cli_common/opt.py | 0 .../jumpstarter_cli_common/table.py | 0 .../jumpstarter_cli_common/table_test.py | 9 + .../jumpstarter_cli_common/time.py | 0 .../jumpstarter_cli_common/version.py | 0 .../jumpstarter_cli_common/pyproject.toml | 37 + .../jumpstarter_cli_exporter}/README.md | 0 .../jumpstarter_cli_exporter}/__init__.py | 0 .../jumpstarter_cli_exporter}/exporter.py | 1 - .../exporter_config.py | 3 +- .../exporter_test.py | 21 +- .../jumpstarter_cli_exporter}/pyproject.toml | 10 +- .../jumpstarter_driver_can}/README.md | 0 .../jumpstarter_driver_can/__init__.py | 0 .../jumpstarter_driver_can/client.py | 0 .../jumpstarter_driver_can/client_test.py | 0 .../jumpstarter_driver_can/common.py | 0 .../jumpstarter_driver_can/driver.py | 0 .../jumpstarter_driver_can}/pyproject.toml | 3 +- .../jumpstarter_driver_composite/README.md | 1 + .../jumpstarter_driver_composite}/__init__.py | 0 .../jumpstarter_driver_composite}/client.py | 1 - .../jumpstarter_driver_composite}/driver.py | 5 +- .../driver_test.py | 5 +- .../pyproject.toml | 9 +- .../jumpstarter_driver_dutlink}/README.md | 0 .../examples/dutlink.py | 3 +- .../examples/exporter.yaml | 0 .../jumpstarter_driver_dutlink}/__init__.py | 0 .../jumpstarter_driver_dutlink/driver.py | 11 +- .../jumpstarter_driver_dutlink/driver_test.py | 4 +- .../jumpstarter_driver_dutlink/pyproject.toml | 41 + .../jumpstarter_driver_http}/README.md | 0 .../jumpstarter_driver_http}/__init__.py | 0 .../jumpstarter_driver_http/client.py | 5 +- .../jumpstarter_driver_http/driver.py | 1 - .../jumpstarter_driver_http/driver_test.py | 1 - .../jumpstarter_driver_http}/pyproject.toml | 3 +- packages/jumpstarter_driver_network/README.md | 1 + .../jumpstarter_driver_network}/__init__.py | 0 .../adapters/__init__.py | 6 + .../adapters/fabric.py | 0 .../adapters/fabric_test.py | 6 +- .../adapters/novnc.py | 3 +- .../adapters/novnc_test.py | 8 +- .../adapters/pexpect.py | 0 .../adapters/portforward.py | 3 +- .../jumpstarter_driver_network}/client.py | 0 .../jumpstarter_driver_network}/driver.py | 3 +- .../driver_test.py | 6 +- .../streams/__init__.py | 3 + .../streams/websocket.py | 3 +- .../jumpstarter_driver_network/pyproject.toml | 36 + packages/jumpstarter_driver_opendal/README.md | 1 + .../jumpstarter_driver_opendal}/__init__.py | 0 .../jumpstarter_driver_opendal/adapter.py | 6 +- .../jumpstarter_driver_opendal}/client.py | 4 +- .../jumpstarter_driver_opendal}/driver.py | 3 +- .../driver_test.py | 4 +- .../jumpstarter_driver_opendal/pyproject.toml | 34 + packages/jumpstarter_driver_power/README.md | 1 + .../jumpstarter_driver_power}/__init__.py | 0 .../jumpstarter_driver_power}/client.py | 1 - .../jumpstarter_driver_power}/client_test.py | 5 +- .../jumpstarter_driver_power}/common.py | 0 .../jumpstarter_driver_power}/driver.py | 6 +- .../jumpstarter_driver_power}/driver_test.py | 4 +- .../jumpstarter_driver_power/pyproject.toml | 35 + .../jumpstarter_driver_pyserial/README.md | 1 + .../jumpstarter_driver_pyserial}/__init__.py | 0 .../jumpstarter_driver_pyserial}/client.py | 6 +- .../jumpstarter_driver_pyserial}/console.py | 0 .../jumpstarter_driver_pyserial}/driver.py | 5 +- .../driver_test.py | 5 +- .../pyproject.toml | 35 + .../jumpstarter_driver_raspberrypi}/README.md | 0 .../__init__.py | 0 .../jumpstarter_driver_raspberrypi/client.py | 0 .../jumpstarter_driver_raspberrypi/driver.py | 0 .../driver_test.py | 0 .../pyproject.toml | 2 +- .../jumpstarter_driver_sdwire}/README.md | 0 .../jumpstarter_driver_sdwire}/__init__.py | 0 .../jumpstarter_driver_sdwire/driver.py | 3 +- .../jumpstarter_driver_sdwire/driver_test.py | 2 +- .../jumpstarter_driver_sdwire}/pyproject.toml | 3 +- .../jumpstarter_driver_tftp}/README.md | 0 .../examples/exporter.yaml | 2 +- .../examples/tftp_test.py | 15 +- .../jumpstarter_driver_tftp}/__init__.py | 0 .../jumpstarter_driver_tftp/client.py | 5 +- .../jumpstarter_driver_tftp/driver.py | 2 +- .../jumpstarter_driver_tftp/driver_test.py | 2 +- .../jumpstarter_driver_tftp/server.py | 0 .../jumpstarter_driver_tftp/server_test.py | 16 +- .../jumpstarter_driver_tftp}/pyproject.toml | 35 +- .../jumpstarter_driver_tftp}/test.txt | 0 .../jumpstarter_driver_ustreamer}/README.md | 0 .../jumpstarter_driver_ustreamer}/__init__.py | 0 .../jumpstarter_driver_ustreamer/client.py | 0 .../jumpstarter_driver_ustreamer/common.py | 0 .../jumpstarter_driver_ustreamer/driver.py | 0 .../driver_test.py | 0 .../pyproject.toml | 2 +- .../jumpstarter_imagehash}/README.md | 0 .../jumpstarter_imagehash/__init__.py | 0 .../jumpstarter_imagehash/imagehash.py | 0 .../jumpstarter_imagehash/imagehash_test.py | 0 .../jumpstarter_imagehash/test_image_a.jpeg | Bin .../jumpstarter_imagehash/test_image_b.jpeg | Bin .../jumpstarter_imagehash}/pyproject.toml | 2 +- packages/jumpstarter_kubernetes/README.md | 1 + .../jumpstarter_kubernetes}/__init__.py | 2 +- .../jumpstarter_kubernetes}/clients.py | 3 +- .../jumpstarter_kubernetes}/exporters.py | 3 +- .../jumpstarter_kubernetes}/install.py | 0 .../jumpstarter_kubernetes}/leases.py | 0 .../jumpstarter_kubernetes}/util/__init__.py | 0 .../util/async_custom_object_api.py | 0 .../jumpstarter_kubernetes/pyproject.toml | 35 + .../jumpstarter_protocol/README.md | 0 .../jumpstarter_protocol/__init__.py | 17 + .../jumpstarter}/v1/jumpstarter_pb2.py | 8 +- .../jumpstarter}/v1/jumpstarter_pb2_grpc.py | 2 +- .../jumpstarter}/v1/kubernetes_pb2.py | 6 +- .../jumpstarter}/v1/kubernetes_pb2_grpc.py | 0 .../jumpstarter}/v1/router_pb2.py | 6 +- .../jumpstarter}/v1/router_pb2_grpc.py | 2 +- packages/jumpstarter_protocol/pyproject.toml | 37 + packages/jumpstarter_testing/README.md | 0 packages/jumpstarter_testing/conftest.py | 7 + .../jumpstarter_testing/__init__.py | 3 + .../jumpstarter_testing}/pytest.py | 3 +- .../jumpstarter_testing}/pytest_test.py | 7 +- packages/jumpstarter_testing/pyproject.toml | 30 + pyproject.toml | 79 +- tests/test_client_config.py | 3 +- tests/test_listener.py | 3 +- uv.lock | 573 +++++++---- 232 files changed, 1143 insertions(+), 2447 deletions(-) rename contrib/README.md => CONTRIB.md (100%) rename {contrib/__templates__ => __templates__}/create_driver.sh (88%) rename {contrib/__templates__ => __templates__}/driver/.gitignore.tmpl (100%) rename {contrib/__templates__ => __templates__}/driver/README.md.tmpl (100%) rename {contrib/__templates__ => __templates__}/driver/examples/exporter.yaml.tmpl (100%) rename {contrib/__templates__ => __templates__}/driver/jumpstarter_driver/__init__.py.tmpl (100%) rename {contrib/__templates__ => __templates__}/driver/jumpstarter_driver/client.py.tmpl (100%) rename {contrib/__templates__ => __templates__}/driver/jumpstarter_driver/driver.py.tmpl (100%) rename {contrib/__templates__ => __templates__}/driver/jumpstarter_driver/driver_test.py.tmpl (100%) rename {contrib/__templates__ => __templates__}/driver/pyproject.toml.tmpl (95%) delete mode 100644 cli/jmp/pyproject.toml delete mode 100644 contrib/drivers/http/.gitignore delete mode 100644 contrib/drivers/http/.python-version delete mode 100644 contrib/drivers/http/uv.lock delete mode 100644 contrib/drivers/tftp/.gitignore delete mode 100644 contrib/drivers/tftp/.python-version delete mode 100644 contrib/drivers/tftp/uv.lock delete mode 100644 jumpstarter/client/adapters/__init__.py create mode 100644 packages/jumpstarter/README.md rename conftest.py => packages/jumpstarter/conftest.py (96%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/client/__init__.py (100%) rename jumpstarter/client/adapters/common.py => packages/jumpstarter/jumpstarter/client/adapters.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/client/base.py (99%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/client/client.py (96%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/client/core.py (97%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/client/lease.py (98%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/common/__init__.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/common/condition.py (94%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/common/grpc.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/common/importlib.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/common/importlib_test.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/common/metadata.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/common/resources.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/common/serde.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/common/streams.py (95%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/common/tempfile.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/common/utils.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/config/__init__.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/config/client.py (99%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/config/common.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/config/env.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/config/exporter.py (98%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/config/exporter_test.py (90%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/config/tls.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/config/user.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/driver/__init__.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/driver/base.py (98%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/driver/decorators.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/driver/decorators_test.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/exporter/__init__.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/exporter/exporter.py (99%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/exporter/session.py (99%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/streams/__init__.py (86%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/streams/aiohttp.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/streams/blocking.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/streams/common.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/streams/metadata.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/streams/progress.py (100%) rename {jumpstarter => packages/jumpstarter/jumpstarter}/streams/router.py (98%) rename {cli/admin => packages/jumpstarter}/pyproject.toml (54%) rename {cli/jmp => packages/jumpstarter_cli}/README.md (100%) rename {cli/jmp => packages/jumpstarter_cli}/jumpstarter_cli/__init__.py (69%) rename {cli/jmp => packages/jumpstarter_cli}/jumpstarter_cli/__main__.py (100%) create mode 100644 packages/jumpstarter_cli/jumpstarter_cli/cli_test.py create mode 100644 packages/jumpstarter_cli/pyproject.toml rename {cli/admin => packages/jumpstarter_cli_admin}/README.md (100%) rename {cli/admin/jumpstarter_admin_cli => packages/jumpstarter_cli_admin/jumpstarter_cli_admin}/__init__.py (100%) rename {cli/admin/jumpstarter_admin_cli => packages/jumpstarter_cli_admin/jumpstarter_cli_admin}/create.py (98%) rename {cli/admin/jumpstarter_admin_cli => packages/jumpstarter_cli_admin/jumpstarter_cli_admin}/create_test.py (99%) rename {cli/admin/jumpstarter_admin_cli => packages/jumpstarter_cli_admin/jumpstarter_cli_admin}/delete.py (97%) rename {cli/admin/jumpstarter_admin_cli => packages/jumpstarter_cli_admin/jumpstarter_cli_admin}/delete_test.py (99%) rename {cli/admin/jumpstarter_admin_cli => packages/jumpstarter_cli_admin/jumpstarter_cli_admin}/get.py (99%) rename {cli/admin/jumpstarter_admin_cli => packages/jumpstarter_cli_admin/jumpstarter_cli_admin}/get_test.py (99%) rename {cli/admin/jumpstarter_admin_cli => packages/jumpstarter_cli_admin/jumpstarter_cli_admin}/import_res.py (95%) rename {cli/admin/jumpstarter_admin_cli => packages/jumpstarter_cli_admin/jumpstarter_cli_admin}/import_res_test.py (99%) rename {cli/admin/jumpstarter_admin_cli => packages/jumpstarter_cli_admin/jumpstarter_cli_admin}/install.py (97%) rename {cli/common/jumpstarter_cli_common => packages/jumpstarter_cli_admin/jumpstarter_cli_admin}/k8s.py (100%) rename {cli/client => packages/jumpstarter_cli_admin}/pyproject.toml (66%) rename {cli/client => packages/jumpstarter_cli_client}/README.md (100%) rename {cli/client/jumpstarter_client_cli => packages/jumpstarter_cli_client/jumpstarter_cli_client}/__init__.py (99%) rename {cli/client/jumpstarter_client_cli => packages/jumpstarter_cli_client/jumpstarter_cli_client}/client_config.py (99%) rename {cli/client/jumpstarter_client_cli => packages/jumpstarter_cli_client/jumpstarter_cli_client}/client_shell.py (99%) rename {cli/client/jumpstarter_client_cli => packages/jumpstarter_cli_client/jumpstarter_cli_client}/client_test.py (71%) rename {cli/client/jumpstarter_client_cli => packages/jumpstarter_cli_client/jumpstarter_cli_client}/j.py (100%) rename {cli/client/jumpstarter_client_cli => packages/jumpstarter_cli_client/jumpstarter_cli_client}/lease.py (99%) rename {cli/exporter => packages/jumpstarter_cli_client}/pyproject.toml (79%) rename {cli/common => packages/jumpstarter_cli_common}/README.md (100%) rename {cli/common => packages/jumpstarter_cli_common}/jumpstarter_cli_common/__init__.py (74%) rename {cli/common => packages/jumpstarter_cli_common}/jumpstarter_cli_common/alias.py (100%) rename {cli/common => packages/jumpstarter_cli_common}/jumpstarter_cli_common/opt.py (100%) rename {cli/common => packages/jumpstarter_cli_common}/jumpstarter_cli_common/table.py (100%) create mode 100644 packages/jumpstarter_cli_common/jumpstarter_cli_common/table_test.py rename {cli/common => packages/jumpstarter_cli_common}/jumpstarter_cli_common/time.py (100%) rename {cli/common => packages/jumpstarter_cli_common}/jumpstarter_cli_common/version.py (100%) create mode 100644 packages/jumpstarter_cli_common/pyproject.toml rename {cli/exporter => packages/jumpstarter_cli_exporter}/README.md (100%) rename {cli/exporter/jumpstarter_exporter_cli => packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter}/__init__.py (100%) rename {cli/exporter/jumpstarter_exporter_cli => packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter}/exporter.py (99%) rename {cli/exporter/jumpstarter_exporter_cli => packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter}/exporter_config.py (99%) rename {cli/exporter/jumpstarter_exporter_cli => packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter}/exporter_test.py (60%) rename {cli/common => packages/jumpstarter_cli_exporter}/pyproject.toml (83%) rename {contrib/drivers/can => packages/jumpstarter_driver_can}/README.md (100%) rename {contrib/drivers/can => packages/jumpstarter_driver_can}/jumpstarter_driver_can/__init__.py (100%) rename {contrib/drivers/can => packages/jumpstarter_driver_can}/jumpstarter_driver_can/client.py (100%) rename {contrib/drivers/can => packages/jumpstarter_driver_can}/jumpstarter_driver_can/client_test.py (100%) rename {contrib/drivers/can => packages/jumpstarter_driver_can}/jumpstarter_driver_can/common.py (100%) rename {contrib/drivers/can => packages/jumpstarter_driver_can}/jumpstarter_driver_can/driver.py (100%) rename {contrib/drivers/can => packages/jumpstarter_driver_can}/pyproject.toml (95%) create mode 100644 packages/jumpstarter_driver_composite/README.md rename {contrib/drivers/dutlink/jumpstarter_driver_dutlink => packages/jumpstarter_driver_composite/jumpstarter_driver_composite}/__init__.py (100%) rename {jumpstarter/drivers/composite => packages/jumpstarter_driver_composite/jumpstarter_driver_composite}/client.py (99%) rename {jumpstarter/drivers/composite => packages/jumpstarter_driver_composite/jumpstarter_driver_composite}/driver.py (76%) rename {jumpstarter/drivers/composite => packages/jumpstarter_driver_composite/jumpstarter_driver_composite}/driver_test.py (80%) rename {contrib/drivers/dutlink => packages/jumpstarter_driver_composite}/pyproject.toml (79%) rename {contrib/drivers/dutlink => packages/jumpstarter_driver_dutlink}/README.md (100%) rename {contrib/drivers/dutlink => packages/jumpstarter_driver_dutlink}/examples/dutlink.py (96%) rename {contrib/drivers/dutlink => packages/jumpstarter_driver_dutlink}/examples/exporter.yaml (100%) rename {contrib/drivers/http/src/jumpstarter_driver_http => packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink}/__init__.py (100%) rename {contrib/drivers/dutlink => packages/jumpstarter_driver_dutlink}/jumpstarter_driver_dutlink/driver.py (97%) rename {contrib/drivers/dutlink => packages/jumpstarter_driver_dutlink}/jumpstarter_driver_dutlink/driver_test.py (94%) create mode 100644 packages/jumpstarter_driver_dutlink/pyproject.toml rename {contrib/drivers/http => packages/jumpstarter_driver_http}/README.md (100%) rename {contrib/drivers/raspberrypi/jumpstarter_driver_raspberrypi => packages/jumpstarter_driver_http/jumpstarter_driver_http}/__init__.py (100%) rename {contrib/drivers/http/src => packages/jumpstarter_driver_http}/jumpstarter_driver_http/client.py (97%) rename {contrib/drivers/http/src => packages/jumpstarter_driver_http}/jumpstarter_driver_http/driver.py (99%) rename {contrib/drivers/http/src => packages/jumpstarter_driver_http}/jumpstarter_driver_http/driver_test.py (99%) rename {contrib/drivers/http => packages/jumpstarter_driver_http}/pyproject.toml (92%) create mode 100644 packages/jumpstarter_driver_network/README.md rename {contrib/drivers/sdwire/jumpstarter_driver_sdwire => packages/jumpstarter_driver_network/jumpstarter_driver_network}/__init__.py (100%) create mode 100644 packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/__init__.py rename {jumpstarter/client => packages/jumpstarter_driver_network/jumpstarter_driver_network}/adapters/fabric.py (100%) rename {jumpstarter/client => packages/jumpstarter_driver_network/jumpstarter_driver_network}/adapters/fabric_test.py (92%) rename {jumpstarter/client => packages/jumpstarter_driver_network/jumpstarter_driver_network}/adapters/novnc.py (90%) rename {jumpstarter/client => packages/jumpstarter_driver_network/jumpstarter_driver_network}/adapters/novnc_test.py (90%) rename {jumpstarter/client => packages/jumpstarter_driver_network/jumpstarter_driver_network}/adapters/pexpect.py (100%) rename {jumpstarter/client => packages/jumpstarter_driver_network/jumpstarter_driver_network}/adapters/portforward.py (94%) rename {jumpstarter/drivers/network => packages/jumpstarter_driver_network/jumpstarter_driver_network}/client.py (100%) rename {jumpstarter/drivers/network => packages/jumpstarter_driver_network/jumpstarter_driver_network}/driver.py (96%) rename {jumpstarter/drivers/network => packages/jumpstarter_driver_network/jumpstarter_driver_network}/driver_test.py (95%) create mode 100644 packages/jumpstarter_driver_network/jumpstarter_driver_network/streams/__init__.py rename {jumpstarter => packages/jumpstarter_driver_network/jumpstarter_driver_network}/streams/websocket.py (95%) create mode 100644 packages/jumpstarter_driver_network/pyproject.toml create mode 100644 packages/jumpstarter_driver_opendal/README.md rename {contrib/drivers/tftp/src/jumpstarter_driver_tftp => packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal}/__init__.py (100%) rename jumpstarter/client/adapters/opendal.py => packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py (97%) rename {jumpstarter/drivers/storage => packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal}/client.py (97%) rename {jumpstarter/drivers/storage => packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal}/driver.py (95%) rename {jumpstarter/drivers/storage => packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal}/driver_test.py (97%) create mode 100644 packages/jumpstarter_driver_opendal/pyproject.toml create mode 100644 packages/jumpstarter_driver_power/README.md rename {contrib/drivers/ustreamer/jumpstarter_driver_ustreamer => packages/jumpstarter_driver_power/jumpstarter_driver_power}/__init__.py (100%) rename {jumpstarter/drivers/power => packages/jumpstarter_driver_power/jumpstarter_driver_power}/client.py (99%) rename {jumpstarter/drivers/power => packages/jumpstarter_driver_power/jumpstarter_driver_power}/client_test.py (83%) rename {jumpstarter/drivers/power => packages/jumpstarter_driver_power/jumpstarter_driver_power}/common.py (100%) rename {jumpstarter/drivers/power => packages/jumpstarter_driver_power/jumpstarter_driver_power}/driver.py (86%) rename {jumpstarter/drivers/power => packages/jumpstarter_driver_power/jumpstarter_driver_power}/driver_test.py (82%) create mode 100644 packages/jumpstarter_driver_power/pyproject.toml create mode 100644 packages/jumpstarter_driver_pyserial/README.md rename {jumpstarter/drivers/composite => packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial}/__init__.py (100%) rename {jumpstarter/drivers/pyserial => packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial}/client.py (95%) rename {jumpstarter/drivers/pyserial => packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial}/console.py (100%) rename {jumpstarter/drivers/pyserial => packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial}/driver.py (95%) rename {jumpstarter/drivers/pyserial => packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial}/driver_test.py (92%) create mode 100644 packages/jumpstarter_driver_pyserial/pyproject.toml rename {contrib/drivers/raspberrypi => packages/jumpstarter_driver_raspberrypi}/README.md (100%) rename {jumpstarter/drivers/network => packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi}/__init__.py (100%) rename {contrib/drivers/raspberrypi => packages/jumpstarter_driver_raspberrypi}/jumpstarter_driver_raspberrypi/client.py (100%) rename {contrib/drivers/raspberrypi => packages/jumpstarter_driver_raspberrypi}/jumpstarter_driver_raspberrypi/driver.py (100%) rename {contrib/drivers/raspberrypi => packages/jumpstarter_driver_raspberrypi}/jumpstarter_driver_raspberrypi/driver_test.py (100%) rename {contrib/drivers/raspberrypi => packages/jumpstarter_driver_raspberrypi}/pyproject.toml (95%) rename {contrib/drivers/sdwire => packages/jumpstarter_driver_sdwire}/README.md (100%) rename {jumpstarter/drivers/power => packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire}/__init__.py (100%) rename {contrib/drivers/sdwire => packages/jumpstarter_driver_sdwire}/jumpstarter_driver_sdwire/driver.py (98%) rename {contrib/drivers/sdwire => packages/jumpstarter_driver_sdwire}/jumpstarter_driver_sdwire/driver_test.py (100%) rename {contrib/drivers/sdwire => packages/jumpstarter_driver_sdwire}/pyproject.toml (90%) rename {contrib/drivers/tftp => packages/jumpstarter_driver_tftp}/README.md (100%) rename {contrib/drivers/tftp => packages/jumpstarter_driver_tftp}/examples/exporter.yaml (86%) rename {contrib/drivers/tftp => packages/jumpstarter_driver_tftp}/examples/tftp_test.py (83%) rename {jumpstarter/drivers/pyserial => packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp}/__init__.py (100%) rename {contrib/drivers/tftp/src => packages/jumpstarter_driver_tftp}/jumpstarter_driver_tftp/client.py (98%) rename {contrib/drivers/tftp/src => packages/jumpstarter_driver_tftp}/jumpstarter_driver_tftp/driver.py (100%) rename {contrib/drivers/tftp/src => packages/jumpstarter_driver_tftp}/jumpstarter_driver_tftp/driver_test.py (100%) rename {contrib/drivers/tftp/src => packages/jumpstarter_driver_tftp}/jumpstarter_driver_tftp/server.py (100%) rename {contrib/drivers/tftp/src => packages/jumpstarter_driver_tftp}/jumpstarter_driver_tftp/server_test.py (96%) rename {contrib/drivers/tftp => packages/jumpstarter_driver_tftp}/pyproject.toml (62%) rename {contrib/drivers/tftp => packages/jumpstarter_driver_tftp}/test.txt (100%) rename {contrib/drivers/ustreamer => packages/jumpstarter_driver_ustreamer}/README.md (100%) rename {jumpstarter/drivers/storage => packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer}/__init__.py (100%) rename {contrib/drivers/ustreamer => packages/jumpstarter_driver_ustreamer}/jumpstarter_driver_ustreamer/client.py (100%) rename {contrib/drivers/ustreamer => packages/jumpstarter_driver_ustreamer}/jumpstarter_driver_ustreamer/common.py (100%) rename {contrib/drivers/ustreamer => packages/jumpstarter_driver_ustreamer}/jumpstarter_driver_ustreamer/driver.py (100%) rename {contrib/drivers/ustreamer => packages/jumpstarter_driver_ustreamer}/jumpstarter_driver_ustreamer/driver_test.py (100%) rename {contrib/drivers/ustreamer => packages/jumpstarter_driver_ustreamer}/pyproject.toml (95%) rename {contrib/libs/imagehash => packages/jumpstarter_imagehash}/README.md (100%) rename {contrib/libs/imagehash => packages/jumpstarter_imagehash}/jumpstarter_imagehash/__init__.py (100%) rename {contrib/libs/imagehash => packages/jumpstarter_imagehash}/jumpstarter_imagehash/imagehash.py (100%) rename {contrib/libs/imagehash => packages/jumpstarter_imagehash}/jumpstarter_imagehash/imagehash_test.py (100%) rename {contrib/libs/imagehash => packages/jumpstarter_imagehash}/jumpstarter_imagehash/test_image_a.jpeg (100%) rename {contrib/libs/imagehash => packages/jumpstarter_imagehash}/jumpstarter_imagehash/test_image_b.jpeg (100%) rename {contrib/libs/imagehash => packages/jumpstarter_imagehash}/pyproject.toml (95%) create mode 100644 packages/jumpstarter_kubernetes/README.md rename {jumpstarter/k8s => packages/jumpstarter_kubernetes/jumpstarter_kubernetes}/__init__.py (96%) rename {jumpstarter/k8s => packages/jumpstarter_kubernetes/jumpstarter_kubernetes}/clients.py (99%) rename {jumpstarter/k8s => packages/jumpstarter_kubernetes/jumpstarter_kubernetes}/exporters.py (99%) rename {jumpstarter/k8s => packages/jumpstarter_kubernetes/jumpstarter_kubernetes}/install.py (100%) rename {jumpstarter/k8s => packages/jumpstarter_kubernetes/jumpstarter_kubernetes}/leases.py (100%) rename {jumpstarter/k8s => packages/jumpstarter_kubernetes/jumpstarter_kubernetes}/util/__init__.py (100%) rename {jumpstarter/k8s => packages/jumpstarter_kubernetes/jumpstarter_kubernetes}/util/async_custom_object_api.py (100%) create mode 100644 packages/jumpstarter_kubernetes/pyproject.toml rename jumpstarter/testing/__init__.py => packages/jumpstarter_protocol/README.md (100%) create mode 100644 packages/jumpstarter_protocol/jumpstarter_protocol/__init__.py rename {jumpstarter => packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter}/v1/jumpstarter_pb2.py (99%) rename {jumpstarter => packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter}/v1/jumpstarter_pb2_grpc.py (99%) rename {jumpstarter => packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter}/v1/kubernetes_pb2.py (98%) rename {jumpstarter => packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter}/v1/kubernetes_pb2_grpc.py (100%) rename {jumpstarter => packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter}/v1/router_pb2.py (98%) rename {jumpstarter => packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter}/v1/router_pb2_grpc.py (97%) create mode 100644 packages/jumpstarter_protocol/pyproject.toml create mode 100644 packages/jumpstarter_testing/README.md create mode 100644 packages/jumpstarter_testing/conftest.py create mode 100644 packages/jumpstarter_testing/jumpstarter_testing/__init__.py rename {jumpstarter/testing => packages/jumpstarter_testing/jumpstarter_testing}/pytest.py (96%) rename {jumpstarter/testing => packages/jumpstarter_testing/jumpstarter_testing}/pytest_test.py (76%) create mode 100644 packages/jumpstarter_testing/pyproject.toml diff --git a/.gitignore b/.gitignore index 82f927558..d5d7484dd 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,6 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ + +# Ruff cache +.ruff_cache/ \ No newline at end of file diff --git a/contrib/README.md b/CONTRIB.md similarity index 100% rename from contrib/README.md rename to CONTRIB.md diff --git a/Makefile b/Makefile index 49e271aa3..3df44175b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,4 @@ -DRIVER_TARGETS = $(subst contrib/drivers/,driver-,$(wildcard contrib/drivers/*)) -LIB_TARGETS = $(subst contrib/libs/,lib-,$(wildcard contrib/libs/*)) +PKG_TARGETS = $(subst packages/,pkg-,$(wildcard packages/*)) EXAMPLE_TARGETS = $(subst examples/,example-,$(wildcard examples/*)) DOC_LISTEN ?= --host 127.0.0.1 @@ -17,13 +16,10 @@ clean-docs: test-jumpstarter: uv run --isolated --package jumpstarter pytest jumpstarter tests -test-driver-%: contrib/drivers/% +test-pkg-%: packages/% uv run --isolated --directory $< pytest -test-lib-%: contrib/libs/% - uv run --isolated --directory $< pytest - -test-contrib: $(addprefix test-,$(DRIVER_TARGETS)) +test-packages: $(addprefix test-,$(PKG_TARGETS)) clean-venv: -rm -rf ./.venv @@ -40,11 +36,14 @@ clean-test: sync: uv sync --all-packages --all-extras -test: test-jumpstarter test-contrib +test: test-packages + +generate: + buf generate build: uv build --all --out-dir dist clean: clean-docs clean-venv clean-build clean-test -.PHONY: sync docs test test-jumpstarter test-contrib build clean-test clean-docs clean-venv clean-build +.PHONY: sync docs test test-jumpstarter test-packages build clean-test clean-docs clean-venv clean-build diff --git a/contrib/__templates__/create_driver.sh b/__templates__/create_driver.sh similarity index 88% rename from contrib/__templates__/create_driver.sh rename to __templates__/create_driver.sh index 740bf787f..ea0040e23 100755 --- a/contrib/__templates__/create_driver.sh +++ b/__templates__/create_driver.sh @@ -21,7 +21,7 @@ export AUTHOR_NAME=$3 export AUTHOR_EMAIL=$4 # create the driver directory -DRIVER_DIRECTORY=contrib/drivers/${DRIVER_NAME} +DRIVER_DIRECTORY=packages/jumpstarter_driver_${DRIVER_NAME} MODULE_DIRECTORY=${DRIVER_DIRECTORY}/jumpstarter_driver_${DRIVER_NAME} # create the module directories mkdir -p ${MODULE_DIRECTORY} @@ -35,6 +35,5 @@ done for f in .gitignore pyproject.toml README.md examples/exporter.yaml; do echo "Creating: ${DRIVER_DIRECTORY}/${f}" - envsubst < contrib/__templates__/driver/${f}.tmpl > ${DRIVER_DIRECTORY}/${f} + envsubst < packages/__templates__/driver/${f}.tmpl > ${DRIVER_DIRECTORY}/${f} done - diff --git a/contrib/__templates__/driver/.gitignore.tmpl b/__templates__/driver/.gitignore.tmpl similarity index 100% rename from contrib/__templates__/driver/.gitignore.tmpl rename to __templates__/driver/.gitignore.tmpl diff --git a/contrib/__templates__/driver/README.md.tmpl b/__templates__/driver/README.md.tmpl similarity index 100% rename from contrib/__templates__/driver/README.md.tmpl rename to __templates__/driver/README.md.tmpl diff --git a/contrib/__templates__/driver/examples/exporter.yaml.tmpl b/__templates__/driver/examples/exporter.yaml.tmpl similarity index 100% rename from contrib/__templates__/driver/examples/exporter.yaml.tmpl rename to __templates__/driver/examples/exporter.yaml.tmpl diff --git a/contrib/__templates__/driver/jumpstarter_driver/__init__.py.tmpl b/__templates__/driver/jumpstarter_driver/__init__.py.tmpl similarity index 100% rename from contrib/__templates__/driver/jumpstarter_driver/__init__.py.tmpl rename to __templates__/driver/jumpstarter_driver/__init__.py.tmpl diff --git a/contrib/__templates__/driver/jumpstarter_driver/client.py.tmpl b/__templates__/driver/jumpstarter_driver/client.py.tmpl similarity index 100% rename from contrib/__templates__/driver/jumpstarter_driver/client.py.tmpl rename to __templates__/driver/jumpstarter_driver/client.py.tmpl diff --git a/contrib/__templates__/driver/jumpstarter_driver/driver.py.tmpl b/__templates__/driver/jumpstarter_driver/driver.py.tmpl similarity index 100% rename from contrib/__templates__/driver/jumpstarter_driver/driver.py.tmpl rename to __templates__/driver/jumpstarter_driver/driver.py.tmpl diff --git a/contrib/__templates__/driver/jumpstarter_driver/driver_test.py.tmpl b/__templates__/driver/jumpstarter_driver/driver_test.py.tmpl similarity index 100% rename from contrib/__templates__/driver/jumpstarter_driver/driver_test.py.tmpl rename to __templates__/driver/jumpstarter_driver/driver_test.py.tmpl diff --git a/contrib/__templates__/driver/pyproject.toml.tmpl b/__templates__/driver/pyproject.toml.tmpl similarity index 95% rename from contrib/__templates__/driver/pyproject.toml.tmpl rename to __templates__/driver/pyproject.toml.tmpl index 01c6b1323..4927c8275 100644 --- a/contrib/__templates__/driver/pyproject.toml.tmpl +++ b/__templates__/driver/pyproject.toml.tmpl @@ -14,7 +14,7 @@ dependencies = [ [tool.hatch.version] source = "vcs" -raw-options = { 'root' = '../../../'} +raw-options = { 'root' = '../../'} [tool.hatch.metadata.hooks.vcs.urls] Homepage = "https://jumpstarter.dev" diff --git a/buf.gen.yaml b/buf.gen.yaml index 6b153cb44..6b52d6ac1 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -3,9 +3,9 @@ managed: enabled: true plugins: - remote: buf.build/protocolbuffers/python - out: . + out: ./packages/jumpstarter_protocol/jumpstarter_protocol - remote: buf.build/grpc/python - out: . + out: ./packages/jumpstarter_protocol/jumpstarter_protocol inputs: - git_repo: https://github.com/jumpstarter-dev/jumpstarter-protocol.git subdir: proto diff --git a/cli/jmp/pyproject.toml b/cli/jmp/pyproject.toml deleted file mode 100644 index eeaf576bf..000000000 --- a/cli/jmp/pyproject.toml +++ /dev/null @@ -1,51 +0,0 @@ -[project] -name = "jumpstarter-cli" -dynamic = ["version", "urls"] -description = "" -authors = [ - { name = "Nick Cao", email = "ncao@redhat.com" }, - { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, - { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, -] -readme = "README.md" -license = { text = "Apache-2.0" } -requires-python = ">=3.11" -dependencies = [ - "jumpstarter", - "jumpstarter-cli-common", - "jumpstarter-client-cli", - "jumpstarter-admin-cli", - "jumpstarter-exporter-cli" -] - -[dependency-groups] -dev = [ - "pytest>=8.3.2", - "pytest-anyio>=0.0.0", - "pytest-asyncio>=0.0.0", - "pytest-cov>=5.0.0", -] - -[project.scripts] -jmp = "jumpstarter_cli:jmp" - -[tool.uv.sources] -jumpstarter-cli-common = { workspace = true } -jumpstarter-admin-cli = { workspace = true } -jumpstarter-client-cli = { workspace = true } -jumpstarter-exporter-cli = { workspace = true } - -[tool.hatch.build.targets.wheel] -packages = ["jumpstarter_cli"] - -[tool.hatch.metadata.hooks.vcs.urls] -Homepage = "https://jumpstarter.dev" -source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" - -[tool.hatch.version] -source = "vcs" -raw-options = { 'root' = '../../'} - -[build-system] -requires = ["hatchling", "hatch-vcs"] -build-backend = "hatchling.build" diff --git a/contrib/drivers/http/.gitignore b/contrib/drivers/http/.gitignore deleted file mode 100644 index cbc5d672b..000000000 --- a/contrib/drivers/http/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -__pycache__/ -.coverage -coverage.xml diff --git a/contrib/drivers/http/.python-version b/contrib/drivers/http/.python-version deleted file mode 100644 index e4fba2183..000000000 --- a/contrib/drivers/http/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.12 diff --git a/contrib/drivers/http/uv.lock b/contrib/drivers/http/uv.lock deleted file mode 100644 index c75d57685..000000000 --- a/contrib/drivers/http/uv.lock +++ /dev/null @@ -1,927 +0,0 @@ -version = 1 -requires-python = ">=3.12" -resolution-markers = [ - "python_full_version < '3.13'", - "python_full_version >= '3.13'", -] - -[[package]] -name = "aiohappyeyeballs" -version = "2.4.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bc/69/2f6d5a019bd02e920a3417689a89887b39ad1e350b562f9955693d900c40/aiohappyeyeballs-2.4.3.tar.gz", hash = "sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586", size = 21809 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/d8/120cd0fe3e8530df0539e71ba9683eade12cae103dd7543e50d15f737917/aiohappyeyeballs-2.4.3-py3-none-any.whl", hash = "sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572", size = 14742 }, -] - -[[package]] -name = "aiohttp" -version = "3.10.10" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohappyeyeballs" }, - { name = "aiosignal" }, - { name = "attrs" }, - { name = "frozenlist" }, - { name = "multidict" }, - { name = "yarl" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/17/7e/16e57e6cf20eb62481a2f9ce8674328407187950ccc602ad07c685279141/aiohttp-3.10.10.tar.gz", hash = "sha256:0631dd7c9f0822cc61c88586ca76d5b5ada26538097d0f1df510b082bad3411a", size = 7542993 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/99/4c5aefe5ad06a1baf206aed6598c7cdcbc7c044c46801cd0d1ecb758cae3/aiohttp-3.10.10-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9294bbb581f92770e6ed5c19559e1e99255e4ca604a22c5c6397b2f9dd3ee42c", size = 583536 }, - { url = "https://files.pythonhosted.org/packages/a9/36/8b3bc49b49cb6d2da40ee61ff15dbcc44fd345a3e6ab5bb20844df929821/aiohttp-3.10.10-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a8fa23fe62c436ccf23ff930149c047f060c7126eae3ccea005f0483f27b2e28", size = 395693 }, - { url = "https://files.pythonhosted.org/packages/e1/77/0aa8660dcf11fa65d61712dbb458c4989de220a844bd69778dff25f2d50b/aiohttp-3.10.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5c6a5b8c7926ba5d8545c7dd22961a107526562da31a7a32fa2456baf040939f", size = 390898 }, - { url = "https://files.pythonhosted.org/packages/38/d2/b833d95deb48c75db85bf6646de0a697e7fb5d87bd27cbade4f9746b48b1/aiohttp-3.10.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:007ec22fbc573e5eb2fb7dec4198ef8f6bf2fe4ce20020798b2eb5d0abda6138", size = 1312060 }, - { url = "https://files.pythonhosted.org/packages/aa/5f/29fd5113165a0893de8efedf9b4737e0ba92dfcd791415a528f947d10299/aiohttp-3.10.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9627cc1a10c8c409b5822a92d57a77f383b554463d1884008e051c32ab1b3742", size = 1350553 }, - { url = "https://files.pythonhosted.org/packages/ad/cc/f835f74b7d344428469200105236d44606cfa448be1e7c95ca52880d9bac/aiohttp-3.10.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:50edbcad60d8f0e3eccc68da67f37268b5144ecc34d59f27a02f9611c1d4eec7", size = 1392646 }, - { url = "https://files.pythonhosted.org/packages/bf/fe/1332409d845ca601893bbf2d76935e0b93d41686e5f333841c7d7a4a770d/aiohttp-3.10.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a45d85cf20b5e0d0aa5a8dca27cce8eddef3292bc29d72dcad1641f4ed50aa16", size = 1306310 }, - { url = "https://files.pythonhosted.org/packages/e4/a1/25a7633a5a513278a9892e333501e2e69c83e50be4b57a62285fb7a008c3/aiohttp-3.10.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b00807e2605f16e1e198f33a53ce3c4523114059b0c09c337209ae55e3823a8", size = 1260255 }, - { url = "https://files.pythonhosted.org/packages/f2/39/30eafe89e0e2a06c25e4762844c8214c0c0cd0fd9ffc3471694a7986f421/aiohttp-3.10.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f2d4324a98062be0525d16f768a03e0bbb3b9fe301ceee99611dc9a7953124e6", size = 1271141 }, - { url = "https://files.pythonhosted.org/packages/5b/fc/33125df728b48391ef1fcb512dfb02072158cc10d041414fb79803463020/aiohttp-3.10.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:438cd072f75bb6612f2aca29f8bd7cdf6e35e8f160bc312e49fbecab77c99e3a", size = 1280244 }, - { url = "https://files.pythonhosted.org/packages/3b/61/e42bf2c2934b5caa4e2ec0b5e5fd86989adb022b5ee60c2572a9d77cf6fe/aiohttp-3.10.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:baa42524a82f75303f714108fea528ccacf0386af429b69fff141ffef1c534f9", size = 1316805 }, - { url = "https://files.pythonhosted.org/packages/18/32/f52a5e2ae9ad3bba10e026a63a7a23abfa37c7d97aeeb9004eaa98df3ce3/aiohttp-3.10.10-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a7d8d14fe962153fc681f6366bdec33d4356f98a3e3567782aac1b6e0e40109a", size = 1343930 }, - { url = "https://files.pythonhosted.org/packages/05/be/6a403b464dcab3631fe8e27b0f1d906d9e45c5e92aca97ee007e5a895560/aiohttp-3.10.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c1277cd707c465cd09572a774559a3cc7c7a28802eb3a2a9472588f062097205", size = 1306186 }, - { url = "https://files.pythonhosted.org/packages/8e/fd/bb50fe781068a736a02bf5c7ad5f3ab53e39f1d1e63110da6d30f7605edc/aiohttp-3.10.10-cp312-cp312-win32.whl", hash = "sha256:59bb3c54aa420521dc4ce3cc2c3fe2ad82adf7b09403fa1f48ae45c0cbde6628", size = 359289 }, - { url = "https://files.pythonhosted.org/packages/70/9e/5add7e240f77ef67c275c82cc1d08afbca57b77593118c1f6e920ae8ad3f/aiohttp-3.10.10-cp312-cp312-win_amd64.whl", hash = "sha256:0e1b370d8007c4ae31ee6db7f9a2fe801a42b146cec80a86766e7ad5c4a259cf", size = 379313 }, - { url = "https://files.pythonhosted.org/packages/b1/eb/618b1b76c7fe8082a71c9d62e3fe84c5b9af6703078caa9ec57850a12080/aiohttp-3.10.10-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ad7593bb24b2ab09e65e8a1d385606f0f47c65b5a2ae6c551db67d6653e78c28", size = 576114 }, - { url = "https://files.pythonhosted.org/packages/aa/37/3126995d7869f8b30d05381b81a2d4fb4ec6ad313db788e009bc6d39c211/aiohttp-3.10.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1eb89d3d29adaf533588f209768a9c02e44e4baf832b08118749c5fad191781d", size = 391901 }, - { url = "https://files.pythonhosted.org/packages/3e/f2/8fdfc845be1f811c31ceb797968523813f8e1263ee3e9120d61253f6848f/aiohttp-3.10.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3fe407bf93533a6fa82dece0e74dbcaaf5d684e5a51862887f9eaebe6372cd79", size = 387418 }, - { url = "https://files.pythonhosted.org/packages/60/d5/33d2061d36bf07e80286e04b7e0a4de37ce04b5ebfed72dba67659a05250/aiohttp-3.10.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50aed5155f819873d23520919e16703fc8925e509abbb1a1491b0087d1cd969e", size = 1287073 }, - { url = "https://files.pythonhosted.org/packages/00/52/affb55be16a4747740bd630b4c002dac6c5eac42f9bb64202fc3cf3f1930/aiohttp-3.10.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f05e9727ce409358baa615dbeb9b969db94324a79b5a5cea45d39bdb01d82e6", size = 1323612 }, - { url = "https://files.pythonhosted.org/packages/94/f2/cddb69b975387daa2182a8442566971d6410b8a0179bb4540d81c97b1611/aiohttp-3.10.10-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dffb610a30d643983aeb185ce134f97f290f8935f0abccdd32c77bed9388b42", size = 1368406 }, - { url = "https://files.pythonhosted.org/packages/c1/e4/afba7327da4d932da8c6e29aecaf855f9d52dace53ac15bfc8030a246f1b/aiohttp-3.10.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa6658732517ddabe22c9036479eabce6036655ba87a0224c612e1ae6af2087e", size = 1282761 }, - { url = "https://files.pythonhosted.org/packages/9f/6b/364856faa0c9031ea76e24ef0f7fef79cddd9fa8e7dba9a1771c6acc56b5/aiohttp-3.10.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:741a46d58677d8c733175d7e5aa618d277cd9d880301a380fd296975a9cdd7bc", size = 1236518 }, - { url = "https://files.pythonhosted.org/packages/46/af/c382846f8356fe64a7b5908bb9b477457aa23b71be7ed551013b7b7d4d87/aiohttp-3.10.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e00e3505cd80440f6c98c6d69269dcc2a119f86ad0a9fd70bccc59504bebd68a", size = 1250344 }, - { url = "https://files.pythonhosted.org/packages/87/53/294f87fc086fd0772d0ab82497beb9df67f0f27a8b3dd5742a2656db2bc6/aiohttp-3.10.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ffe595f10566f8276b76dc3a11ae4bb7eba1aac8ddd75811736a15b0d5311414", size = 1248956 }, - { url = "https://files.pythonhosted.org/packages/86/30/7d746717fe11bdfefb88bb6c09c5fc985d85c4632da8bb6018e273899254/aiohttp-3.10.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdfcf6443637c148c4e1a20c48c566aa694fa5e288d34b20fcdc58507882fed3", size = 1293379 }, - { url = "https://files.pythonhosted.org/packages/48/b9/45d670a834458db67a24258e9139ba61fa3bd7d69b98ecf3650c22806f8f/aiohttp-3.10.10-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d183cf9c797a5291e8301790ed6d053480ed94070637bfaad914dd38b0981f67", size = 1320108 }, - { url = "https://files.pythonhosted.org/packages/72/8c/804bb2e837a175635d2000a0659eafc15b2e9d92d3d81c8f69e141ecd0b0/aiohttp-3.10.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:77abf6665ae54000b98b3c742bc6ea1d1fb31c394bcabf8b5d2c1ac3ebfe7f3b", size = 1281546 }, - { url = "https://files.pythonhosted.org/packages/89/c0/862e6a9de3d6eeb126cd9d9ea388243b70df9b871ce1a42b193b7a4a77fc/aiohttp-3.10.10-cp313-cp313-win32.whl", hash = "sha256:4470c73c12cd9109db8277287d11f9dd98f77fc54155fc71a7738a83ffcc8ea8", size = 357516 }, - { url = "https://files.pythonhosted.org/packages/ae/63/3e1aee3e554263f3f1011cca50d78a4894ae16ce99bf78101ac3a2f0ef74/aiohttp-3.10.10-cp313-cp313-win_amd64.whl", hash = "sha256:486f7aabfa292719a2753c016cc3a8f8172965cabb3ea2e7f7436c7f5a22a151", size = 376785 }, -] - -[[package]] -name = "aiosignal" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "frozenlist" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ae/67/0952ed97a9793b4958e5736f6d2b346b414a2cd63e82d05940032f45b32f/aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", size = 19422 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17", size = 7617 }, -] - -[[package]] -name = "annotated-types" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, -] - -[[package]] -name = "anyio" -version = "4.6.2.post1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, - { name = "sniffio" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9f/09/45b9b7a6d4e45c6bcb5bf61d19e3ab87df68e0601fa8c5293de3542546cc/anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c", size = 173422 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/f5/f2b75d2fc6f1a260f340f0e7c6a060f4dd2961cc16884ed851b0d18da06a/anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d", size = 90377 }, -] - -[[package]] -name = "attrs" -version = "24.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fc/0f/aafca9af9315aee06a89ffde799a10a582fe8de76c563ee80bbcdc08b3fb/attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346", size = 792678 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2", size = 63001 }, -] - -[[package]] -name = "bcrypt" -version = "4.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e4/7e/d95e7d96d4828e965891af92e43b52a4cd3395dc1c1ef4ee62748d0471d0/bcrypt-4.2.0.tar.gz", hash = "sha256:cf69eaf5185fd58f268f805b505ce31f9b9fc2d64b376642164e9244540c1221", size = 24294 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/81/4e8f5bc0cd947e91fb720e1737371922854da47a94bc9630454e7b2845f8/bcrypt-4.2.0-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:096a15d26ed6ce37a14c1ac1e48119660f21b24cba457f160a4b830f3fe6b5cb", size = 471568 }, - { url = "https://files.pythonhosted.org/packages/05/d2/1be1e16aedec04bcf8d0156e01b987d16a2063d38e64c3f28030a3427d61/bcrypt-4.2.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c02d944ca89d9b1922ceb8a46460dd17df1ba37ab66feac4870f6862a1533c00", size = 277372 }, - { url = "https://files.pythonhosted.org/packages/e3/96/7a654027638ad9b7589effb6db77eb63eba64319dfeaf9c0f4ca953e5f76/bcrypt-4.2.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d84cf6d877918620b687b8fd1bf7781d11e8a0998f576c7aa939776b512b98d", size = 273488 }, - { url = "https://files.pythonhosted.org/packages/46/54/dc7b58abeb4a3d95bab653405935e27ba32f21b812d8ff38f271fb6f7f55/bcrypt-4.2.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:1bb429fedbe0249465cdd85a58e8376f31bb315e484f16e68ca4c786dcc04291", size = 277759 }, - { url = "https://files.pythonhosted.org/packages/ac/be/da233c5f11fce3f8adec05e8e532b299b64833cc962f49331cdd0e614fa9/bcrypt-4.2.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:655ea221910bcac76ea08aaa76df427ef8625f92e55a8ee44fbf7753dbabb328", size = 273796 }, - { url = "https://files.pythonhosted.org/packages/b0/b8/8b4add88d55a263cf1c6b8cf66c735280954a04223fcd2880120cc767ac3/bcrypt-4.2.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:1ee38e858bf5d0287c39b7a1fc59eec64bbf880c7d504d3a06a96c16e14058e7", size = 311082 }, - { url = "https://files.pythonhosted.org/packages/7b/76/2aa660679abbdc7f8ee961552e4bb6415a81b303e55e9374533f22770203/bcrypt-4.2.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0da52759f7f30e83f1e30a888d9163a81353ef224d82dc58eb5bb52efcabc399", size = 305912 }, - { url = "https://files.pythonhosted.org/packages/00/03/2af7c45034aba6002d4f2b728c1a385676b4eab7d764410e34fd768009f2/bcrypt-4.2.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3698393a1b1f1fd5714524193849d0c6d524d33523acca37cd28f02899285060", size = 325185 }, - { url = "https://files.pythonhosted.org/packages/dc/5d/6843443ce4ab3af40bddb6c7c085ed4a8418b3396f7a17e60e6d9888416c/bcrypt-4.2.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:762a2c5fb35f89606a9fde5e51392dad0cd1ab7ae64149a8b935fe8d79dd5ed7", size = 335188 }, - { url = "https://files.pythonhosted.org/packages/cb/4c/ff8ca83d816052fba36def1d24e97d9a85739b9bbf428c0d0ecd296a07c8/bcrypt-4.2.0-cp37-abi3-win32.whl", hash = "sha256:5a1e8aa9b28ae28020a3ac4b053117fb51c57a010b9f969603ed885f23841458", size = 156481 }, - { url = "https://files.pythonhosted.org/packages/65/f1/e09626c88a56cda488810fb29d5035f1662873777ed337880856b9d204ae/bcrypt-4.2.0-cp37-abi3-win_amd64.whl", hash = "sha256:8f6ede91359e5df88d1f5c1ef47428a4420136f3ce97763e31b86dd8280fbdf5", size = 151336 }, - { url = "https://files.pythonhosted.org/packages/96/86/8c6a84daed4dd878fbab094400c9174c43d9b838ace077a2f8ee8bc3ae12/bcrypt-4.2.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:c52aac18ea1f4a4f65963ea4f9530c306b56ccd0c6f8c8da0c06976e34a6e841", size = 472414 }, - { url = "https://files.pythonhosted.org/packages/f6/05/e394515f4e23c17662e5aeb4d1859b11dc651be01a3bd03c2e919a155901/bcrypt-4.2.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3bbbfb2734f0e4f37c5136130405332640a1e46e6b23e000eeff2ba8d005da68", size = 277599 }, - { url = "https://files.pythonhosted.org/packages/4b/3b/ad784eac415937c53da48983756105d267b91e56aa53ba8a1b2014b8d930/bcrypt-4.2.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3413bd60460f76097ee2e0a493ccebe4a7601918219c02f503984f0a7ee0aebe", size = 273491 }, - { url = "https://files.pythonhosted.org/packages/cc/14/b9ff8e0218bee95e517b70e91130effb4511e8827ac1ab00b4e30943a3f6/bcrypt-4.2.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8d7bb9c42801035e61c109c345a28ed7e84426ae4865511eb82e913df18f58c2", size = 277934 }, - { url = "https://files.pythonhosted.org/packages/3e/d0/31938bb697600a04864246acde4918c4190a938f891fd11883eaaf41327a/bcrypt-4.2.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d3a6d28cb2305b43feac298774b997e372e56c7c7afd90a12b3dc49b189151c", size = 273804 }, - { url = "https://files.pythonhosted.org/packages/e7/c3/dae866739989e3f04ae304e1201932571708cb292a28b2f1b93283e2dcd8/bcrypt-4.2.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:9c1c4ad86351339c5f320ca372dfba6cb6beb25e8efc659bedd918d921956bae", size = 311275 }, - { url = "https://files.pythonhosted.org/packages/5d/2c/019bc2c63c6125ddf0483ee7d914a405860327767d437913942b476e9c9b/bcrypt-4.2.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:27fe0f57bb5573104b5a6de5e4153c60814c711b29364c10a75a54bb6d7ff48d", size = 306355 }, - { url = "https://files.pythonhosted.org/packages/75/fe/9e137727f122bbe29771d56afbf4e0dbc85968caa8957806f86404a5bfe1/bcrypt-4.2.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8ac68872c82f1add6a20bd489870c71b00ebacd2e9134a8aa3f98a0052ab4b0e", size = 325381 }, - { url = "https://files.pythonhosted.org/packages/1a/d4/586b9c18a327561ea4cd336ff4586cca1a7aa0f5ee04e23a8a8bb9ca64f1/bcrypt-4.2.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cb2a8ec2bc07d3553ccebf0746bbf3d19426d1c6d1adbd4fa48925f66af7b9e8", size = 335685 }, - { url = "https://files.pythonhosted.org/packages/24/55/1a7127faf4576138bb278b91e9c75307490178979d69c8e6e273f74b974f/bcrypt-4.2.0-cp39-abi3-win32.whl", hash = "sha256:77800b7147c9dc905db1cba26abe31e504d8247ac73580b4aa179f98e6608f34", size = 155857 }, - { url = "https://files.pythonhosted.org/packages/1c/2a/c74052e54162ec639266d91539cca7cbf3d1d3b8b36afbfeaee0ea6a1702/bcrypt-4.2.0-cp39-abi3-win_amd64.whl", hash = "sha256:61ed14326ee023917ecd093ee6ef422a72f3aec6f07e21ea5f10622b735538a9", size = 151717 }, -] - -[[package]] -name = "certifi" -version = "2024.8.30" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9", size = 168507 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", size = 167321 }, -] - -[[package]] -name = "cffi" -version = "1.17.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pycparser" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, - { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, - { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, - { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 }, - { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 }, - { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 }, - { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 }, - { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 }, - { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 }, - { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, - { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, - { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 }, - { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 }, - { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 }, - { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 }, - { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 }, - { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 }, - { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 }, - { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 }, - { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 }, - { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, - { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, -] - -[[package]] -name = "click" -version = "8.1.7" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941 }, -] - -[[package]] -name = "colorama" -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 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, -] - -[[package]] -name = "coverage" -version = "7.6.9" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5b/d2/c25011f4d036cf7e8acbbee07a8e09e9018390aee25ba085596c4b83d510/coverage-7.6.9.tar.gz", hash = "sha256:4a8d8977b0c6ef5aeadcb644da9e69ae0dcfe66ec7f368c89c72e058bd71164d", size = 801710 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/60/52/b16af8989a2daf0f80a88522bd8e8eed90b5fcbdecf02a6888f3e80f6ba7/coverage-7.6.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:99e266ae0b5d15f1ca8d278a668df6f51cc4b854513daab5cae695ed7b721cf8", size = 207325 }, - { url = "https://files.pythonhosted.org/packages/0f/79/6b7826fca8846c1216a113227b9f114ac3e6eacf168b4adcad0cb974aaca/coverage-7.6.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9901d36492009a0a9b94b20e52ebfc8453bf49bb2b27bca2c9706f8b4f5a554a", size = 207563 }, - { url = "https://files.pythonhosted.org/packages/a7/07/0bc73da0ccaf45d0d64ef86d33b7d7fdeef84b4c44bf6b85fb12c215c5a6/coverage-7.6.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abd3e72dd5b97e3af4246cdada7738ef0e608168de952b837b8dd7e90341f015", size = 240580 }, - { url = "https://files.pythonhosted.org/packages/71/8a/9761f409910961647d892454687cedbaccb99aae828f49486734a82ede6e/coverage-7.6.9-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff74026a461eb0660366fb01c650c1d00f833a086b336bdad7ab00cc952072b3", size = 237613 }, - { url = "https://files.pythonhosted.org/packages/8b/10/ee7d696a17ac94f32f2dbda1e17e730bf798ae9931aec1fc01c1944cd4de/coverage-7.6.9-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65dad5a248823a4996724a88eb51d4b31587aa7aa428562dbe459c684e5787ae", size = 239684 }, - { url = "https://files.pythonhosted.org/packages/16/60/aa1066040d3c52fff051243c2d6ccda264da72dc6d199d047624d395b2b2/coverage-7.6.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:22be16571504c9ccea919fcedb459d5ab20d41172056206eb2994e2ff06118a4", size = 239112 }, - { url = "https://files.pythonhosted.org/packages/4e/e5/69f35344c6f932ba9028bf168d14a79fedb0dd4849b796d43c81ce75a3c9/coverage-7.6.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f957943bc718b87144ecaee70762bc2bc3f1a7a53c7b861103546d3a403f0a6", size = 237428 }, - { url = "https://files.pythonhosted.org/packages/32/20/adc895523c4a28f63441b8ac645abd74f9bdd499d2d175bef5b41fc7f92d/coverage-7.6.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ae1387db4aecb1f485fb70a6c0148c6cdaebb6038f1d40089b1fc84a5db556f", size = 239098 }, - { url = "https://files.pythonhosted.org/packages/a9/a6/e0e74230c9bb3549ec8ffc137cfd16ea5d56e993d6bffed2218bff6187e3/coverage-7.6.9-cp312-cp312-win32.whl", hash = "sha256:1a330812d9cc7ac2182586f6d41b4d0fadf9be9049f350e0efb275c8ee8eb692", size = 209940 }, - { url = "https://files.pythonhosted.org/packages/3e/18/cb5b88349d4aa2f41ec78d65f92ea32572b30b3f55bc2b70e87578b8f434/coverage-7.6.9-cp312-cp312-win_amd64.whl", hash = "sha256:b12c6b18269ca471eedd41c1b6a1065b2f7827508edb9a7ed5555e9a56dcfc97", size = 210726 }, - { url = "https://files.pythonhosted.org/packages/35/26/9abab6539d2191dbda2ce8c97b67d74cbfc966cc5b25abb880ffc7c459bc/coverage-7.6.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:899b8cd4781c400454f2f64f7776a5d87bbd7b3e7f7bda0cb18f857bb1334664", size = 207356 }, - { url = "https://files.pythonhosted.org/packages/44/da/d49f19402240c93453f606e660a6676a2a1fbbaa6870cc23207790aa9697/coverage-7.6.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:61f70dc68bd36810972e55bbbe83674ea073dd1dcc121040a08cdf3416c5349c", size = 207614 }, - { url = "https://files.pythonhosted.org/packages/da/e6/93bb9bf85497816082ec8da6124c25efa2052bd4c887dd3b317b91990c9e/coverage-7.6.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a289d23d4c46f1a82d5db4abeb40b9b5be91731ee19a379d15790e53031c014", size = 240129 }, - { url = "https://files.pythonhosted.org/packages/df/65/6a824b9406fe066835c1274a9949e06f084d3e605eb1a602727a27ec2fe3/coverage-7.6.9-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e216d8044a356fc0337c7a2a0536d6de07888d7bcda76febcb8adc50bdbbd00", size = 237276 }, - { url = "https://files.pythonhosted.org/packages/9f/79/6c7a800913a9dd23ac8c8da133ebb556771a5a3d4df36b46767b1baffd35/coverage-7.6.9-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c026eb44f744acaa2bda7493dad903aa5bf5fc4f2554293a798d5606710055d", size = 239267 }, - { url = "https://files.pythonhosted.org/packages/57/e7/834d530293fdc8a63ba8ff70033d5182022e569eceb9aec7fc716b678a39/coverage-7.6.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e77363e8425325384f9d49272c54045bbed2f478e9dd698dbc65dbc37860eb0a", size = 238887 }, - { url = "https://files.pythonhosted.org/packages/15/05/ec9d6080852984f7163c96984444e7cd98b338fd045b191064f943ee1c08/coverage-7.6.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:777abfab476cf83b5177b84d7486497e034eb9eaea0d746ce0c1268c71652077", size = 236970 }, - { url = "https://files.pythonhosted.org/packages/0a/d8/775937670b93156aec29f694ce37f56214ed7597e1a75b4083ee4c32121c/coverage-7.6.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:447af20e25fdbe16f26e84eb714ba21d98868705cb138252d28bc400381f6ffb", size = 238831 }, - { url = "https://files.pythonhosted.org/packages/f4/58/88551cb7fdd5ec98cb6044e8814e38583436b14040a5ece15349c44c8f7c/coverage-7.6.9-cp313-cp313-win32.whl", hash = "sha256:d872ec5aeb086cbea771c573600d47944eea2dcba8be5f3ee649bfe3cb8dc9ba", size = 210000 }, - { url = "https://files.pythonhosted.org/packages/b7/12/cfbf49b95120872785ff8d56ab1c7fe3970a65e35010c311d7dd35c5fd00/coverage-7.6.9-cp313-cp313-win_amd64.whl", hash = "sha256:fd1213c86e48dfdc5a0cc676551db467495a95a662d2396ecd58e719191446e1", size = 210753 }, - { url = "https://files.pythonhosted.org/packages/7c/68/c1cb31445599b04bde21cbbaa6d21b47c5823cdfef99eae470dfce49c35a/coverage-7.6.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ba9e7484d286cd5a43744e5f47b0b3fb457865baf07bafc6bee91896364e1419", size = 208091 }, - { url = "https://files.pythonhosted.org/packages/11/73/84b02c6b19c4a11eb2d5b5eabe926fb26c21c080e0852f5e5a4f01165f9e/coverage-7.6.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e5ea1cf0872ee455c03e5674b5bca5e3e68e159379c1af0903e89f5eba9ccc3a", size = 208369 }, - { url = "https://files.pythonhosted.org/packages/de/e0/ae5d878b72ff26df2e994a5c5b1c1f6a7507d976b23beecb1ed4c85411ef/coverage-7.6.9-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d10e07aa2b91835d6abec555ec8b2733347956991901eea6ffac295f83a30e4", size = 251089 }, - { url = "https://files.pythonhosted.org/packages/ab/9c/0aaac011aef95a93ef3cb2fba3fde30bc7e68a6635199ed469b1f5ea355a/coverage-7.6.9-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:13a9e2d3ee855db3dd6ea1ba5203316a1b1fd8eaeffc37c5b54987e61e4194ae", size = 246806 }, - { url = "https://files.pythonhosted.org/packages/f8/19/4d5d3ae66938a7dcb2f58cef3fa5386f838f469575b0bb568c8cc9e3a33d/coverage-7.6.9-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c38bf15a40ccf5619fa2fe8f26106c7e8e080d7760aeccb3722664c8656b030", size = 249164 }, - { url = "https://files.pythonhosted.org/packages/b3/0b/4ee8a7821f682af9ad440ae3c1e379da89a998883271f088102d7ca2473d/coverage-7.6.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d5275455b3e4627c8e7154feaf7ee0743c2e7af82f6e3b561967b1cca755a0be", size = 248642 }, - { url = "https://files.pythonhosted.org/packages/8a/12/36ff1d52be18a16b4700f561852e7afd8df56363a5edcfb04cf26a0e19e0/coverage-7.6.9-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8f8770dfc6e2c6a2d4569f411015c8d751c980d17a14b0530da2d7f27ffdd88e", size = 246516 }, - { url = "https://files.pythonhosted.org/packages/43/d0/8e258f6c3a527c1655602f4f576215e055ac704de2d101710a71a2affac2/coverage-7.6.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8d2dfa71665a29b153a9681edb1c8d9c1ea50dfc2375fb4dac99ea7e21a0bcd9", size = 247783 }, - { url = "https://files.pythonhosted.org/packages/a9/0d/1e4a48d289429d38aae3babdfcadbf35ca36bdcf3efc8f09b550a845bdb5/coverage-7.6.9-cp313-cp313t-win32.whl", hash = "sha256:5e6b86b5847a016d0fbd31ffe1001b63355ed309651851295315031ea7eb5a9b", size = 210646 }, - { url = "https://files.pythonhosted.org/packages/26/74/b0729f196f328ac55e42b1e22ec2f16d8bcafe4b8158a26ec9f1cdd1d93e/coverage-7.6.9-cp313-cp313t-win_amd64.whl", hash = "sha256:97ddc94d46088304772d21b060041c97fc16bdda13c6c7f9d8fcd8d5ae0d8611", size = 211815 }, -] - -[[package]] -name = "cryptography" -version = "43.0.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0d/05/07b55d1fa21ac18c3a8c79f764e2514e6f6a9698f1be44994f5adf0d29db/cryptography-43.0.3.tar.gz", hash = "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805", size = 686989 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/f3/01fdf26701a26f4b4dbc337a26883ad5bccaa6f1bbbdd29cd89e22f18a1c/cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e", size = 6225303 }, - { url = "https://files.pythonhosted.org/packages/a3/01/4896f3d1b392025d4fcbecf40fdea92d3df8662123f6835d0af828d148fd/cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e", size = 3760905 }, - { url = "https://files.pythonhosted.org/packages/0a/be/f9a1f673f0ed4b7f6c643164e513dbad28dd4f2dcdf5715004f172ef24b6/cryptography-43.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f", size = 3977271 }, - { url = "https://files.pythonhosted.org/packages/4e/49/80c3a7b5514d1b416d7350830e8c422a4d667b6d9b16a9392ebfd4a5388a/cryptography-43.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6", size = 3746606 }, - { url = "https://files.pythonhosted.org/packages/0e/16/a28ddf78ac6e7e3f25ebcef69ab15c2c6be5ff9743dd0709a69a4f968472/cryptography-43.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18", size = 3986484 }, - { url = "https://files.pythonhosted.org/packages/01/f5/69ae8da70c19864a32b0315049866c4d411cce423ec169993d0434218762/cryptography-43.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd", size = 3852131 }, - { url = "https://files.pythonhosted.org/packages/fd/db/e74911d95c040f9afd3612b1f732e52b3e517cb80de8bf183be0b7d413c6/cryptography-43.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73", size = 4075647 }, - { url = "https://files.pythonhosted.org/packages/56/48/7b6b190f1462818b324e674fa20d1d5ef3e24f2328675b9b16189cbf0b3c/cryptography-43.0.3-cp37-abi3-win32.whl", hash = "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2", size = 2623873 }, - { url = "https://files.pythonhosted.org/packages/eb/b1/0ebff61a004f7f89e7b65ca95f2f2375679d43d0290672f7713ee3162aff/cryptography-43.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd", size = 3068039 }, - { url = "https://files.pythonhosted.org/packages/30/d5/c8b32c047e2e81dd172138f772e81d852c51f0f2ad2ae8a24f1122e9e9a7/cryptography-43.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984", size = 6222984 }, - { url = "https://files.pythonhosted.org/packages/2f/78/55356eb9075d0be6e81b59f45c7b48df87f76a20e73893872170471f3ee8/cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5", size = 3762968 }, - { url = "https://files.pythonhosted.org/packages/2a/2c/488776a3dc843f95f86d2f957ca0fc3407d0242b50bede7fad1e339be03f/cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4", size = 3977754 }, - { url = "https://files.pythonhosted.org/packages/7c/04/2345ca92f7a22f601a9c62961741ef7dd0127c39f7310dffa0041c80f16f/cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7", size = 3749458 }, - { url = "https://files.pythonhosted.org/packages/ac/25/e715fa0bc24ac2114ed69da33adf451a38abb6f3f24ec207908112e9ba53/cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405", size = 3988220 }, - { url = "https://files.pythonhosted.org/packages/21/ce/b9c9ff56c7164d8e2edfb6c9305045fbc0df4508ccfdb13ee66eb8c95b0e/cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16", size = 3853898 }, - { url = "https://files.pythonhosted.org/packages/2a/33/b3682992ab2e9476b9c81fff22f02c8b0a1e6e1d49ee1750a67d85fd7ed2/cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73", size = 4076592 }, - { url = "https://files.pythonhosted.org/packages/81/1e/ffcc41b3cebd64ca90b28fd58141c5f68c83d48563c88333ab660e002cd3/cryptography-43.0.3-cp39-abi3-win32.whl", hash = "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995", size = 2623145 }, - { url = "https://files.pythonhosted.org/packages/87/5c/3dab83cc4aba1f4b0e733e3f0c3e7d4386440d660ba5b1e3ff995feb734d/cryptography-43.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362", size = 3068026 }, -] - -[[package]] -name = "decorator" -version = "5.1.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/66/0c/8d907af351aa16b42caae42f9d6aa37b900c67308052d10fdce809f8d952/decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", size = 35016 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/50/83c593b07763e1161326b3b8c6686f0f4b0f24d5526546bee538c89837d6/decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186", size = 9073 }, -] - -[[package]] -name = "deprecated" -version = "1.2.14" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "wrapt" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/92/14/1e41f504a246fc224d2ac264c227975427a85caf37c3979979edb9b1b232/Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3", size = 2974416 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c", size = 9561 }, -] - -[[package]] -name = "fabric" -version = "3.2.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "decorator" }, - { name = "deprecated" }, - { name = "invoke" }, - { name = "paramiko" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0d/3f/337f278b70ba339c618a490f6b8033b7006c583bd197a897f12fbc468c51/fabric-3.2.2.tar.gz", hash = "sha256:8783ca42e3b0076f08b26901aac6b9d9b1f19c410074e7accfab902c184ff4a3", size = 183215 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/1f/e99e23ee01847147fa194e8d41cfcf2535a2dbfcb51414c541cadb15c5d7/fabric-3.2.2-py3-none-any.whl", hash = "sha256:91c47c0be68b14936c88b34da8a1f55e5710fd28397dac5d4ff2e21558113a6f", size = 59417 }, -] - -[[package]] -name = "frozenlist" -version = "1.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8f/ed/0f4cec13a93c02c47ec32d81d11c0c1efbadf4a471e3f3ce7cad366cbbd3/frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", size = 39930 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/79/73/fa6d1a96ab7fd6e6d1c3500700963eab46813847f01ef0ccbaa726181dd5/frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", size = 94026 }, - { url = "https://files.pythonhosted.org/packages/ab/04/ea8bf62c8868b8eada363f20ff1b647cf2e93377a7b284d36062d21d81d1/frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", size = 54150 }, - { url = "https://files.pythonhosted.org/packages/d0/9a/8e479b482a6f2070b26bda572c5e6889bb3ba48977e81beea35b5ae13ece/frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", size = 51927 }, - { url = "https://files.pythonhosted.org/packages/e3/12/2aad87deb08a4e7ccfb33600871bbe8f0e08cb6d8224371387f3303654d7/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a", size = 282647 }, - { url = "https://files.pythonhosted.org/packages/77/f2/07f06b05d8a427ea0060a9cef6e63405ea9e0d761846b95ef3fb3be57111/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a", size = 289052 }, - { url = "https://files.pythonhosted.org/packages/bd/9f/8bf45a2f1cd4aa401acd271b077989c9267ae8463e7c8b1eb0d3f561b65e/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee", size = 291719 }, - { url = "https://files.pythonhosted.org/packages/41/d1/1f20fd05a6c42d3868709b7604c9f15538a29e4f734c694c6bcfc3d3b935/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6", size = 267433 }, - { url = "https://files.pythonhosted.org/packages/af/f2/64b73a9bb86f5a89fb55450e97cd5c1f84a862d4ff90d9fd1a73ab0f64a5/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", size = 283591 }, - { url = "https://files.pythonhosted.org/packages/29/e2/ffbb1fae55a791fd6c2938dd9ea779509c977435ba3940b9f2e8dc9d5316/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9", size = 273249 }, - { url = "https://files.pythonhosted.org/packages/2e/6e/008136a30798bb63618a114b9321b5971172a5abddff44a100c7edc5ad4f/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039", size = 271075 }, - { url = "https://files.pythonhosted.org/packages/ae/f0/4e71e54a026b06724cec9b6c54f0b13a4e9e298cc8db0f82ec70e151f5ce/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784", size = 285398 }, - { url = "https://files.pythonhosted.org/packages/4d/36/70ec246851478b1c0b59f11ef8ade9c482ff447c1363c2bd5fad45098b12/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631", size = 294445 }, - { url = "https://files.pythonhosted.org/packages/37/e0/47f87544055b3349b633a03c4d94b405956cf2437f4ab46d0928b74b7526/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f", size = 280569 }, - { url = "https://files.pythonhosted.org/packages/f9/7c/490133c160fb6b84ed374c266f42800e33b50c3bbab1652764e6e1fc498a/frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8", size = 44721 }, - { url = "https://files.pythonhosted.org/packages/b1/56/4e45136ffc6bdbfa68c29ca56ef53783ef4c2fd395f7cbf99a2624aa9aaa/frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f", size = 51329 }, - { url = "https://files.pythonhosted.org/packages/da/3b/915f0bca8a7ea04483622e84a9bd90033bab54bdf485479556c74fd5eaf5/frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953", size = 91538 }, - { url = "https://files.pythonhosted.org/packages/c7/d1/a7c98aad7e44afe5306a2b068434a5830f1470675f0e715abb86eb15f15b/frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0", size = 52849 }, - { url = "https://files.pythonhosted.org/packages/3a/c8/76f23bf9ab15d5f760eb48701909645f686f9c64fbb8982674c241fbef14/frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2", size = 50583 }, - { url = "https://files.pythonhosted.org/packages/1f/22/462a3dd093d11df623179d7754a3b3269de3b42de2808cddef50ee0f4f48/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f", size = 265636 }, - { url = "https://files.pythonhosted.org/packages/80/cf/e075e407fc2ae7328155a1cd7e22f932773c8073c1fc78016607d19cc3e5/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608", size = 270214 }, - { url = "https://files.pythonhosted.org/packages/a1/58/0642d061d5de779f39c50cbb00df49682832923f3d2ebfb0fedf02d05f7f/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b", size = 273905 }, - { url = "https://files.pythonhosted.org/packages/ab/66/3fe0f5f8f2add5b4ab7aa4e199f767fd3b55da26e3ca4ce2cc36698e50c4/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840", size = 250542 }, - { url = "https://files.pythonhosted.org/packages/f6/b8/260791bde9198c87a465224e0e2bb62c4e716f5d198fc3a1dacc4895dbd1/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439", size = 267026 }, - { url = "https://files.pythonhosted.org/packages/2e/a4/3d24f88c527f08f8d44ade24eaee83b2627793fa62fa07cbb7ff7a2f7d42/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de", size = 257690 }, - { url = "https://files.pythonhosted.org/packages/de/9a/d311d660420b2beeff3459b6626f2ab4fb236d07afbdac034a4371fe696e/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641", size = 253893 }, - { url = "https://files.pythonhosted.org/packages/c6/23/e491aadc25b56eabd0f18c53bb19f3cdc6de30b2129ee0bc39cd387cd560/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e", size = 267006 }, - { url = "https://files.pythonhosted.org/packages/08/c4/ab918ce636a35fb974d13d666dcbe03969592aeca6c3ab3835acff01f79c/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9", size = 276157 }, - { url = "https://files.pythonhosted.org/packages/c0/29/3b7a0bbbbe5a34833ba26f686aabfe982924adbdcafdc294a7a129c31688/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03", size = 264642 }, - { url = "https://files.pythonhosted.org/packages/ab/42/0595b3dbffc2e82d7fe658c12d5a5bafcd7516c6bf2d1d1feb5387caa9c1/frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c", size = 44914 }, - { url = "https://files.pythonhosted.org/packages/17/c4/b7db1206a3fea44bf3b838ca61deb6f74424a8a5db1dd53ecb21da669be6/frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28", size = 51167 }, - { url = "https://files.pythonhosted.org/packages/c6/c8/a5be5b7550c10858fcf9b0ea054baccab474da77d37f1e828ce043a3a5d4/frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", size = 11901 }, -] - -[[package]] -name = "grpcio" -version = "1.67.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/53/d9282a66a5db45981499190b77790570617a604a38f3d103d0400974aeb5/grpcio-1.67.1.tar.gz", hash = "sha256:3dc2ed4cabea4dc14d5e708c2b426205956077cc5de419b4d4079315017e9732", size = 12580022 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/25/6f95bd18d5f506364379eabc0d5874873cc7dbdaf0757df8d1e82bc07a88/grpcio-1.67.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:267d1745894200e4c604958da5f856da6293f063327cb049a51fe67348e4f953", size = 5089809 }, - { url = "https://files.pythonhosted.org/packages/10/3f/d79e32e5d0354be33a12db2267c66d3cfeff700dd5ccdd09fd44a3ff4fb6/grpcio-1.67.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:85f69fdc1d28ce7cff8de3f9c67db2b0ca9ba4449644488c1e0303c146135ddb", size = 10981985 }, - { url = "https://files.pythonhosted.org/packages/21/f2/36fbc14b3542e3a1c20fb98bd60c4732c55a44e374a4eb68f91f28f14aab/grpcio-1.67.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:f26b0b547eb8d00e195274cdfc63ce64c8fc2d3e2d00b12bf468ece41a0423a0", size = 5588770 }, - { url = "https://files.pythonhosted.org/packages/0d/af/bbc1305df60c4e65de8c12820a942b5e37f9cf684ef5e49a63fbb1476a73/grpcio-1.67.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4422581cdc628f77302270ff839a44f4c24fdc57887dc2a45b7e53d8fc2376af", size = 6214476 }, - { url = "https://files.pythonhosted.org/packages/92/cf/1d4c3e93efa93223e06a5c83ac27e32935f998bc368e276ef858b8883154/grpcio-1.67.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d7616d2ded471231c701489190379e0c311ee0a6c756f3c03e6a62b95a7146e", size = 5850129 }, - { url = "https://files.pythonhosted.org/packages/ae/ca/26195b66cb253ac4d5ef59846e354d335c9581dba891624011da0e95d67b/grpcio-1.67.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8a00efecde9d6fcc3ab00c13f816313c040a28450e5e25739c24f432fc6d3c75", size = 6568489 }, - { url = "https://files.pythonhosted.org/packages/d1/94/16550ad6b3f13b96f0856ee5dfc2554efac28539ee84a51d7b14526da985/grpcio-1.67.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:699e964923b70f3101393710793289e42845791ea07565654ada0969522d0a38", size = 6149369 }, - { url = "https://files.pythonhosted.org/packages/33/0d/4c3b2587e8ad7f121b597329e6c2620374fccbc2e4e1aa3c73ccc670fde4/grpcio-1.67.1-cp312-cp312-win32.whl", hash = "sha256:4e7b904484a634a0fff132958dabdb10d63e0927398273917da3ee103e8d1f78", size = 3599176 }, - { url = "https://files.pythonhosted.org/packages/7d/36/0c03e2d80db69e2472cf81c6123aa7d14741de7cf790117291a703ae6ae1/grpcio-1.67.1-cp312-cp312-win_amd64.whl", hash = "sha256:5721e66a594a6c4204458004852719b38f3d5522082be9061d6510b455c90afc", size = 4346574 }, - { url = "https://files.pythonhosted.org/packages/12/d2/2f032b7a153c7723ea3dea08bffa4bcaca9e0e5bdf643ce565b76da87461/grpcio-1.67.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:aa0162e56fd10a5547fac8774c4899fc3e18c1aa4a4759d0ce2cd00d3696ea6b", size = 5091487 }, - { url = "https://files.pythonhosted.org/packages/d0/ae/ea2ff6bd2475a082eb97db1104a903cf5fc57c88c87c10b3c3f41a184fc0/grpcio-1.67.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:beee96c8c0b1a75d556fe57b92b58b4347c77a65781ee2ac749d550f2a365dc1", size = 10943530 }, - { url = "https://files.pythonhosted.org/packages/07/62/646be83d1a78edf8d69b56647327c9afc223e3140a744c59b25fbb279c3b/grpcio-1.67.1-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:a93deda571a1bf94ec1f6fcda2872dad3ae538700d94dc283c672a3b508ba3af", size = 5589079 }, - { url = "https://files.pythonhosted.org/packages/d0/25/71513d0a1b2072ce80d7f5909a93596b7ed10348b2ea4fdcbad23f6017bf/grpcio-1.67.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e6f255980afef598a9e64a24efce87b625e3e3c80a45162d111a461a9f92955", size = 6213542 }, - { url = "https://files.pythonhosted.org/packages/76/9a/d21236297111052dcb5dc85cd77dc7bf25ba67a0f55ae028b2af19a704bc/grpcio-1.67.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e838cad2176ebd5d4a8bb03955138d6589ce9e2ce5d51c3ada34396dbd2dba8", size = 5850211 }, - { url = "https://files.pythonhosted.org/packages/2d/fe/70b1da9037f5055be14f359026c238821b9bcf6ca38a8d760f59a589aacd/grpcio-1.67.1-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:a6703916c43b1d468d0756c8077b12017a9fcb6a1ef13faf49e67d20d7ebda62", size = 6572129 }, - { url = "https://files.pythonhosted.org/packages/74/0d/7df509a2cd2a54814598caf2fb759f3e0b93764431ff410f2175a6efb9e4/grpcio-1.67.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:917e8d8994eed1d86b907ba2a61b9f0aef27a2155bca6cbb322430fc7135b7bb", size = 6149819 }, - { url = "https://files.pythonhosted.org/packages/0a/08/bc3b0155600898fd10f16b79054e1cca6cb644fa3c250c0fe59385df5e6f/grpcio-1.67.1-cp313-cp313-win32.whl", hash = "sha256:e279330bef1744040db8fc432becc8a727b84f456ab62b744d3fdb83f327e121", size = 3596561 }, - { url = "https://files.pythonhosted.org/packages/5a/96/44759eca966720d0f3e1b105c43f8ad4590c97bf8eb3cd489656e9590baa/grpcio-1.67.1-cp313-cp313-win_amd64.whl", hash = "sha256:fa0c739ad8b1996bd24823950e3cb5152ae91fca1c09cc791190bf1627ffefba", size = 4346042 }, -] - -[[package]] -name = "h11" -version = "0.14.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, -] - -[[package]] -name = "httpcore" -version = "1.0.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "h11" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b6/44/ed0fa6a17845fb033bd885c03e842f08c1b9406c86a2e60ac1ae1b9206a6/httpcore-1.0.6.tar.gz", hash = "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f", size = 85180 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/06/89/b161908e2f51be56568184aeb4a880fd287178d176fd1c860d2217f41106/httpcore-1.0.6-py3-none-any.whl", hash = "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f", size = 78011 }, -] - -[[package]] -name = "httpx" -version = "0.27.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "certifi" }, - { name = "httpcore" }, - { name = "idna" }, - { name = "sniffio" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/78/82/08f8c936781f67d9e6b9eeb8a0c8b4e406136ea4c3d1f89a5db71d42e0e6/httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2", size = 144189 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/56/95/9377bcb415797e44274b51d46e3249eba641711cf3348050f76ee7b15ffc/httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0", size = 76395 }, -] - -[[package]] -name = "idna" -version = "3.10" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, -] - -[[package]] -name = "iniconfig" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, -] - -[[package]] -name = "invoke" -version = "2.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/42/127e6d792884ab860defc3f4d80a8f9812e48ace584ffc5a346de58cdc6c/invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5", size = 299835 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/66/7f8c48009c72d73bc6bbe6eb87ac838d6a526146f7dab14af671121eb379/invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820", size = 160274 }, -] - -[[package]] -name = "jumpstarter" -version = "0.0.4.dev62+g36d1217" -source = { git = "https://github.com/jumpstarter-dev/jumpstarter.git#36d1217db1be316faa449df781a8c2d3c37a3f18" } -dependencies = [ - { name = "aiohttp" }, - { name = "anyio" }, - { name = "click" }, - { name = "fabric" }, - { name = "grpcio" }, - { name = "httpx" }, - { name = "opendal" }, - { name = "pexpect" }, - { name = "protobuf" }, - { name = "pydantic" }, - { name = "pyserial" }, - { name = "pyyaml" }, - { name = "tqdm" }, - { name = "wsproto" }, -] - -[[package]] -name = "jumpstarter-driver-http" -version = "0.1.0" -source = { editable = "." } -dependencies = [ - { name = "anyio" }, - { name = "jumpstarter" }, -] - -[package.dev-dependencies] -dev = [ - { name = "pytest" }, - { name = "pytest-asyncio" }, - { name = "pytest-cov" }, - { name = "ruff" }, -] - -[package.metadata] -requires-dist = [ - { name = "anyio", specifier = ">=4.6.2.post1" }, - { name = "jumpstarter", git = "https://github.com/jumpstarter-dev/jumpstarter.git" }, -] - -[package.metadata.requires-dev] -dev = [ - { name = "pytest", specifier = ">=8.3.3" }, - { name = "pytest-asyncio", specifier = ">=0.24.0" }, - { name = "pytest-cov", specifier = ">=6.0.0" }, - { name = "ruff", specifier = ">=0.7.1" }, -] - -[[package]] -name = "multidict" -version = "6.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/be/504b89a5e9ca731cd47487e91c469064f8ae5af93b7259758dcfc2b9c848/multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", size = 64002 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/16/92057c74ba3b96d5e211b553895cd6dc7cc4d1e43d9ab8fafc727681ef71/multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", size = 48713 }, - { url = "https://files.pythonhosted.org/packages/94/3d/37d1b8893ae79716179540b89fc6a0ee56b4a65fcc0d63535c6f5d96f217/multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", size = 29516 }, - { url = "https://files.pythonhosted.org/packages/a2/12/adb6b3200c363062f805275b4c1e656be2b3681aada66c80129932ff0bae/multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", size = 29557 }, - { url = "https://files.pythonhosted.org/packages/47/e9/604bb05e6e5bce1e6a5cf80a474e0f072e80d8ac105f1b994a53e0b28c42/multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", size = 130170 }, - { url = "https://files.pythonhosted.org/packages/7e/13/9efa50801785eccbf7086b3c83b71a4fb501a4d43549c2f2f80b8787d69f/multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", size = 134836 }, - { url = "https://files.pythonhosted.org/packages/bf/0f/93808b765192780d117814a6dfcc2e75de6dcc610009ad408b8814dca3ba/multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", size = 133475 }, - { url = "https://files.pythonhosted.org/packages/d3/c8/529101d7176fe7dfe1d99604e48d69c5dfdcadb4f06561f465c8ef12b4df/multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", size = 131049 }, - { url = "https://files.pythonhosted.org/packages/ca/0c/fc85b439014d5a58063e19c3a158a889deec399d47b5269a0f3b6a2e28bc/multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", size = 120370 }, - { url = "https://files.pythonhosted.org/packages/db/46/d4416eb20176492d2258fbd47b4abe729ff3b6e9c829ea4236f93c865089/multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", size = 125178 }, - { url = "https://files.pythonhosted.org/packages/5b/46/73697ad7ec521df7de5531a32780bbfd908ded0643cbe457f981a701457c/multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", size = 119567 }, - { url = "https://files.pythonhosted.org/packages/cd/ed/51f060e2cb0e7635329fa6ff930aa5cffa17f4c7f5c6c3ddc3500708e2f2/multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", size = 129822 }, - { url = "https://files.pythonhosted.org/packages/df/9e/ee7d1954b1331da3eddea0c4e08d9142da5f14b1321c7301f5014f49d492/multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", size = 128656 }, - { url = "https://files.pythonhosted.org/packages/77/00/8538f11e3356b5d95fa4b024aa566cde7a38aa7a5f08f4912b32a037c5dc/multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", size = 125360 }, - { url = "https://files.pythonhosted.org/packages/be/05/5d334c1f2462d43fec2363cd00b1c44c93a78c3925d952e9a71caf662e96/multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", size = 26382 }, - { url = "https://files.pythonhosted.org/packages/a3/bf/f332a13486b1ed0496d624bcc7e8357bb8053823e8cd4b9a18edc1d97e73/multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", size = 28529 }, - { url = "https://files.pythonhosted.org/packages/22/67/1c7c0f39fe069aa4e5d794f323be24bf4d33d62d2a348acdb7991f8f30db/multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", size = 48771 }, - { url = "https://files.pythonhosted.org/packages/3c/25/c186ee7b212bdf0df2519eacfb1981a017bda34392c67542c274651daf23/multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", size = 29533 }, - { url = "https://files.pythonhosted.org/packages/67/5e/04575fd837e0958e324ca035b339cea174554f6f641d3fb2b4f2e7ff44a2/multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", size = 29595 }, - { url = "https://files.pythonhosted.org/packages/d3/b2/e56388f86663810c07cfe4a3c3d87227f3811eeb2d08450b9e5d19d78876/multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", size = 130094 }, - { url = "https://files.pythonhosted.org/packages/6c/ee/30ae9b4186a644d284543d55d491fbd4239b015d36b23fea43b4c94f7052/multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", size = 134876 }, - { url = "https://files.pythonhosted.org/packages/84/c7/70461c13ba8ce3c779503c70ec9d0345ae84de04521c1f45a04d5f48943d/multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", size = 133500 }, - { url = "https://files.pythonhosted.org/packages/4a/9f/002af221253f10f99959561123fae676148dd730e2daa2cd053846a58507/multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", size = 131099 }, - { url = "https://files.pythonhosted.org/packages/82/42/d1c7a7301d52af79d88548a97e297f9d99c961ad76bbe6f67442bb77f097/multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", size = 120403 }, - { url = "https://files.pythonhosted.org/packages/68/f3/471985c2c7ac707547553e8f37cff5158030d36bdec4414cb825fbaa5327/multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", size = 125348 }, - { url = "https://files.pythonhosted.org/packages/67/2c/e6df05c77e0e433c214ec1d21ddd203d9a4770a1f2866a8ca40a545869a0/multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", size = 119673 }, - { url = "https://files.pythonhosted.org/packages/c5/cd/bc8608fff06239c9fb333f9db7743a1b2eafe98c2666c9a196e867a3a0a4/multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", size = 129927 }, - { url = "https://files.pythonhosted.org/packages/44/8e/281b69b7bc84fc963a44dc6e0bbcc7150e517b91df368a27834299a526ac/multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", size = 128711 }, - { url = "https://files.pythonhosted.org/packages/12/a4/63e7cd38ed29dd9f1881d5119f272c898ca92536cdb53ffe0843197f6c85/multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", size = 125519 }, - { url = "https://files.pythonhosted.org/packages/38/e0/4f5855037a72cd8a7a2f60a3952d9aa45feedb37ae7831642102604e8a37/multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", size = 26426 }, - { url = "https://files.pythonhosted.org/packages/7e/a5/17ee3a4db1e310b7405f5d25834460073a8ccd86198ce044dfaf69eac073/multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", size = 28531 }, - { url = "https://files.pythonhosted.org/packages/99/b7/b9e70fde2c0f0c9af4cc5277782a89b66d35948ea3369ec9f598358c3ac5/multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", size = 10051 }, -] - -[[package]] -name = "opendal" -version = "0.45.11" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b7/c2/9bff01d8e59c1b168d3ce0c642bbe61841118a330e10d1d4cbf8a0ffc09c/opendal-0.45.11.tar.gz", hash = "sha256:caad0dc4ce3d59d52b224d49f1edaf5efb65bbd18f5476957130f41944dabb33", size = 739998 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/dc/3ddc7f0eb393cd1c5c7b700fd2d9557cf5dd283ab98ab0a9093446c3011d/opendal-0.45.11-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:31cb8fff90775c72dd55e7ce12df23784a19b7b8baaa41dcbc1a2e983f3e3e6b", size = 29365212 }, - { url = "https://files.pythonhosted.org/packages/7e/4b/54b50be2ecdcc6353e54d2809add3bb5ae5df982c22ba137c7d7ee4723f9/opendal-0.45.11-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:718b782ff2909ca2599c0de326f0fa613063a2a6b18738d6702844c963536e0b", size = 15800423 }, - { url = "https://files.pythonhosted.org/packages/cd/9c/b92d6bf214f039aa43ec8a35c1a03eb422ea7484088aed3e55fd23626a4d/opendal-0.45.11-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad22109a3ad837b34ee181222c5c5cd53888f57a57253259024357f668e8224a", size = 15459912 }, - { url = "https://files.pythonhosted.org/packages/3d/61/a9dfe04443585967e313c68083644bffcb485cfc00f639845ff99e5b56c4/opendal-0.45.11-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e984f317ab871dc75b65028ec0c1451cc6faa41d105443b749d7d6a3440cd31d", size = 16334398 }, - { url = "https://files.pythonhosted.org/packages/f8/68/80b17a403dcddd8be342b348cb007ef2c151d4fb7fa9f9c71fe354a5ac4b/opendal-0.45.11-cp311-abi3-win_amd64.whl", hash = "sha256:9bd4bdac96a6f0d21cc933f0ea11100c0c8be0c157e0d81f138a66a56c8ca789", size = 14395052 }, -] - -[[package]] -name = "packaging" -version = "24.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, -] - -[[package]] -name = "paramiko" -version = "3.5.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "bcrypt" }, - { name = "cryptography" }, - { name = "pynacl" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1b/0f/c00296e36ff7485935b83d466c4f2cf5934b84b0ad14e81796e1d9d3609b/paramiko-3.5.0.tar.gz", hash = "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124", size = 1704305 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/66/14b2c030fcce69cba482d205c2d1462ca5c77303a263260dcb1192801c85/paramiko-3.5.0-py3-none-any.whl", hash = "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9", size = 227143 }, -] - -[[package]] -name = "pexpect" -version = "4.9.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ptyprocess" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772 }, -] - -[[package]] -name = "pluggy" -version = "1.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, -] - -[[package]] -name = "propcache" -version = "0.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a9/4d/5e5a60b78dbc1d464f8a7bbaeb30957257afdc8512cbb9dfd5659304f5cd/propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70", size = 40951 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/46/a41ca1097769fc548fc9216ec4c1471b772cc39720eb47ed7e38ef0006a9/propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2", size = 80800 }, - { url = "https://files.pythonhosted.org/packages/75/4f/93df46aab9cc473498ff56be39b5f6ee1e33529223d7a4d8c0a6101a9ba2/propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7", size = 46443 }, - { url = "https://files.pythonhosted.org/packages/0b/17/308acc6aee65d0f9a8375e36c4807ac6605d1f38074b1581bd4042b9fb37/propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8", size = 45676 }, - { url = "https://files.pythonhosted.org/packages/65/44/626599d2854d6c1d4530b9a05e7ff2ee22b790358334b475ed7c89f7d625/propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793", size = 246191 }, - { url = "https://files.pythonhosted.org/packages/f2/df/5d996d7cb18df076debae7d76ac3da085c0575a9f2be6b1f707fe227b54c/propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09", size = 251791 }, - { url = "https://files.pythonhosted.org/packages/2e/6d/9f91e5dde8b1f662f6dd4dff36098ed22a1ef4e08e1316f05f4758f1576c/propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89", size = 253434 }, - { url = "https://files.pythonhosted.org/packages/3c/e9/1b54b7e26f50b3e0497cd13d3483d781d284452c2c50dd2a615a92a087a3/propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e", size = 248150 }, - { url = "https://files.pythonhosted.org/packages/a7/ef/a35bf191c8038fe3ce9a414b907371c81d102384eda5dbafe6f4dce0cf9b/propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9", size = 233568 }, - { url = "https://files.pythonhosted.org/packages/97/d9/d00bb9277a9165a5e6d60f2142cd1a38a750045c9c12e47ae087f686d781/propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4", size = 229874 }, - { url = "https://files.pythonhosted.org/packages/8e/78/c123cf22469bdc4b18efb78893e69c70a8b16de88e6160b69ca6bdd88b5d/propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c", size = 225857 }, - { url = "https://files.pythonhosted.org/packages/31/1b/fd6b2f1f36d028820d35475be78859d8c89c8f091ad30e377ac49fd66359/propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887", size = 227604 }, - { url = "https://files.pythonhosted.org/packages/99/36/b07be976edf77a07233ba712e53262937625af02154353171716894a86a6/propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57", size = 238430 }, - { url = "https://files.pythonhosted.org/packages/0d/64/5822f496c9010e3966e934a011ac08cac8734561842bc7c1f65586e0683c/propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23", size = 244814 }, - { url = "https://files.pythonhosted.org/packages/fd/bd/8657918a35d50b18a9e4d78a5df7b6c82a637a311ab20851eef4326305c1/propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348", size = 235922 }, - { url = "https://files.pythonhosted.org/packages/a8/6f/ec0095e1647b4727db945213a9f395b1103c442ef65e54c62e92a72a3f75/propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5", size = 40177 }, - { url = "https://files.pythonhosted.org/packages/20/a2/bd0896fdc4f4c1db46d9bc361c8c79a9bf08ccc08ba054a98e38e7ba1557/propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3", size = 44446 }, - { url = "https://files.pythonhosted.org/packages/a8/a7/5f37b69197d4f558bfef5b4bceaff7c43cc9b51adf5bd75e9081d7ea80e4/propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7", size = 78120 }, - { url = "https://files.pythonhosted.org/packages/c8/cd/48ab2b30a6b353ecb95a244915f85756d74f815862eb2ecc7a518d565b48/propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763", size = 45127 }, - { url = "https://files.pythonhosted.org/packages/a5/ba/0a1ef94a3412aab057bd996ed5f0ac7458be5bf469e85c70fa9ceb43290b/propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d", size = 44419 }, - { url = "https://files.pythonhosted.org/packages/b4/6c/ca70bee4f22fa99eacd04f4d2f1699be9d13538ccf22b3169a61c60a27fa/propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a", size = 229611 }, - { url = "https://files.pythonhosted.org/packages/19/70/47b872a263e8511ca33718d96a10c17d3c853aefadeb86dc26e8421184b9/propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b", size = 234005 }, - { url = "https://files.pythonhosted.org/packages/4f/be/3b0ab8c84a22e4a3224719099c1229ddfdd8a6a1558cf75cb55ee1e35c25/propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb", size = 237270 }, - { url = "https://files.pythonhosted.org/packages/04/d8/f071bb000d4b8f851d312c3c75701e586b3f643fe14a2e3409b1b9ab3936/propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf", size = 231877 }, - { url = "https://files.pythonhosted.org/packages/93/e7/57a035a1359e542bbb0a7df95aad6b9871ebee6dce2840cb157a415bd1f3/propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2", size = 217848 }, - { url = "https://files.pythonhosted.org/packages/f0/93/d1dea40f112ec183398fb6c42fde340edd7bab202411c4aa1a8289f461b6/propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f", size = 216987 }, - { url = "https://files.pythonhosted.org/packages/62/4c/877340871251145d3522c2b5d25c16a1690ad655fbab7bb9ece6b117e39f/propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136", size = 212451 }, - { url = "https://files.pythonhosted.org/packages/7c/bb/a91b72efeeb42906ef58ccf0cdb87947b54d7475fee3c93425d732f16a61/propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325", size = 212879 }, - { url = "https://files.pythonhosted.org/packages/9b/7f/ee7fea8faac57b3ec5d91ff47470c6c5d40d7f15d0b1fccac806348fa59e/propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44", size = 222288 }, - { url = "https://files.pythonhosted.org/packages/ff/d7/acd67901c43d2e6b20a7a973d9d5fd543c6e277af29b1eb0e1f7bd7ca7d2/propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83", size = 228257 }, - { url = "https://files.pythonhosted.org/packages/8d/6f/6272ecc7a8daad1d0754cfc6c8846076a8cb13f810005c79b15ce0ef0cf2/propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544", size = 221075 }, - { url = "https://files.pythonhosted.org/packages/7c/bd/c7a6a719a6b3dd8b3aeadb3675b5783983529e4a3185946aa444d3e078f6/propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032", size = 39654 }, - { url = "https://files.pythonhosted.org/packages/88/e7/0eef39eff84fa3e001b44de0bd41c7c0e3432e7648ffd3d64955910f002d/propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e", size = 43705 }, - { url = "https://files.pythonhosted.org/packages/3d/b6/e6d98278f2d49b22b4d033c9f792eda783b9ab2094b041f013fc69bcde87/propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036", size = 11603 }, -] - -[[package]] -name = "protobuf" -version = "5.28.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/74/6e/e69eb906fddcb38f8530a12f4b410699972ab7ced4e21524ece9d546ac27/protobuf-5.28.3.tar.gz", hash = "sha256:64badbc49180a5e401f373f9ce7ab1d18b63f7dd4a9cdc43c92b9f0b481cef7b", size = 422479 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/c5/05163fad52d7c43e124a545f1372d18266db36036377ad29de4271134a6a/protobuf-5.28.3-cp310-abi3-win32.whl", hash = "sha256:0c4eec6f987338617072592b97943fdbe30d019c56126493111cf24344c1cc24", size = 419624 }, - { url = "https://files.pythonhosted.org/packages/9c/4c/4563ebe001ff30dca9d7ed12e471fa098d9759712980cde1fd03a3a44fb7/protobuf-5.28.3-cp310-abi3-win_amd64.whl", hash = "sha256:91fba8f445723fcf400fdbe9ca796b19d3b1242cd873907979b9ed71e4afe868", size = 431464 }, - { url = "https://files.pythonhosted.org/packages/1c/f2/baf397f3dd1d3e4af7e3f5a0382b868d25ac068eefe1ebde05132333436c/protobuf-5.28.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a3f6857551e53ce35e60b403b8a27b0295f7d6eb63d10484f12bc6879c715687", size = 414743 }, - { url = "https://files.pythonhosted.org/packages/85/50/cd61a358ba1601f40e7d38bcfba22e053f40ef2c50d55b55926aecc8fec7/protobuf-5.28.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:3fa2de6b8b29d12c61911505d893afe7320ce7ccba4df913e2971461fa36d584", size = 316511 }, - { url = "https://files.pythonhosted.org/packages/5d/ae/3257b09328c0b4e59535e497b0c7537d4954038bdd53a2f0d2f49d15a7c4/protobuf-5.28.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:712319fbdddb46f21abb66cd33cb9e491a5763b2febd8f228251add221981135", size = 316624 }, - { url = "https://files.pythonhosted.org/packages/ad/c3/2377c159e28ea89a91cf1ca223f827ae8deccb2c9c401e5ca233cd73002f/protobuf-5.28.3-py3-none-any.whl", hash = "sha256:cee1757663fa32a1ee673434fcf3bf24dd54763c79690201208bafec62f19eed", size = 169511 }, -] - -[[package]] -name = "ptyprocess" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993 }, -] - -[[package]] -name = "pycparser" -version = "2.22" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 }, -] - -[[package]] -name = "pydantic" -version = "2.9.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "annotated-types" }, - { name = "pydantic-core" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a9/b7/d9e3f12af310e1120c21603644a1cd86f59060e040ec5c3a80b8f05fae30/pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f", size = 769917 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/df/e4/ba44652d562cbf0bf320e0f3810206149c8a4e99cdbf66da82e97ab53a15/pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12", size = 434928 }, -] - -[[package]] -name = "pydantic-core" -version = "2.23.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e2/aa/6b6a9b9f8537b872f552ddd46dd3da230367754b6f707b8e1e963f515ea3/pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863", size = 402156 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/74/7b/8e315f80666194b354966ec84b7d567da77ad927ed6323db4006cf915f3f/pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231", size = 1856459 }, - { url = "https://files.pythonhosted.org/packages/14/de/866bdce10ed808323d437612aca1ec9971b981e1c52e5e42ad9b8e17a6f6/pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee", size = 1770007 }, - { url = "https://files.pythonhosted.org/packages/dc/69/8edd5c3cd48bb833a3f7ef9b81d7666ccddd3c9a635225214e044b6e8281/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87", size = 1790245 }, - { url = "https://files.pythonhosted.org/packages/80/33/9c24334e3af796ce80d2274940aae38dd4e5676298b4398eff103a79e02d/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8", size = 1801260 }, - { url = "https://files.pythonhosted.org/packages/a5/6f/e9567fd90104b79b101ca9d120219644d3314962caa7948dd8b965e9f83e/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327", size = 1996872 }, - { url = "https://files.pythonhosted.org/packages/2d/ad/b5f0fe9e6cfee915dd144edbd10b6e9c9c9c9d7a56b69256d124b8ac682e/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2", size = 2661617 }, - { url = "https://files.pythonhosted.org/packages/06/c8/7d4b708f8d05a5cbfda3243aad468052c6e99de7d0937c9146c24d9f12e9/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36", size = 2071831 }, - { url = "https://files.pythonhosted.org/packages/89/4d/3079d00c47f22c9a9a8220db088b309ad6e600a73d7a69473e3a8e5e3ea3/pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126", size = 1917453 }, - { url = "https://files.pythonhosted.org/packages/e9/88/9df5b7ce880a4703fcc2d76c8c2d8eb9f861f79d0c56f4b8f5f2607ccec8/pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e", size = 1968793 }, - { url = "https://files.pythonhosted.org/packages/e3/b9/41f7efe80f6ce2ed3ee3c2dcfe10ab7adc1172f778cc9659509a79518c43/pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24", size = 2116872 }, - { url = "https://files.pythonhosted.org/packages/63/08/b59b7a92e03dd25554b0436554bf23e7c29abae7cce4b1c459cd92746811/pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84", size = 1738535 }, - { url = "https://files.pythonhosted.org/packages/88/8d/479293e4d39ab409747926eec4329de5b7129beaedc3786eca070605d07f/pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9", size = 1917992 }, - { url = "https://files.pythonhosted.org/packages/ad/ef/16ee2df472bf0e419b6bc68c05bf0145c49247a1095e85cee1463c6a44a1/pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc", size = 1856143 }, - { url = "https://files.pythonhosted.org/packages/da/fa/bc3dbb83605669a34a93308e297ab22be82dfb9dcf88c6cf4b4f264e0a42/pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd", size = 1770063 }, - { url = "https://files.pythonhosted.org/packages/4e/48/e813f3bbd257a712303ebdf55c8dc46f9589ec74b384c9f652597df3288d/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05", size = 1790013 }, - { url = "https://files.pythonhosted.org/packages/b4/e0/56eda3a37929a1d297fcab1966db8c339023bcca0b64c5a84896db3fcc5c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d", size = 1801077 }, - { url = "https://files.pythonhosted.org/packages/04/be/5e49376769bfbf82486da6c5c1683b891809365c20d7c7e52792ce4c71f3/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510", size = 1996782 }, - { url = "https://files.pythonhosted.org/packages/bc/24/e3ee6c04f1d58cc15f37bcc62f32c7478ff55142b7b3e6d42ea374ea427c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6", size = 2661375 }, - { url = "https://files.pythonhosted.org/packages/c1/f8/11a9006de4e89d016b8de74ebb1db727dc100608bb1e6bbe9d56a3cbbcce/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b", size = 2071635 }, - { url = "https://files.pythonhosted.org/packages/7c/45/bdce5779b59f468bdf262a5bc9eecbae87f271c51aef628d8c073b4b4b4c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327", size = 1916994 }, - { url = "https://files.pythonhosted.org/packages/d8/fa/c648308fe711ee1f88192cad6026ab4f925396d1293e8356de7e55be89b5/pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6", size = 1968877 }, - { url = "https://files.pythonhosted.org/packages/16/16/b805c74b35607d24d37103007f899abc4880923b04929547ae68d478b7f4/pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f", size = 2116814 }, - { url = "https://files.pythonhosted.org/packages/d1/58/5305e723d9fcdf1c5a655e6a4cc2a07128bf644ff4b1d98daf7a9dbf57da/pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769", size = 1738360 }, - { url = "https://files.pythonhosted.org/packages/a5/ae/e14b0ff8b3f48e02394d8acd911376b7b66e164535687ef7dc24ea03072f/pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5", size = 1919411 }, -] - -[[package]] -name = "pynacl" -version = "1.5.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cffi" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a7/22/27582568be639dfe22ddb3902225f91f2f17ceff88ce80e4db396c8986da/PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba", size = 3392854 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1", size = 349920 }, - { url = "https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92", size = 601722 }, - { url = "https://files.pythonhosted.org/packages/5d/70/87a065c37cca41a75f2ce113a5a2c2aa7533be648b184ade58971b5f7ccc/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394", size = 680087 }, - { url = "https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d", size = 856678 }, - { url = "https://files.pythonhosted.org/packages/66/28/ca86676b69bf9f90e710571b67450508484388bfce09acf8a46f0b8c785f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858", size = 1133660 }, - { url = "https://files.pythonhosted.org/packages/3d/85/c262db650e86812585e2bc59e497a8f59948a005325a11bbbc9ecd3fe26b/PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b", size = 663824 }, - { url = "https://files.pythonhosted.org/packages/fd/1a/cc308a884bd299b651f1633acb978e8596c71c33ca85e9dc9fa33a5399b9/PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff", size = 1117912 }, - { url = "https://files.pythonhosted.org/packages/25/2d/b7df6ddb0c2a33afdb358f8af6ea3b8c4d1196ca45497dd37a56f0c122be/PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543", size = 204624 }, - { url = "https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93", size = 212141 }, -] - -[[package]] -name = "pyserial" -version = "3.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1e/7d/ae3f0a63f41e4d2f6cb66a5b57197850f919f59e558159a4dd3a818f5082/pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb", size = 159125 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0", size = 90585 }, -] - -[[package]] -name = "pytest" -version = "8.3.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "iniconfig" }, - { name = "packaging" }, - { name = "pluggy" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, -] - -[[package]] -name = "pytest-asyncio" -version = "0.24.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pytest" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/52/6d/c6cf50ce320cf8611df7a1254d86233b3df7cc07f9b5f5cbcb82e08aa534/pytest_asyncio-0.24.0.tar.gz", hash = "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276", size = 49855 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/96/31/6607dab48616902f76885dfcf62c08d929796fc3b2d2318faf9fd54dbed9/pytest_asyncio-0.24.0-py3-none-any.whl", hash = "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b", size = 18024 }, -] - -[[package]] -name = "pytest-cov" -version = "6.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "coverage" }, - { name = "pytest" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 }, -] - -[[package]] -name = "pyyaml" -version = "6.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, - { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, - { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, - { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, - { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, - { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, - { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, - { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, - { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, - { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, - { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, - { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, - { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, - { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, - { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, - { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, - { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, - { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, -] - -[[package]] -name = "ruff" -version = "0.8.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5e/2b/01245f4f3a727d60bebeacd7ee6d22586c7f62380a2597ddb22c2f45d018/ruff-0.8.2.tar.gz", hash = "sha256:b84f4f414dda8ac7f75075c1fa0b905ac0ff25361f42e6d5da681a465e0f78e5", size = 3349020 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/91/29/366be70216dba1731a00a41f2f030822b0c96c7c4f3b2c0cdce15cbace74/ruff-0.8.2-py3-none-linux_armv6l.whl", hash = "sha256:c49ab4da37e7c457105aadfd2725e24305ff9bc908487a9bf8d548c6dad8bb3d", size = 10530649 }, - { url = "https://files.pythonhosted.org/packages/63/82/a733956540bb388f00df5a3e6a02467b16c0e529132625fe44ce4c5fb9c7/ruff-0.8.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ec016beb69ac16be416c435828be702ee694c0d722505f9c1f35e1b9c0cc1bf5", size = 10274069 }, - { url = "https://files.pythonhosted.org/packages/3d/12/0b3aa14d1d71546c988a28e1b412981c1b80c8a1072e977a2f30c595cc4a/ruff-0.8.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f05cdf8d050b30e2ba55c9b09330b51f9f97d36d4673213679b965d25a785f3c", size = 9909400 }, - { url = "https://files.pythonhosted.org/packages/23/08/f9f08cefb7921784c891c4151cce6ed357ff49e84b84978440cffbc87408/ruff-0.8.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60f578c11feb1d3d257b2fb043ddb47501ab4816e7e221fbb0077f0d5d4e7b6f", size = 10766782 }, - { url = "https://files.pythonhosted.org/packages/e4/71/bf50c321ec179aa420c8ec40adac5ae9cc408d4d37283a485b19a2331ceb/ruff-0.8.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cbd5cf9b0ae8f30eebc7b360171bd50f59ab29d39f06a670b3e4501a36ba5897", size = 10286316 }, - { url = "https://files.pythonhosted.org/packages/f2/83/c82688a2a6117539aea0ce63fdf6c08e60fe0202779361223bcd7f40bd74/ruff-0.8.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b402ddee3d777683de60ff76da801fa7e5e8a71038f57ee53e903afbcefdaa58", size = 11338270 }, - { url = "https://files.pythonhosted.org/packages/7f/d7/bc6a45e5a22e627640388e703160afb1d77c572b1d0fda8b4349f334fc66/ruff-0.8.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:705832cd7d85605cb7858d8a13d75993c8f3ef1397b0831289109e953d833d29", size = 12058579 }, - { url = "https://files.pythonhosted.org/packages/da/3b/64150c93946ec851e6f1707ff586bb460ca671581380c919698d6a9267dc/ruff-0.8.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:32096b41aaf7a5cc095fa45b4167b890e4c8d3fd217603f3634c92a541de7248", size = 11615172 }, - { url = "https://files.pythonhosted.org/packages/e4/9e/cf12b697ea83cfe92ec4509ae414dc4c9b38179cc681a497031f0d0d9a8e/ruff-0.8.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e769083da9439508833cfc7c23e351e1809e67f47c50248250ce1ac52c21fb93", size = 12882398 }, - { url = "https://files.pythonhosted.org/packages/a9/27/96d10863accf76a9c97baceac30b0a52d917eb985a8ac058bd4636aeede0/ruff-0.8.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fe716592ae8a376c2673fdfc1f5c0c193a6d0411f90a496863c99cd9e2ae25d", size = 11176094 }, - { url = "https://files.pythonhosted.org/packages/eb/10/cd2fd77d4a4e7f03c29351be0f53278a393186b540b99df68beb5304fddd/ruff-0.8.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:81c148825277e737493242b44c5388a300584d73d5774defa9245aaef55448b0", size = 10771884 }, - { url = "https://files.pythonhosted.org/packages/71/5d/beabb2ff18870fc4add05fa3a69a4cb1b1d2d6f83f3cf3ae5ab0d52f455d/ruff-0.8.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d261d7850c8367704874847d95febc698a950bf061c9475d4a8b7689adc4f7fa", size = 10382535 }, - { url = "https://files.pythonhosted.org/packages/ae/29/6b3fdf3ad3e35b28d87c25a9ff4c8222ad72485ab783936b2b267250d7a7/ruff-0.8.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1ca4e3a87496dc07d2427b7dd7ffa88a1e597c28dad65ae6433ecb9f2e4f022f", size = 10886995 }, - { url = "https://files.pythonhosted.org/packages/e9/dc/859d889b4d9356a1a2cdbc1e4a0dda94052bc5b5300098647e51a58c430b/ruff-0.8.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:729850feed82ef2440aa27946ab39c18cb4a8889c1128a6d589ffa028ddcfc22", size = 11220750 }, - { url = "https://files.pythonhosted.org/packages/0b/08/e8f519f61f1d624264bfd6b8829e4c5f31c3c61193bc3cff1f19dbe7626a/ruff-0.8.2-py3-none-win32.whl", hash = "sha256:ac42caaa0411d6a7d9594363294416e0e48fc1279e1b0e948391695db2b3d5b1", size = 8729396 }, - { url = "https://files.pythonhosted.org/packages/f8/d4/ba1c7ab72aba37a2b71fe48ab95b80546dbad7a7f35ea28cf66fc5cea5f6/ruff-0.8.2-py3-none-win_amd64.whl", hash = "sha256:2aae99ec70abf43372612a838d97bfe77d45146254568d94926e8ed5bbb409ea", size = 9594729 }, - { url = "https://files.pythonhosted.org/packages/23/34/db20e12d3db11b8a2a8874258f0f6d96a9a4d631659d54575840557164c8/ruff-0.8.2-py3-none-win_arm64.whl", hash = "sha256:fb88e2a506b70cfbc2de6fae6681c4f944f7dd5f2fe87233a7233d888bad73e8", size = 9035131 }, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, -] - -[[package]] -name = "tqdm" -version = "4.66.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e9/34/bef135b27fe1864993a5284ad001157ee9b5538e859ac90f5b0e8cc8c9ec/tqdm-4.66.6.tar.gz", hash = "sha256:4bdd694238bef1485ce839d67967ab50af8f9272aab687c0d7702a01da0be090", size = 169533 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/41/73/02342de9c2d20922115f787e101527b831c0cffd2105c946c4a4826bcfd4/tqdm-4.66.6-py3-none-any.whl", hash = "sha256:223e8b5359c2efc4b30555531f09e9f2f3589bcd7fdd389271191031b49b7a63", size = 78326 }, -] - -[[package]] -name = "typing-extensions" -version = "4.12.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, -] - -[[package]] -name = "wrapt" -version = "1.16.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/95/4c/063a912e20bcef7124e0df97282a8af3ff3e4b603ce84c481d6d7346be0a/wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d", size = 53972 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/17/224132494c1e23521868cdd57cd1e903f3b6a7ba6996b7b8f077ff8ac7fe/wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b", size = 37614 }, - { url = "https://files.pythonhosted.org/packages/6a/d7/cfcd73e8f4858079ac59d9db1ec5a1349bc486ae8e9ba55698cc1f4a1dff/wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36", size = 38316 }, - { url = "https://files.pythonhosted.org/packages/7e/79/5ff0a5c54bda5aec75b36453d06be4f83d5cd4932cc84b7cb2b52cee23e2/wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73", size = 86322 }, - { url = "https://files.pythonhosted.org/packages/c4/81/e799bf5d419f422d8712108837c1d9bf6ebe3cb2a81ad94413449543a923/wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809", size = 79055 }, - { url = "https://files.pythonhosted.org/packages/62/62/30ca2405de6a20448ee557ab2cd61ab9c5900be7cbd18a2639db595f0b98/wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b", size = 87291 }, - { url = "https://files.pythonhosted.org/packages/49/4e/5d2f6d7b57fc9956bf06e944eb00463551f7d52fc73ca35cfc4c2cdb7aed/wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81", size = 90374 }, - { url = "https://files.pythonhosted.org/packages/a6/9b/c2c21b44ff5b9bf14a83252a8b973fb84923764ff63db3e6dfc3895cf2e0/wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9", size = 83896 }, - { url = "https://files.pythonhosted.org/packages/14/26/93a9fa02c6f257df54d7570dfe8011995138118d11939a4ecd82cb849613/wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c", size = 91738 }, - { url = "https://files.pythonhosted.org/packages/a2/5b/4660897233eb2c8c4de3dc7cefed114c61bacb3c28327e64150dc44ee2f6/wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc", size = 35568 }, - { url = "https://files.pythonhosted.org/packages/5c/cc/8297f9658506b224aa4bd71906447dea6bb0ba629861a758c28f67428b91/wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8", size = 37653 }, - { url = "https://files.pythonhosted.org/packages/ff/21/abdedb4cdf6ff41ebf01a74087740a709e2edb146490e4d9beea054b0b7a/wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1", size = 23362 }, -] - -[[package]] -name = "wsproto" -version = "1.2.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "h11" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226 }, -] - -[[package]] -name = "yarl" -version = "1.17.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, - { name = "multidict" }, - { name = "propcache" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/54/9c/9c0a9bfa683fc1be7fdcd9687635151544d992cccd48892dc5e0a5885a29/yarl-1.17.1.tar.gz", hash = "sha256:067a63fcfda82da6b198fa73079b1ca40b7c9b7994995b6ee38acda728b64d47", size = 178163 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/af/e25615c7920396219b943b9ff8b34636ae3e1ad30777649371317d7f05f8/yarl-1.17.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:327828786da2006085a4d1feb2594de6f6d26f8af48b81eb1ae950c788d97f61", size = 141839 }, - { url = "https://files.pythonhosted.org/packages/83/5e/363d9de3495c7c66592523f05d21576a811015579e0c87dd38c7b5788afd/yarl-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cc353841428d56b683a123a813e6a686e07026d6b1c5757970a877195f880c2d", size = 94125 }, - { url = "https://files.pythonhosted.org/packages/e3/a2/b65447626227ebe36f18f63ac551790068bf42c69bb22dfa3ae986170728/yarl-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c73df5b6e8fabe2ddb74876fb82d9dd44cbace0ca12e8861ce9155ad3c886139", size = 92048 }, - { url = "https://files.pythonhosted.org/packages/a1/f5/2ef86458446f85cde10582054fd5113495ef8ce8477da35aaaf26d2970ef/yarl-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bdff5e0995522706c53078f531fb586f56de9c4c81c243865dd5c66c132c3b5", size = 331472 }, - { url = "https://files.pythonhosted.org/packages/f3/6b/1ba79758ba352cdf2ad4c20cab1b982dd369aa595bb0d7601fc89bf82bee/yarl-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:06157fb3c58f2736a5e47c8fcbe1afc8b5de6fb28b14d25574af9e62150fcaac", size = 341260 }, - { url = "https://files.pythonhosted.org/packages/2d/41/4e07c2afca3f9ed3da5b0e38d43d0280d9b624a3d5c478c425e5ce17775c/yarl-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1654ec814b18be1af2c857aa9000de7a601400bd4c9ca24629b18486c2e35463", size = 340882 }, - { url = "https://files.pythonhosted.org/packages/c3/c0/cd8e94618983c1b811af082e1a7ad7764edb3a6af2bc6b468e0e686238ba/yarl-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f6595c852ca544aaeeb32d357e62c9c780eac69dcd34e40cae7b55bc4fb1147", size = 336648 }, - { url = "https://files.pythonhosted.org/packages/ac/fc/73ec4340d391ffbb8f34eb4c55429784ec9f5bd37973ce86d52d67135418/yarl-1.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:459e81c2fb920b5f5df744262d1498ec2c8081acdcfe18181da44c50f51312f7", size = 325019 }, - { url = "https://files.pythonhosted.org/packages/57/48/da3ebf418fc239d0a156b3bdec6b17a5446f8d2dea752299c6e47b143a85/yarl-1.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e48cdb8226644e2fbd0bdb0a0f87906a3db07087f4de77a1b1b1ccfd9e93685", size = 342841 }, - { url = "https://files.pythonhosted.org/packages/5d/79/107272745a470a8167924e353a5312eb52b5a9bb58e22686adc46c94f7ec/yarl-1.17.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d9b6b28a57feb51605d6ae5e61a9044a31742db557a3b851a74c13bc61de5172", size = 341433 }, - { url = "https://files.pythonhosted.org/packages/30/9c/6459668b3b8dcc11cd061fc53e12737e740fb6b1575b49c84cbffb387b3a/yarl-1.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e594b22688d5747b06e957f1ef822060cb5cb35b493066e33ceac0cf882188b7", size = 344927 }, - { url = "https://files.pythonhosted.org/packages/c5/0b/93a17ed733aca8164fc3a01cb7d47b3f08854ce4f957cce67a6afdb388a0/yarl-1.17.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5f236cb5999ccd23a0ab1bd219cfe0ee3e1c1b65aaf6dd3320e972f7ec3a39da", size = 355732 }, - { url = "https://files.pythonhosted.org/packages/9a/63/ead2ed6aec3c59397e135cadc66572330325a0c24cd353cd5c94f5e63463/yarl-1.17.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a2a64e62c7a0edd07c1c917b0586655f3362d2c2d37d474db1a509efb96fea1c", size = 362123 }, - { url = "https://files.pythonhosted.org/packages/89/bf/f6b75b4c2fcf0e7bb56edc0ed74e33f37fac45dc40e5a52a3be66b02587a/yarl-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d0eea830b591dbc68e030c86a9569826145df485b2b4554874b07fea1275a199", size = 356355 }, - { url = "https://files.pythonhosted.org/packages/45/1f/50a0257cd07eef65c8c65ad6a21f5fb230012d659e021aeb6ac8a7897bf6/yarl-1.17.1-cp312-cp312-win32.whl", hash = "sha256:46ddf6e0b975cd680eb83318aa1d321cb2bf8d288d50f1754526230fcf59ba96", size = 83279 }, - { url = "https://files.pythonhosted.org/packages/bc/82/fafb2c1268d63d54ec08b3a254fbe51f4ef098211501df646026717abee3/yarl-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:117ed8b3732528a1e41af3aa6d4e08483c2f0f2e3d3d7dca7cf538b3516d93df", size = 89590 }, - { url = "https://files.pythonhosted.org/packages/06/1e/5a93e3743c20eefbc68bd89334d9c9f04f3f2334380f7bbf5e950f29511b/yarl-1.17.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5d1d42556b063d579cae59e37a38c61f4402b47d70c29f0ef15cee1acaa64488", size = 139974 }, - { url = "https://files.pythonhosted.org/packages/a1/be/4e0f6919013c7c5eaea5c31811c551ccd599d2fc80aa3dd6962f1bbdcddd/yarl-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0167540094838ee9093ef6cc2c69d0074bbf84a432b4995835e8e5a0d984374", size = 93364 }, - { url = "https://files.pythonhosted.org/packages/73/f0/650f994bc491d0cb85df8bb45392780b90eab1e175f103a5edc61445ff67/yarl-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2f0a6423295a0d282d00e8701fe763eeefba8037e984ad5de44aa349002562ac", size = 91177 }, - { url = "https://files.pythonhosted.org/packages/f3/e8/9945ed555d14b43ede3ae8b1bd73e31068a694cad2b9d3cad0a28486c2eb/yarl-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5b078134f48552c4d9527db2f7da0b5359abd49393cdf9794017baec7506170", size = 333086 }, - { url = "https://files.pythonhosted.org/packages/a6/c0/7d167e48e14d26639ca066825af8da7df1d2fcdba827e3fd6341aaf22a3b/yarl-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d401f07261dc5aa36c2e4efc308548f6ae943bfff20fcadb0a07517a26b196d8", size = 343661 }, - { url = "https://files.pythonhosted.org/packages/fa/81/80a266517531d4e3553aecd141800dbf48d02e23ebd52909e63598a80134/yarl-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5f1ac7359e17efe0b6e5fec21de34145caef22b260e978336f325d5c84e6938", size = 345196 }, - { url = "https://files.pythonhosted.org/packages/b0/77/6adc482ba7f2dc6c0d9b3b492e7cd100edfac4cfc3849c7ffa26fd7beb1a/yarl-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f63d176a81555984e91f2c84c2a574a61cab7111cc907e176f0f01538e9ff6e", size = 338743 }, - { url = "https://files.pythonhosted.org/packages/6d/cc/f0c4c0b92ff3ada517ffde2b127406c001504b225692216d969879ada89a/yarl-1.17.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e275792097c9f7e80741c36de3b61917aebecc08a67ae62899b074566ff8556", size = 326719 }, - { url = "https://files.pythonhosted.org/packages/18/3b/7bfc80d3376b5fa162189993a87a5a6a58057f88315bd0ea00610055b57a/yarl-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:81713b70bea5c1386dc2f32a8f0dab4148a2928c7495c808c541ee0aae614d67", size = 345826 }, - { url = "https://files.pythonhosted.org/packages/2e/66/cf0b0338107a5c370205c1a572432af08f36ca12ecce127f5b558398b4fd/yarl-1.17.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:aa46dce75078fceaf7cecac5817422febb4355fbdda440db55206e3bd288cfb8", size = 340335 }, - { url = "https://files.pythonhosted.org/packages/2f/52/b084b0eec0fd4d2490e1d33ace3320fad704c5f1f3deaa709f929d2d87fc/yarl-1.17.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1ce36ded585f45b1e9bb36d0ae94765c6608b43bd2e7f5f88079f7a85c61a4d3", size = 345301 }, - { url = "https://files.pythonhosted.org/packages/ef/38/9e2036d948efd3bafcdb4976cb212166fded76615f0dfc6c1492c4ce4784/yarl-1.17.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2d374d70fdc36f5863b84e54775452f68639bc862918602d028f89310a034ab0", size = 354205 }, - { url = "https://files.pythonhosted.org/packages/81/c1/13dfe1e70b86811733316221c696580725ceb1c46d4e4db852807e134310/yarl-1.17.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:2d9f0606baaec5dd54cb99667fcf85183a7477f3766fbddbe3f385e7fc253299", size = 360501 }, - { url = "https://files.pythonhosted.org/packages/91/87/756e05c74cd8bf9e71537df4a2cae7e8211a9ebe0d2350a3e26949e1e41c/yarl-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b0341e6d9a0c0e3cdc65857ef518bb05b410dbd70d749a0d33ac0f39e81a4258", size = 359452 }, - { url = "https://files.pythonhosted.org/packages/06/b2/b2bb09c1e6d59e1c9b1b36a86caa473e22c3dbf26d1032c030e9bfb554dc/yarl-1.17.1-cp313-cp313-win32.whl", hash = "sha256:2e7ba4c9377e48fb7b20dedbd473cbcbc13e72e1826917c185157a137dac9df2", size = 308904 }, - { url = "https://files.pythonhosted.org/packages/f3/27/f084d9a5668853c1f3b246620269b14ee871ef3c3cc4f3a1dd53645b68ec/yarl-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:949681f68e0e3c25377462be4b658500e85ca24323d9619fdc41f68d46a1ffda", size = 314637 }, - { url = "https://files.pythonhosted.org/packages/52/ad/1fe7ff5f3e8869d4c5070f47b96bac2b4d15e67c100a8278d8e7876329fc/yarl-1.17.1-py3-none-any.whl", hash = "sha256:f1790a4b1e8e8e028c391175433b9c8122c39b46e1663228158e61e6f915bf06", size = 44352 }, -] diff --git a/contrib/drivers/tftp/.gitignore b/contrib/drivers/tftp/.gitignore deleted file mode 100644 index cbc5d672b..000000000 --- a/contrib/drivers/tftp/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -__pycache__/ -.coverage -coverage.xml diff --git a/contrib/drivers/tftp/.python-version b/contrib/drivers/tftp/.python-version deleted file mode 100644 index e4fba2183..000000000 --- a/contrib/drivers/tftp/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.12 diff --git a/contrib/drivers/tftp/uv.lock b/contrib/drivers/tftp/uv.lock deleted file mode 100644 index 2c7d9a6bc..000000000 --- a/contrib/drivers/tftp/uv.lock +++ /dev/null @@ -1,921 +0,0 @@ -version = 1 -requires-python = ">=3.12" -resolution-markers = [ - "python_full_version < '3.13'", - "python_full_version >= '3.13'", -] - -[[package]] -name = "aiohappyeyeballs" -version = "2.4.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bc/69/2f6d5a019bd02e920a3417689a89887b39ad1e350b562f9955693d900c40/aiohappyeyeballs-2.4.3.tar.gz", hash = "sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586", size = 21809 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/d8/120cd0fe3e8530df0539e71ba9683eade12cae103dd7543e50d15f737917/aiohappyeyeballs-2.4.3-py3-none-any.whl", hash = "sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572", size = 14742 }, -] - -[[package]] -name = "aiohttp" -version = "3.10.10" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohappyeyeballs" }, - { name = "aiosignal" }, - { name = "attrs" }, - { name = "frozenlist" }, - { name = "multidict" }, - { name = "yarl" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/17/7e/16e57e6cf20eb62481a2f9ce8674328407187950ccc602ad07c685279141/aiohttp-3.10.10.tar.gz", hash = "sha256:0631dd7c9f0822cc61c88586ca76d5b5ada26538097d0f1df510b082bad3411a", size = 7542993 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/99/4c5aefe5ad06a1baf206aed6598c7cdcbc7c044c46801cd0d1ecb758cae3/aiohttp-3.10.10-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9294bbb581f92770e6ed5c19559e1e99255e4ca604a22c5c6397b2f9dd3ee42c", size = 583536 }, - { url = "https://files.pythonhosted.org/packages/a9/36/8b3bc49b49cb6d2da40ee61ff15dbcc44fd345a3e6ab5bb20844df929821/aiohttp-3.10.10-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a8fa23fe62c436ccf23ff930149c047f060c7126eae3ccea005f0483f27b2e28", size = 395693 }, - { url = "https://files.pythonhosted.org/packages/e1/77/0aa8660dcf11fa65d61712dbb458c4989de220a844bd69778dff25f2d50b/aiohttp-3.10.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5c6a5b8c7926ba5d8545c7dd22961a107526562da31a7a32fa2456baf040939f", size = 390898 }, - { url = "https://files.pythonhosted.org/packages/38/d2/b833d95deb48c75db85bf6646de0a697e7fb5d87bd27cbade4f9746b48b1/aiohttp-3.10.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:007ec22fbc573e5eb2fb7dec4198ef8f6bf2fe4ce20020798b2eb5d0abda6138", size = 1312060 }, - { url = "https://files.pythonhosted.org/packages/aa/5f/29fd5113165a0893de8efedf9b4737e0ba92dfcd791415a528f947d10299/aiohttp-3.10.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9627cc1a10c8c409b5822a92d57a77f383b554463d1884008e051c32ab1b3742", size = 1350553 }, - { url = "https://files.pythonhosted.org/packages/ad/cc/f835f74b7d344428469200105236d44606cfa448be1e7c95ca52880d9bac/aiohttp-3.10.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:50edbcad60d8f0e3eccc68da67f37268b5144ecc34d59f27a02f9611c1d4eec7", size = 1392646 }, - { url = "https://files.pythonhosted.org/packages/bf/fe/1332409d845ca601893bbf2d76935e0b93d41686e5f333841c7d7a4a770d/aiohttp-3.10.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a45d85cf20b5e0d0aa5a8dca27cce8eddef3292bc29d72dcad1641f4ed50aa16", size = 1306310 }, - { url = "https://files.pythonhosted.org/packages/e4/a1/25a7633a5a513278a9892e333501e2e69c83e50be4b57a62285fb7a008c3/aiohttp-3.10.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b00807e2605f16e1e198f33a53ce3c4523114059b0c09c337209ae55e3823a8", size = 1260255 }, - { url = "https://files.pythonhosted.org/packages/f2/39/30eafe89e0e2a06c25e4762844c8214c0c0cd0fd9ffc3471694a7986f421/aiohttp-3.10.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f2d4324a98062be0525d16f768a03e0bbb3b9fe301ceee99611dc9a7953124e6", size = 1271141 }, - { url = "https://files.pythonhosted.org/packages/5b/fc/33125df728b48391ef1fcb512dfb02072158cc10d041414fb79803463020/aiohttp-3.10.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:438cd072f75bb6612f2aca29f8bd7cdf6e35e8f160bc312e49fbecab77c99e3a", size = 1280244 }, - { url = "https://files.pythonhosted.org/packages/3b/61/e42bf2c2934b5caa4e2ec0b5e5fd86989adb022b5ee60c2572a9d77cf6fe/aiohttp-3.10.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:baa42524a82f75303f714108fea528ccacf0386af429b69fff141ffef1c534f9", size = 1316805 }, - { url = "https://files.pythonhosted.org/packages/18/32/f52a5e2ae9ad3bba10e026a63a7a23abfa37c7d97aeeb9004eaa98df3ce3/aiohttp-3.10.10-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a7d8d14fe962153fc681f6366bdec33d4356f98a3e3567782aac1b6e0e40109a", size = 1343930 }, - { url = "https://files.pythonhosted.org/packages/05/be/6a403b464dcab3631fe8e27b0f1d906d9e45c5e92aca97ee007e5a895560/aiohttp-3.10.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c1277cd707c465cd09572a774559a3cc7c7a28802eb3a2a9472588f062097205", size = 1306186 }, - { url = "https://files.pythonhosted.org/packages/8e/fd/bb50fe781068a736a02bf5c7ad5f3ab53e39f1d1e63110da6d30f7605edc/aiohttp-3.10.10-cp312-cp312-win32.whl", hash = "sha256:59bb3c54aa420521dc4ce3cc2c3fe2ad82adf7b09403fa1f48ae45c0cbde6628", size = 359289 }, - { url = "https://files.pythonhosted.org/packages/70/9e/5add7e240f77ef67c275c82cc1d08afbca57b77593118c1f6e920ae8ad3f/aiohttp-3.10.10-cp312-cp312-win_amd64.whl", hash = "sha256:0e1b370d8007c4ae31ee6db7f9a2fe801a42b146cec80a86766e7ad5c4a259cf", size = 379313 }, - { url = "https://files.pythonhosted.org/packages/b1/eb/618b1b76c7fe8082a71c9d62e3fe84c5b9af6703078caa9ec57850a12080/aiohttp-3.10.10-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ad7593bb24b2ab09e65e8a1d385606f0f47c65b5a2ae6c551db67d6653e78c28", size = 576114 }, - { url = "https://files.pythonhosted.org/packages/aa/37/3126995d7869f8b30d05381b81a2d4fb4ec6ad313db788e009bc6d39c211/aiohttp-3.10.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1eb89d3d29adaf533588f209768a9c02e44e4baf832b08118749c5fad191781d", size = 391901 }, - { url = "https://files.pythonhosted.org/packages/3e/f2/8fdfc845be1f811c31ceb797968523813f8e1263ee3e9120d61253f6848f/aiohttp-3.10.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3fe407bf93533a6fa82dece0e74dbcaaf5d684e5a51862887f9eaebe6372cd79", size = 387418 }, - { url = "https://files.pythonhosted.org/packages/60/d5/33d2061d36bf07e80286e04b7e0a4de37ce04b5ebfed72dba67659a05250/aiohttp-3.10.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50aed5155f819873d23520919e16703fc8925e509abbb1a1491b0087d1cd969e", size = 1287073 }, - { url = "https://files.pythonhosted.org/packages/00/52/affb55be16a4747740bd630b4c002dac6c5eac42f9bb64202fc3cf3f1930/aiohttp-3.10.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f05e9727ce409358baa615dbeb9b969db94324a79b5a5cea45d39bdb01d82e6", size = 1323612 }, - { url = "https://files.pythonhosted.org/packages/94/f2/cddb69b975387daa2182a8442566971d6410b8a0179bb4540d81c97b1611/aiohttp-3.10.10-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dffb610a30d643983aeb185ce134f97f290f8935f0abccdd32c77bed9388b42", size = 1368406 }, - { url = "https://files.pythonhosted.org/packages/c1/e4/afba7327da4d932da8c6e29aecaf855f9d52dace53ac15bfc8030a246f1b/aiohttp-3.10.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa6658732517ddabe22c9036479eabce6036655ba87a0224c612e1ae6af2087e", size = 1282761 }, - { url = "https://files.pythonhosted.org/packages/9f/6b/364856faa0c9031ea76e24ef0f7fef79cddd9fa8e7dba9a1771c6acc56b5/aiohttp-3.10.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:741a46d58677d8c733175d7e5aa618d277cd9d880301a380fd296975a9cdd7bc", size = 1236518 }, - { url = "https://files.pythonhosted.org/packages/46/af/c382846f8356fe64a7b5908bb9b477457aa23b71be7ed551013b7b7d4d87/aiohttp-3.10.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e00e3505cd80440f6c98c6d69269dcc2a119f86ad0a9fd70bccc59504bebd68a", size = 1250344 }, - { url = "https://files.pythonhosted.org/packages/87/53/294f87fc086fd0772d0ab82497beb9df67f0f27a8b3dd5742a2656db2bc6/aiohttp-3.10.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ffe595f10566f8276b76dc3a11ae4bb7eba1aac8ddd75811736a15b0d5311414", size = 1248956 }, - { url = "https://files.pythonhosted.org/packages/86/30/7d746717fe11bdfefb88bb6c09c5fc985d85c4632da8bb6018e273899254/aiohttp-3.10.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdfcf6443637c148c4e1a20c48c566aa694fa5e288d34b20fcdc58507882fed3", size = 1293379 }, - { url = "https://files.pythonhosted.org/packages/48/b9/45d670a834458db67a24258e9139ba61fa3bd7d69b98ecf3650c22806f8f/aiohttp-3.10.10-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d183cf9c797a5291e8301790ed6d053480ed94070637bfaad914dd38b0981f67", size = 1320108 }, - { url = "https://files.pythonhosted.org/packages/72/8c/804bb2e837a175635d2000a0659eafc15b2e9d92d3d81c8f69e141ecd0b0/aiohttp-3.10.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:77abf6665ae54000b98b3c742bc6ea1d1fb31c394bcabf8b5d2c1ac3ebfe7f3b", size = 1281546 }, - { url = "https://files.pythonhosted.org/packages/89/c0/862e6a9de3d6eeb126cd9d9ea388243b70df9b871ce1a42b193b7a4a77fc/aiohttp-3.10.10-cp313-cp313-win32.whl", hash = "sha256:4470c73c12cd9109db8277287d11f9dd98f77fc54155fc71a7738a83ffcc8ea8", size = 357516 }, - { url = "https://files.pythonhosted.org/packages/ae/63/3e1aee3e554263f3f1011cca50d78a4894ae16ce99bf78101ac3a2f0ef74/aiohttp-3.10.10-cp313-cp313-win_amd64.whl", hash = "sha256:486f7aabfa292719a2753c016cc3a8f8172965cabb3ea2e7f7436c7f5a22a151", size = 376785 }, -] - -[[package]] -name = "aiosignal" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "frozenlist" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ae/67/0952ed97a9793b4958e5736f6d2b346b414a2cd63e82d05940032f45b32f/aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", size = 19422 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17", size = 7617 }, -] - -[[package]] -name = "annotated-types" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, -] - -[[package]] -name = "anyio" -version = "4.6.2.post1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, - { name = "sniffio" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9f/09/45b9b7a6d4e45c6bcb5bf61d19e3ab87df68e0601fa8c5293de3542546cc/anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c", size = 173422 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/f5/f2b75d2fc6f1a260f340f0e7c6a060f4dd2961cc16884ed851b0d18da06a/anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d", size = 90377 }, -] - -[[package]] -name = "attrs" -version = "24.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fc/0f/aafca9af9315aee06a89ffde799a10a582fe8de76c563ee80bbcdc08b3fb/attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346", size = 792678 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2", size = 63001 }, -] - -[[package]] -name = "bcrypt" -version = "4.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e4/7e/d95e7d96d4828e965891af92e43b52a4cd3395dc1c1ef4ee62748d0471d0/bcrypt-4.2.0.tar.gz", hash = "sha256:cf69eaf5185fd58f268f805b505ce31f9b9fc2d64b376642164e9244540c1221", size = 24294 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/81/4e8f5bc0cd947e91fb720e1737371922854da47a94bc9630454e7b2845f8/bcrypt-4.2.0-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:096a15d26ed6ce37a14c1ac1e48119660f21b24cba457f160a4b830f3fe6b5cb", size = 471568 }, - { url = "https://files.pythonhosted.org/packages/05/d2/1be1e16aedec04bcf8d0156e01b987d16a2063d38e64c3f28030a3427d61/bcrypt-4.2.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c02d944ca89d9b1922ceb8a46460dd17df1ba37ab66feac4870f6862a1533c00", size = 277372 }, - { url = "https://files.pythonhosted.org/packages/e3/96/7a654027638ad9b7589effb6db77eb63eba64319dfeaf9c0f4ca953e5f76/bcrypt-4.2.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d84cf6d877918620b687b8fd1bf7781d11e8a0998f576c7aa939776b512b98d", size = 273488 }, - { url = "https://files.pythonhosted.org/packages/46/54/dc7b58abeb4a3d95bab653405935e27ba32f21b812d8ff38f271fb6f7f55/bcrypt-4.2.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:1bb429fedbe0249465cdd85a58e8376f31bb315e484f16e68ca4c786dcc04291", size = 277759 }, - { url = "https://files.pythonhosted.org/packages/ac/be/da233c5f11fce3f8adec05e8e532b299b64833cc962f49331cdd0e614fa9/bcrypt-4.2.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:655ea221910bcac76ea08aaa76df427ef8625f92e55a8ee44fbf7753dbabb328", size = 273796 }, - { url = "https://files.pythonhosted.org/packages/b0/b8/8b4add88d55a263cf1c6b8cf66c735280954a04223fcd2880120cc767ac3/bcrypt-4.2.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:1ee38e858bf5d0287c39b7a1fc59eec64bbf880c7d504d3a06a96c16e14058e7", size = 311082 }, - { url = "https://files.pythonhosted.org/packages/7b/76/2aa660679abbdc7f8ee961552e4bb6415a81b303e55e9374533f22770203/bcrypt-4.2.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0da52759f7f30e83f1e30a888d9163a81353ef224d82dc58eb5bb52efcabc399", size = 305912 }, - { url = "https://files.pythonhosted.org/packages/00/03/2af7c45034aba6002d4f2b728c1a385676b4eab7d764410e34fd768009f2/bcrypt-4.2.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3698393a1b1f1fd5714524193849d0c6d524d33523acca37cd28f02899285060", size = 325185 }, - { url = "https://files.pythonhosted.org/packages/dc/5d/6843443ce4ab3af40bddb6c7c085ed4a8418b3396f7a17e60e6d9888416c/bcrypt-4.2.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:762a2c5fb35f89606a9fde5e51392dad0cd1ab7ae64149a8b935fe8d79dd5ed7", size = 335188 }, - { url = "https://files.pythonhosted.org/packages/cb/4c/ff8ca83d816052fba36def1d24e97d9a85739b9bbf428c0d0ecd296a07c8/bcrypt-4.2.0-cp37-abi3-win32.whl", hash = "sha256:5a1e8aa9b28ae28020a3ac4b053117fb51c57a010b9f969603ed885f23841458", size = 156481 }, - { url = "https://files.pythonhosted.org/packages/65/f1/e09626c88a56cda488810fb29d5035f1662873777ed337880856b9d204ae/bcrypt-4.2.0-cp37-abi3-win_amd64.whl", hash = "sha256:8f6ede91359e5df88d1f5c1ef47428a4420136f3ce97763e31b86dd8280fbdf5", size = 151336 }, - { url = "https://files.pythonhosted.org/packages/96/86/8c6a84daed4dd878fbab094400c9174c43d9b838ace077a2f8ee8bc3ae12/bcrypt-4.2.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:c52aac18ea1f4a4f65963ea4f9530c306b56ccd0c6f8c8da0c06976e34a6e841", size = 472414 }, - { url = "https://files.pythonhosted.org/packages/f6/05/e394515f4e23c17662e5aeb4d1859b11dc651be01a3bd03c2e919a155901/bcrypt-4.2.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3bbbfb2734f0e4f37c5136130405332640a1e46e6b23e000eeff2ba8d005da68", size = 277599 }, - { url = "https://files.pythonhosted.org/packages/4b/3b/ad784eac415937c53da48983756105d267b91e56aa53ba8a1b2014b8d930/bcrypt-4.2.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3413bd60460f76097ee2e0a493ccebe4a7601918219c02f503984f0a7ee0aebe", size = 273491 }, - { url = "https://files.pythonhosted.org/packages/cc/14/b9ff8e0218bee95e517b70e91130effb4511e8827ac1ab00b4e30943a3f6/bcrypt-4.2.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8d7bb9c42801035e61c109c345a28ed7e84426ae4865511eb82e913df18f58c2", size = 277934 }, - { url = "https://files.pythonhosted.org/packages/3e/d0/31938bb697600a04864246acde4918c4190a938f891fd11883eaaf41327a/bcrypt-4.2.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d3a6d28cb2305b43feac298774b997e372e56c7c7afd90a12b3dc49b189151c", size = 273804 }, - { url = "https://files.pythonhosted.org/packages/e7/c3/dae866739989e3f04ae304e1201932571708cb292a28b2f1b93283e2dcd8/bcrypt-4.2.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:9c1c4ad86351339c5f320ca372dfba6cb6beb25e8efc659bedd918d921956bae", size = 311275 }, - { url = "https://files.pythonhosted.org/packages/5d/2c/019bc2c63c6125ddf0483ee7d914a405860327767d437913942b476e9c9b/bcrypt-4.2.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:27fe0f57bb5573104b5a6de5e4153c60814c711b29364c10a75a54bb6d7ff48d", size = 306355 }, - { url = "https://files.pythonhosted.org/packages/75/fe/9e137727f122bbe29771d56afbf4e0dbc85968caa8957806f86404a5bfe1/bcrypt-4.2.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8ac68872c82f1add6a20bd489870c71b00ebacd2e9134a8aa3f98a0052ab4b0e", size = 325381 }, - { url = "https://files.pythonhosted.org/packages/1a/d4/586b9c18a327561ea4cd336ff4586cca1a7aa0f5ee04e23a8a8bb9ca64f1/bcrypt-4.2.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cb2a8ec2bc07d3553ccebf0746bbf3d19426d1c6d1adbd4fa48925f66af7b9e8", size = 335685 }, - { url = "https://files.pythonhosted.org/packages/24/55/1a7127faf4576138bb278b91e9c75307490178979d69c8e6e273f74b974f/bcrypt-4.2.0-cp39-abi3-win32.whl", hash = "sha256:77800b7147c9dc905db1cba26abe31e504d8247ac73580b4aa179f98e6608f34", size = 155857 }, - { url = "https://files.pythonhosted.org/packages/1c/2a/c74052e54162ec639266d91539cca7cbf3d1d3b8b36afbfeaee0ea6a1702/bcrypt-4.2.0-cp39-abi3-win_amd64.whl", hash = "sha256:61ed14326ee023917ecd093ee6ef422a72f3aec6f07e21ea5f10622b735538a9", size = 151717 }, -] - -[[package]] -name = "certifi" -version = "2024.8.30" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9", size = 168507 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", size = 167321 }, -] - -[[package]] -name = "cffi" -version = "1.17.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pycparser" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, - { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, - { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, - { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 }, - { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 }, - { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 }, - { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 }, - { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 }, - { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 }, - { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, - { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, - { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 }, - { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 }, - { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 }, - { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 }, - { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 }, - { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 }, - { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 }, - { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 }, - { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 }, - { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, - { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, -] - -[[package]] -name = "click" -version = "8.1.7" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941 }, -] - -[[package]] -name = "colorama" -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 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, -] - -[[package]] -name = "coverage" -version = "7.6.9" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5b/d2/c25011f4d036cf7e8acbbee07a8e09e9018390aee25ba085596c4b83d510/coverage-7.6.9.tar.gz", hash = "sha256:4a8d8977b0c6ef5aeadcb644da9e69ae0dcfe66ec7f368c89c72e058bd71164d", size = 801710 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/60/52/b16af8989a2daf0f80a88522bd8e8eed90b5fcbdecf02a6888f3e80f6ba7/coverage-7.6.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:99e266ae0b5d15f1ca8d278a668df6f51cc4b854513daab5cae695ed7b721cf8", size = 207325 }, - { url = "https://files.pythonhosted.org/packages/0f/79/6b7826fca8846c1216a113227b9f114ac3e6eacf168b4adcad0cb974aaca/coverage-7.6.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9901d36492009a0a9b94b20e52ebfc8453bf49bb2b27bca2c9706f8b4f5a554a", size = 207563 }, - { url = "https://files.pythonhosted.org/packages/a7/07/0bc73da0ccaf45d0d64ef86d33b7d7fdeef84b4c44bf6b85fb12c215c5a6/coverage-7.6.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abd3e72dd5b97e3af4246cdada7738ef0e608168de952b837b8dd7e90341f015", size = 240580 }, - { url = "https://files.pythonhosted.org/packages/71/8a/9761f409910961647d892454687cedbaccb99aae828f49486734a82ede6e/coverage-7.6.9-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff74026a461eb0660366fb01c650c1d00f833a086b336bdad7ab00cc952072b3", size = 237613 }, - { url = "https://files.pythonhosted.org/packages/8b/10/ee7d696a17ac94f32f2dbda1e17e730bf798ae9931aec1fc01c1944cd4de/coverage-7.6.9-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65dad5a248823a4996724a88eb51d4b31587aa7aa428562dbe459c684e5787ae", size = 239684 }, - { url = "https://files.pythonhosted.org/packages/16/60/aa1066040d3c52fff051243c2d6ccda264da72dc6d199d047624d395b2b2/coverage-7.6.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:22be16571504c9ccea919fcedb459d5ab20d41172056206eb2994e2ff06118a4", size = 239112 }, - { url = "https://files.pythonhosted.org/packages/4e/e5/69f35344c6f932ba9028bf168d14a79fedb0dd4849b796d43c81ce75a3c9/coverage-7.6.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f957943bc718b87144ecaee70762bc2bc3f1a7a53c7b861103546d3a403f0a6", size = 237428 }, - { url = "https://files.pythonhosted.org/packages/32/20/adc895523c4a28f63441b8ac645abd74f9bdd499d2d175bef5b41fc7f92d/coverage-7.6.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ae1387db4aecb1f485fb70a6c0148c6cdaebb6038f1d40089b1fc84a5db556f", size = 239098 }, - { url = "https://files.pythonhosted.org/packages/a9/a6/e0e74230c9bb3549ec8ffc137cfd16ea5d56e993d6bffed2218bff6187e3/coverage-7.6.9-cp312-cp312-win32.whl", hash = "sha256:1a330812d9cc7ac2182586f6d41b4d0fadf9be9049f350e0efb275c8ee8eb692", size = 209940 }, - { url = "https://files.pythonhosted.org/packages/3e/18/cb5b88349d4aa2f41ec78d65f92ea32572b30b3f55bc2b70e87578b8f434/coverage-7.6.9-cp312-cp312-win_amd64.whl", hash = "sha256:b12c6b18269ca471eedd41c1b6a1065b2f7827508edb9a7ed5555e9a56dcfc97", size = 210726 }, - { url = "https://files.pythonhosted.org/packages/35/26/9abab6539d2191dbda2ce8c97b67d74cbfc966cc5b25abb880ffc7c459bc/coverage-7.6.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:899b8cd4781c400454f2f64f7776a5d87bbd7b3e7f7bda0cb18f857bb1334664", size = 207356 }, - { url = "https://files.pythonhosted.org/packages/44/da/d49f19402240c93453f606e660a6676a2a1fbbaa6870cc23207790aa9697/coverage-7.6.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:61f70dc68bd36810972e55bbbe83674ea073dd1dcc121040a08cdf3416c5349c", size = 207614 }, - { url = "https://files.pythonhosted.org/packages/da/e6/93bb9bf85497816082ec8da6124c25efa2052bd4c887dd3b317b91990c9e/coverage-7.6.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a289d23d4c46f1a82d5db4abeb40b9b5be91731ee19a379d15790e53031c014", size = 240129 }, - { url = "https://files.pythonhosted.org/packages/df/65/6a824b9406fe066835c1274a9949e06f084d3e605eb1a602727a27ec2fe3/coverage-7.6.9-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e216d8044a356fc0337c7a2a0536d6de07888d7bcda76febcb8adc50bdbbd00", size = 237276 }, - { url = "https://files.pythonhosted.org/packages/9f/79/6c7a800913a9dd23ac8c8da133ebb556771a5a3d4df36b46767b1baffd35/coverage-7.6.9-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c026eb44f744acaa2bda7493dad903aa5bf5fc4f2554293a798d5606710055d", size = 239267 }, - { url = "https://files.pythonhosted.org/packages/57/e7/834d530293fdc8a63ba8ff70033d5182022e569eceb9aec7fc716b678a39/coverage-7.6.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e77363e8425325384f9d49272c54045bbed2f478e9dd698dbc65dbc37860eb0a", size = 238887 }, - { url = "https://files.pythonhosted.org/packages/15/05/ec9d6080852984f7163c96984444e7cd98b338fd045b191064f943ee1c08/coverage-7.6.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:777abfab476cf83b5177b84d7486497e034eb9eaea0d746ce0c1268c71652077", size = 236970 }, - { url = "https://files.pythonhosted.org/packages/0a/d8/775937670b93156aec29f694ce37f56214ed7597e1a75b4083ee4c32121c/coverage-7.6.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:447af20e25fdbe16f26e84eb714ba21d98868705cb138252d28bc400381f6ffb", size = 238831 }, - { url = "https://files.pythonhosted.org/packages/f4/58/88551cb7fdd5ec98cb6044e8814e38583436b14040a5ece15349c44c8f7c/coverage-7.6.9-cp313-cp313-win32.whl", hash = "sha256:d872ec5aeb086cbea771c573600d47944eea2dcba8be5f3ee649bfe3cb8dc9ba", size = 210000 }, - { url = "https://files.pythonhosted.org/packages/b7/12/cfbf49b95120872785ff8d56ab1c7fe3970a65e35010c311d7dd35c5fd00/coverage-7.6.9-cp313-cp313-win_amd64.whl", hash = "sha256:fd1213c86e48dfdc5a0cc676551db467495a95a662d2396ecd58e719191446e1", size = 210753 }, - { url = "https://files.pythonhosted.org/packages/7c/68/c1cb31445599b04bde21cbbaa6d21b47c5823cdfef99eae470dfce49c35a/coverage-7.6.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ba9e7484d286cd5a43744e5f47b0b3fb457865baf07bafc6bee91896364e1419", size = 208091 }, - { url = "https://files.pythonhosted.org/packages/11/73/84b02c6b19c4a11eb2d5b5eabe926fb26c21c080e0852f5e5a4f01165f9e/coverage-7.6.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e5ea1cf0872ee455c03e5674b5bca5e3e68e159379c1af0903e89f5eba9ccc3a", size = 208369 }, - { url = "https://files.pythonhosted.org/packages/de/e0/ae5d878b72ff26df2e994a5c5b1c1f6a7507d976b23beecb1ed4c85411ef/coverage-7.6.9-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d10e07aa2b91835d6abec555ec8b2733347956991901eea6ffac295f83a30e4", size = 251089 }, - { url = "https://files.pythonhosted.org/packages/ab/9c/0aaac011aef95a93ef3cb2fba3fde30bc7e68a6635199ed469b1f5ea355a/coverage-7.6.9-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:13a9e2d3ee855db3dd6ea1ba5203316a1b1fd8eaeffc37c5b54987e61e4194ae", size = 246806 }, - { url = "https://files.pythonhosted.org/packages/f8/19/4d5d3ae66938a7dcb2f58cef3fa5386f838f469575b0bb568c8cc9e3a33d/coverage-7.6.9-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c38bf15a40ccf5619fa2fe8f26106c7e8e080d7760aeccb3722664c8656b030", size = 249164 }, - { url = "https://files.pythonhosted.org/packages/b3/0b/4ee8a7821f682af9ad440ae3c1e379da89a998883271f088102d7ca2473d/coverage-7.6.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d5275455b3e4627c8e7154feaf7ee0743c2e7af82f6e3b561967b1cca755a0be", size = 248642 }, - { url = "https://files.pythonhosted.org/packages/8a/12/36ff1d52be18a16b4700f561852e7afd8df56363a5edcfb04cf26a0e19e0/coverage-7.6.9-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8f8770dfc6e2c6a2d4569f411015c8d751c980d17a14b0530da2d7f27ffdd88e", size = 246516 }, - { url = "https://files.pythonhosted.org/packages/43/d0/8e258f6c3a527c1655602f4f576215e055ac704de2d101710a71a2affac2/coverage-7.6.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8d2dfa71665a29b153a9681edb1c8d9c1ea50dfc2375fb4dac99ea7e21a0bcd9", size = 247783 }, - { url = "https://files.pythonhosted.org/packages/a9/0d/1e4a48d289429d38aae3babdfcadbf35ca36bdcf3efc8f09b550a845bdb5/coverage-7.6.9-cp313-cp313t-win32.whl", hash = "sha256:5e6b86b5847a016d0fbd31ffe1001b63355ed309651851295315031ea7eb5a9b", size = 210646 }, - { url = "https://files.pythonhosted.org/packages/26/74/b0729f196f328ac55e42b1e22ec2f16d8bcafe4b8158a26ec9f1cdd1d93e/coverage-7.6.9-cp313-cp313t-win_amd64.whl", hash = "sha256:97ddc94d46088304772d21b060041c97fc16bdda13c6c7f9d8fcd8d5ae0d8611", size = 211815 }, -] - -[[package]] -name = "cryptography" -version = "43.0.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0d/05/07b55d1fa21ac18c3a8c79f764e2514e6f6a9698f1be44994f5adf0d29db/cryptography-43.0.3.tar.gz", hash = "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805", size = 686989 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/f3/01fdf26701a26f4b4dbc337a26883ad5bccaa6f1bbbdd29cd89e22f18a1c/cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e", size = 6225303 }, - { url = "https://files.pythonhosted.org/packages/a3/01/4896f3d1b392025d4fcbecf40fdea92d3df8662123f6835d0af828d148fd/cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e", size = 3760905 }, - { url = "https://files.pythonhosted.org/packages/0a/be/f9a1f673f0ed4b7f6c643164e513dbad28dd4f2dcdf5715004f172ef24b6/cryptography-43.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f", size = 3977271 }, - { url = "https://files.pythonhosted.org/packages/4e/49/80c3a7b5514d1b416d7350830e8c422a4d667b6d9b16a9392ebfd4a5388a/cryptography-43.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6", size = 3746606 }, - { url = "https://files.pythonhosted.org/packages/0e/16/a28ddf78ac6e7e3f25ebcef69ab15c2c6be5ff9743dd0709a69a4f968472/cryptography-43.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18", size = 3986484 }, - { url = "https://files.pythonhosted.org/packages/01/f5/69ae8da70c19864a32b0315049866c4d411cce423ec169993d0434218762/cryptography-43.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd", size = 3852131 }, - { url = "https://files.pythonhosted.org/packages/fd/db/e74911d95c040f9afd3612b1f732e52b3e517cb80de8bf183be0b7d413c6/cryptography-43.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73", size = 4075647 }, - { url = "https://files.pythonhosted.org/packages/56/48/7b6b190f1462818b324e674fa20d1d5ef3e24f2328675b9b16189cbf0b3c/cryptography-43.0.3-cp37-abi3-win32.whl", hash = "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2", size = 2623873 }, - { url = "https://files.pythonhosted.org/packages/eb/b1/0ebff61a004f7f89e7b65ca95f2f2375679d43d0290672f7713ee3162aff/cryptography-43.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd", size = 3068039 }, - { url = "https://files.pythonhosted.org/packages/30/d5/c8b32c047e2e81dd172138f772e81d852c51f0f2ad2ae8a24f1122e9e9a7/cryptography-43.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984", size = 6222984 }, - { url = "https://files.pythonhosted.org/packages/2f/78/55356eb9075d0be6e81b59f45c7b48df87f76a20e73893872170471f3ee8/cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5", size = 3762968 }, - { url = "https://files.pythonhosted.org/packages/2a/2c/488776a3dc843f95f86d2f957ca0fc3407d0242b50bede7fad1e339be03f/cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4", size = 3977754 }, - { url = "https://files.pythonhosted.org/packages/7c/04/2345ca92f7a22f601a9c62961741ef7dd0127c39f7310dffa0041c80f16f/cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7", size = 3749458 }, - { url = "https://files.pythonhosted.org/packages/ac/25/e715fa0bc24ac2114ed69da33adf451a38abb6f3f24ec207908112e9ba53/cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405", size = 3988220 }, - { url = "https://files.pythonhosted.org/packages/21/ce/b9c9ff56c7164d8e2edfb6c9305045fbc0df4508ccfdb13ee66eb8c95b0e/cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16", size = 3853898 }, - { url = "https://files.pythonhosted.org/packages/2a/33/b3682992ab2e9476b9c81fff22f02c8b0a1e6e1d49ee1750a67d85fd7ed2/cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73", size = 4076592 }, - { url = "https://files.pythonhosted.org/packages/81/1e/ffcc41b3cebd64ca90b28fd58141c5f68c83d48563c88333ab660e002cd3/cryptography-43.0.3-cp39-abi3-win32.whl", hash = "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995", size = 2623145 }, - { url = "https://files.pythonhosted.org/packages/87/5c/3dab83cc4aba1f4b0e733e3f0c3e7d4386440d660ba5b1e3ff995feb734d/cryptography-43.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362", size = 3068026 }, -] - -[[package]] -name = "decorator" -version = "5.1.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/66/0c/8d907af351aa16b42caae42f9d6aa37b900c67308052d10fdce809f8d952/decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", size = 35016 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/50/83c593b07763e1161326b3b8c6686f0f4b0f24d5526546bee538c89837d6/decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186", size = 9073 }, -] - -[[package]] -name = "deprecated" -version = "1.2.14" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "wrapt" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/92/14/1e41f504a246fc224d2ac264c227975427a85caf37c3979979edb9b1b232/Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3", size = 2974416 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c", size = 9561 }, -] - -[[package]] -name = "fabric" -version = "3.2.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "decorator" }, - { name = "deprecated" }, - { name = "invoke" }, - { name = "paramiko" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0d/3f/337f278b70ba339c618a490f6b8033b7006c583bd197a897f12fbc468c51/fabric-3.2.2.tar.gz", hash = "sha256:8783ca42e3b0076f08b26901aac6b9d9b1f19c410074e7accfab902c184ff4a3", size = 183215 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/1f/e99e23ee01847147fa194e8d41cfcf2535a2dbfcb51414c541cadb15c5d7/fabric-3.2.2-py3-none-any.whl", hash = "sha256:91c47c0be68b14936c88b34da8a1f55e5710fd28397dac5d4ff2e21558113a6f", size = 59417 }, -] - -[[package]] -name = "frozenlist" -version = "1.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8f/ed/0f4cec13a93c02c47ec32d81d11c0c1efbadf4a471e3f3ce7cad366cbbd3/frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", size = 39930 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/79/73/fa6d1a96ab7fd6e6d1c3500700963eab46813847f01ef0ccbaa726181dd5/frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", size = 94026 }, - { url = "https://files.pythonhosted.org/packages/ab/04/ea8bf62c8868b8eada363f20ff1b647cf2e93377a7b284d36062d21d81d1/frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", size = 54150 }, - { url = "https://files.pythonhosted.org/packages/d0/9a/8e479b482a6f2070b26bda572c5e6889bb3ba48977e81beea35b5ae13ece/frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", size = 51927 }, - { url = "https://files.pythonhosted.org/packages/e3/12/2aad87deb08a4e7ccfb33600871bbe8f0e08cb6d8224371387f3303654d7/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a", size = 282647 }, - { url = "https://files.pythonhosted.org/packages/77/f2/07f06b05d8a427ea0060a9cef6e63405ea9e0d761846b95ef3fb3be57111/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a", size = 289052 }, - { url = "https://files.pythonhosted.org/packages/bd/9f/8bf45a2f1cd4aa401acd271b077989c9267ae8463e7c8b1eb0d3f561b65e/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee", size = 291719 }, - { url = "https://files.pythonhosted.org/packages/41/d1/1f20fd05a6c42d3868709b7604c9f15538a29e4f734c694c6bcfc3d3b935/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6", size = 267433 }, - { url = "https://files.pythonhosted.org/packages/af/f2/64b73a9bb86f5a89fb55450e97cd5c1f84a862d4ff90d9fd1a73ab0f64a5/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", size = 283591 }, - { url = "https://files.pythonhosted.org/packages/29/e2/ffbb1fae55a791fd6c2938dd9ea779509c977435ba3940b9f2e8dc9d5316/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9", size = 273249 }, - { url = "https://files.pythonhosted.org/packages/2e/6e/008136a30798bb63618a114b9321b5971172a5abddff44a100c7edc5ad4f/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039", size = 271075 }, - { url = "https://files.pythonhosted.org/packages/ae/f0/4e71e54a026b06724cec9b6c54f0b13a4e9e298cc8db0f82ec70e151f5ce/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784", size = 285398 }, - { url = "https://files.pythonhosted.org/packages/4d/36/70ec246851478b1c0b59f11ef8ade9c482ff447c1363c2bd5fad45098b12/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631", size = 294445 }, - { url = "https://files.pythonhosted.org/packages/37/e0/47f87544055b3349b633a03c4d94b405956cf2437f4ab46d0928b74b7526/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f", size = 280569 }, - { url = "https://files.pythonhosted.org/packages/f9/7c/490133c160fb6b84ed374c266f42800e33b50c3bbab1652764e6e1fc498a/frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8", size = 44721 }, - { url = "https://files.pythonhosted.org/packages/b1/56/4e45136ffc6bdbfa68c29ca56ef53783ef4c2fd395f7cbf99a2624aa9aaa/frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f", size = 51329 }, - { url = "https://files.pythonhosted.org/packages/da/3b/915f0bca8a7ea04483622e84a9bd90033bab54bdf485479556c74fd5eaf5/frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953", size = 91538 }, - { url = "https://files.pythonhosted.org/packages/c7/d1/a7c98aad7e44afe5306a2b068434a5830f1470675f0e715abb86eb15f15b/frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0", size = 52849 }, - { url = "https://files.pythonhosted.org/packages/3a/c8/76f23bf9ab15d5f760eb48701909645f686f9c64fbb8982674c241fbef14/frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2", size = 50583 }, - { url = "https://files.pythonhosted.org/packages/1f/22/462a3dd093d11df623179d7754a3b3269de3b42de2808cddef50ee0f4f48/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f", size = 265636 }, - { url = "https://files.pythonhosted.org/packages/80/cf/e075e407fc2ae7328155a1cd7e22f932773c8073c1fc78016607d19cc3e5/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608", size = 270214 }, - { url = "https://files.pythonhosted.org/packages/a1/58/0642d061d5de779f39c50cbb00df49682832923f3d2ebfb0fedf02d05f7f/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b", size = 273905 }, - { url = "https://files.pythonhosted.org/packages/ab/66/3fe0f5f8f2add5b4ab7aa4e199f767fd3b55da26e3ca4ce2cc36698e50c4/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840", size = 250542 }, - { url = "https://files.pythonhosted.org/packages/f6/b8/260791bde9198c87a465224e0e2bb62c4e716f5d198fc3a1dacc4895dbd1/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439", size = 267026 }, - { url = "https://files.pythonhosted.org/packages/2e/a4/3d24f88c527f08f8d44ade24eaee83b2627793fa62fa07cbb7ff7a2f7d42/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de", size = 257690 }, - { url = "https://files.pythonhosted.org/packages/de/9a/d311d660420b2beeff3459b6626f2ab4fb236d07afbdac034a4371fe696e/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641", size = 253893 }, - { url = "https://files.pythonhosted.org/packages/c6/23/e491aadc25b56eabd0f18c53bb19f3cdc6de30b2129ee0bc39cd387cd560/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e", size = 267006 }, - { url = "https://files.pythonhosted.org/packages/08/c4/ab918ce636a35fb974d13d666dcbe03969592aeca6c3ab3835acff01f79c/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9", size = 276157 }, - { url = "https://files.pythonhosted.org/packages/c0/29/3b7a0bbbbe5a34833ba26f686aabfe982924adbdcafdc294a7a129c31688/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03", size = 264642 }, - { url = "https://files.pythonhosted.org/packages/ab/42/0595b3dbffc2e82d7fe658c12d5a5bafcd7516c6bf2d1d1feb5387caa9c1/frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c", size = 44914 }, - { url = "https://files.pythonhosted.org/packages/17/c4/b7db1206a3fea44bf3b838ca61deb6f74424a8a5db1dd53ecb21da669be6/frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28", size = 51167 }, - { url = "https://files.pythonhosted.org/packages/c6/c8/a5be5b7550c10858fcf9b0ea054baccab474da77d37f1e828ce043a3a5d4/frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", size = 11901 }, -] - -[[package]] -name = "grpcio" -version = "1.67.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/53/d9282a66a5db45981499190b77790570617a604a38f3d103d0400974aeb5/grpcio-1.67.1.tar.gz", hash = "sha256:3dc2ed4cabea4dc14d5e708c2b426205956077cc5de419b4d4079315017e9732", size = 12580022 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/25/6f95bd18d5f506364379eabc0d5874873cc7dbdaf0757df8d1e82bc07a88/grpcio-1.67.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:267d1745894200e4c604958da5f856da6293f063327cb049a51fe67348e4f953", size = 5089809 }, - { url = "https://files.pythonhosted.org/packages/10/3f/d79e32e5d0354be33a12db2267c66d3cfeff700dd5ccdd09fd44a3ff4fb6/grpcio-1.67.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:85f69fdc1d28ce7cff8de3f9c67db2b0ca9ba4449644488c1e0303c146135ddb", size = 10981985 }, - { url = "https://files.pythonhosted.org/packages/21/f2/36fbc14b3542e3a1c20fb98bd60c4732c55a44e374a4eb68f91f28f14aab/grpcio-1.67.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:f26b0b547eb8d00e195274cdfc63ce64c8fc2d3e2d00b12bf468ece41a0423a0", size = 5588770 }, - { url = "https://files.pythonhosted.org/packages/0d/af/bbc1305df60c4e65de8c12820a942b5e37f9cf684ef5e49a63fbb1476a73/grpcio-1.67.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4422581cdc628f77302270ff839a44f4c24fdc57887dc2a45b7e53d8fc2376af", size = 6214476 }, - { url = "https://files.pythonhosted.org/packages/92/cf/1d4c3e93efa93223e06a5c83ac27e32935f998bc368e276ef858b8883154/grpcio-1.67.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d7616d2ded471231c701489190379e0c311ee0a6c756f3c03e6a62b95a7146e", size = 5850129 }, - { url = "https://files.pythonhosted.org/packages/ae/ca/26195b66cb253ac4d5ef59846e354d335c9581dba891624011da0e95d67b/grpcio-1.67.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8a00efecde9d6fcc3ab00c13f816313c040a28450e5e25739c24f432fc6d3c75", size = 6568489 }, - { url = "https://files.pythonhosted.org/packages/d1/94/16550ad6b3f13b96f0856ee5dfc2554efac28539ee84a51d7b14526da985/grpcio-1.67.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:699e964923b70f3101393710793289e42845791ea07565654ada0969522d0a38", size = 6149369 }, - { url = "https://files.pythonhosted.org/packages/33/0d/4c3b2587e8ad7f121b597329e6c2620374fccbc2e4e1aa3c73ccc670fde4/grpcio-1.67.1-cp312-cp312-win32.whl", hash = "sha256:4e7b904484a634a0fff132958dabdb10d63e0927398273917da3ee103e8d1f78", size = 3599176 }, - { url = "https://files.pythonhosted.org/packages/7d/36/0c03e2d80db69e2472cf81c6123aa7d14741de7cf790117291a703ae6ae1/grpcio-1.67.1-cp312-cp312-win_amd64.whl", hash = "sha256:5721e66a594a6c4204458004852719b38f3d5522082be9061d6510b455c90afc", size = 4346574 }, - { url = "https://files.pythonhosted.org/packages/12/d2/2f032b7a153c7723ea3dea08bffa4bcaca9e0e5bdf643ce565b76da87461/grpcio-1.67.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:aa0162e56fd10a5547fac8774c4899fc3e18c1aa4a4759d0ce2cd00d3696ea6b", size = 5091487 }, - { url = "https://files.pythonhosted.org/packages/d0/ae/ea2ff6bd2475a082eb97db1104a903cf5fc57c88c87c10b3c3f41a184fc0/grpcio-1.67.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:beee96c8c0b1a75d556fe57b92b58b4347c77a65781ee2ac749d550f2a365dc1", size = 10943530 }, - { url = "https://files.pythonhosted.org/packages/07/62/646be83d1a78edf8d69b56647327c9afc223e3140a744c59b25fbb279c3b/grpcio-1.67.1-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:a93deda571a1bf94ec1f6fcda2872dad3ae538700d94dc283c672a3b508ba3af", size = 5589079 }, - { url = "https://files.pythonhosted.org/packages/d0/25/71513d0a1b2072ce80d7f5909a93596b7ed10348b2ea4fdcbad23f6017bf/grpcio-1.67.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e6f255980afef598a9e64a24efce87b625e3e3c80a45162d111a461a9f92955", size = 6213542 }, - { url = "https://files.pythonhosted.org/packages/76/9a/d21236297111052dcb5dc85cd77dc7bf25ba67a0f55ae028b2af19a704bc/grpcio-1.67.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e838cad2176ebd5d4a8bb03955138d6589ce9e2ce5d51c3ada34396dbd2dba8", size = 5850211 }, - { url = "https://files.pythonhosted.org/packages/2d/fe/70b1da9037f5055be14f359026c238821b9bcf6ca38a8d760f59a589aacd/grpcio-1.67.1-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:a6703916c43b1d468d0756c8077b12017a9fcb6a1ef13faf49e67d20d7ebda62", size = 6572129 }, - { url = "https://files.pythonhosted.org/packages/74/0d/7df509a2cd2a54814598caf2fb759f3e0b93764431ff410f2175a6efb9e4/grpcio-1.67.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:917e8d8994eed1d86b907ba2a61b9f0aef27a2155bca6cbb322430fc7135b7bb", size = 6149819 }, - { url = "https://files.pythonhosted.org/packages/0a/08/bc3b0155600898fd10f16b79054e1cca6cb644fa3c250c0fe59385df5e6f/grpcio-1.67.1-cp313-cp313-win32.whl", hash = "sha256:e279330bef1744040db8fc432becc8a727b84f456ab62b744d3fdb83f327e121", size = 3596561 }, - { url = "https://files.pythonhosted.org/packages/5a/96/44759eca966720d0f3e1b105c43f8ad4590c97bf8eb3cd489656e9590baa/grpcio-1.67.1-cp313-cp313-win_amd64.whl", hash = "sha256:fa0c739ad8b1996bd24823950e3cb5152ae91fca1c09cc791190bf1627ffefba", size = 4346042 }, -] - -[[package]] -name = "h11" -version = "0.14.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, -] - -[[package]] -name = "httpcore" -version = "1.0.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "h11" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b6/44/ed0fa6a17845fb033bd885c03e842f08c1b9406c86a2e60ac1ae1b9206a6/httpcore-1.0.6.tar.gz", hash = "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f", size = 85180 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/06/89/b161908e2f51be56568184aeb4a880fd287178d176fd1c860d2217f41106/httpcore-1.0.6-py3-none-any.whl", hash = "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f", size = 78011 }, -] - -[[package]] -name = "httpx" -version = "0.27.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "certifi" }, - { name = "httpcore" }, - { name = "idna" }, - { name = "sniffio" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/78/82/08f8c936781f67d9e6b9eeb8a0c8b4e406136ea4c3d1f89a5db71d42e0e6/httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2", size = 144189 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/56/95/9377bcb415797e44274b51d46e3249eba641711cf3348050f76ee7b15ffc/httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0", size = 76395 }, -] - -[[package]] -name = "idna" -version = "3.10" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, -] - -[[package]] -name = "iniconfig" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, -] - -[[package]] -name = "invoke" -version = "2.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/42/127e6d792884ab860defc3f4d80a8f9812e48ace584ffc5a346de58cdc6c/invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5", size = 299835 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/66/7f8c48009c72d73bc6bbe6eb87ac838d6a526146f7dab14af671121eb379/invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820", size = 160274 }, -] - -[[package]] -name = "jumpstarter" -version = "0.0.4.dev62+g36d1217" -source = { git = "https://github.com/jumpstarter-dev/jumpstarter.git#36d1217db1be316faa449df781a8c2d3c37a3f18" } -dependencies = [ - { name = "aiohttp" }, - { name = "anyio" }, - { name = "click" }, - { name = "fabric" }, - { name = "grpcio" }, - { name = "httpx" }, - { name = "opendal" }, - { name = "pexpect" }, - { name = "protobuf" }, - { name = "pydantic" }, - { name = "pyserial" }, - { name = "pyyaml" }, - { name = "tqdm" }, - { name = "wsproto" }, -] - -[[package]] -name = "jumpstarter-driver-tftp" -version = "0.1.0" -source = { editable = "." } -dependencies = [ - { name = "anyio" }, - { name = "jumpstarter" }, - { name = "tftpy" }, -] - -[package.dev-dependencies] -dev = [ - { name = "pytest" }, - { name = "pytest-cov" }, - { name = "ruff" }, -] - -[package.metadata] -requires-dist = [ - { name = "anyio", specifier = ">=4.6.2.post1" }, - { name = "jumpstarter", git = "https://github.com/jumpstarter-dev/jumpstarter.git" }, - { name = "tftpy", specifier = ">=0.8.2" }, -] - -[package.metadata.requires-dev] -dev = [ - { name = "pytest", specifier = ">=8.3.3" }, - { name = "pytest-cov", specifier = ">=6.0.0" }, - { name = "ruff", specifier = ">=0.7.1" }, -] - -[[package]] -name = "multidict" -version = "6.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/be/504b89a5e9ca731cd47487e91c469064f8ae5af93b7259758dcfc2b9c848/multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", size = 64002 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/16/92057c74ba3b96d5e211b553895cd6dc7cc4d1e43d9ab8fafc727681ef71/multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", size = 48713 }, - { url = "https://files.pythonhosted.org/packages/94/3d/37d1b8893ae79716179540b89fc6a0ee56b4a65fcc0d63535c6f5d96f217/multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", size = 29516 }, - { url = "https://files.pythonhosted.org/packages/a2/12/adb6b3200c363062f805275b4c1e656be2b3681aada66c80129932ff0bae/multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", size = 29557 }, - { url = "https://files.pythonhosted.org/packages/47/e9/604bb05e6e5bce1e6a5cf80a474e0f072e80d8ac105f1b994a53e0b28c42/multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", size = 130170 }, - { url = "https://files.pythonhosted.org/packages/7e/13/9efa50801785eccbf7086b3c83b71a4fb501a4d43549c2f2f80b8787d69f/multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", size = 134836 }, - { url = "https://files.pythonhosted.org/packages/bf/0f/93808b765192780d117814a6dfcc2e75de6dcc610009ad408b8814dca3ba/multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", size = 133475 }, - { url = "https://files.pythonhosted.org/packages/d3/c8/529101d7176fe7dfe1d99604e48d69c5dfdcadb4f06561f465c8ef12b4df/multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", size = 131049 }, - { url = "https://files.pythonhosted.org/packages/ca/0c/fc85b439014d5a58063e19c3a158a889deec399d47b5269a0f3b6a2e28bc/multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", size = 120370 }, - { url = "https://files.pythonhosted.org/packages/db/46/d4416eb20176492d2258fbd47b4abe729ff3b6e9c829ea4236f93c865089/multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", size = 125178 }, - { url = "https://files.pythonhosted.org/packages/5b/46/73697ad7ec521df7de5531a32780bbfd908ded0643cbe457f981a701457c/multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", size = 119567 }, - { url = "https://files.pythonhosted.org/packages/cd/ed/51f060e2cb0e7635329fa6ff930aa5cffa17f4c7f5c6c3ddc3500708e2f2/multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", size = 129822 }, - { url = "https://files.pythonhosted.org/packages/df/9e/ee7d1954b1331da3eddea0c4e08d9142da5f14b1321c7301f5014f49d492/multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", size = 128656 }, - { url = "https://files.pythonhosted.org/packages/77/00/8538f11e3356b5d95fa4b024aa566cde7a38aa7a5f08f4912b32a037c5dc/multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", size = 125360 }, - { url = "https://files.pythonhosted.org/packages/be/05/5d334c1f2462d43fec2363cd00b1c44c93a78c3925d952e9a71caf662e96/multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", size = 26382 }, - { url = "https://files.pythonhosted.org/packages/a3/bf/f332a13486b1ed0496d624bcc7e8357bb8053823e8cd4b9a18edc1d97e73/multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", size = 28529 }, - { url = "https://files.pythonhosted.org/packages/22/67/1c7c0f39fe069aa4e5d794f323be24bf4d33d62d2a348acdb7991f8f30db/multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", size = 48771 }, - { url = "https://files.pythonhosted.org/packages/3c/25/c186ee7b212bdf0df2519eacfb1981a017bda34392c67542c274651daf23/multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", size = 29533 }, - { url = "https://files.pythonhosted.org/packages/67/5e/04575fd837e0958e324ca035b339cea174554f6f641d3fb2b4f2e7ff44a2/multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", size = 29595 }, - { url = "https://files.pythonhosted.org/packages/d3/b2/e56388f86663810c07cfe4a3c3d87227f3811eeb2d08450b9e5d19d78876/multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", size = 130094 }, - { url = "https://files.pythonhosted.org/packages/6c/ee/30ae9b4186a644d284543d55d491fbd4239b015d36b23fea43b4c94f7052/multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", size = 134876 }, - { url = "https://files.pythonhosted.org/packages/84/c7/70461c13ba8ce3c779503c70ec9d0345ae84de04521c1f45a04d5f48943d/multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", size = 133500 }, - { url = "https://files.pythonhosted.org/packages/4a/9f/002af221253f10f99959561123fae676148dd730e2daa2cd053846a58507/multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", size = 131099 }, - { url = "https://files.pythonhosted.org/packages/82/42/d1c7a7301d52af79d88548a97e297f9d99c961ad76bbe6f67442bb77f097/multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", size = 120403 }, - { url = "https://files.pythonhosted.org/packages/68/f3/471985c2c7ac707547553e8f37cff5158030d36bdec4414cb825fbaa5327/multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", size = 125348 }, - { url = "https://files.pythonhosted.org/packages/67/2c/e6df05c77e0e433c214ec1d21ddd203d9a4770a1f2866a8ca40a545869a0/multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", size = 119673 }, - { url = "https://files.pythonhosted.org/packages/c5/cd/bc8608fff06239c9fb333f9db7743a1b2eafe98c2666c9a196e867a3a0a4/multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", size = 129927 }, - { url = "https://files.pythonhosted.org/packages/44/8e/281b69b7bc84fc963a44dc6e0bbcc7150e517b91df368a27834299a526ac/multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", size = 128711 }, - { url = "https://files.pythonhosted.org/packages/12/a4/63e7cd38ed29dd9f1881d5119f272c898ca92536cdb53ffe0843197f6c85/multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", size = 125519 }, - { url = "https://files.pythonhosted.org/packages/38/e0/4f5855037a72cd8a7a2f60a3952d9aa45feedb37ae7831642102604e8a37/multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", size = 26426 }, - { url = "https://files.pythonhosted.org/packages/7e/a5/17ee3a4db1e310b7405f5d25834460073a8ccd86198ce044dfaf69eac073/multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", size = 28531 }, - { url = "https://files.pythonhosted.org/packages/99/b7/b9e70fde2c0f0c9af4cc5277782a89b66d35948ea3369ec9f598358c3ac5/multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", size = 10051 }, -] - -[[package]] -name = "opendal" -version = "0.45.11" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b7/c2/9bff01d8e59c1b168d3ce0c642bbe61841118a330e10d1d4cbf8a0ffc09c/opendal-0.45.11.tar.gz", hash = "sha256:caad0dc4ce3d59d52b224d49f1edaf5efb65bbd18f5476957130f41944dabb33", size = 739998 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/dc/3ddc7f0eb393cd1c5c7b700fd2d9557cf5dd283ab98ab0a9093446c3011d/opendal-0.45.11-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:31cb8fff90775c72dd55e7ce12df23784a19b7b8baaa41dcbc1a2e983f3e3e6b", size = 29365212 }, - { url = "https://files.pythonhosted.org/packages/7e/4b/54b50be2ecdcc6353e54d2809add3bb5ae5df982c22ba137c7d7ee4723f9/opendal-0.45.11-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:718b782ff2909ca2599c0de326f0fa613063a2a6b18738d6702844c963536e0b", size = 15800423 }, - { url = "https://files.pythonhosted.org/packages/cd/9c/b92d6bf214f039aa43ec8a35c1a03eb422ea7484088aed3e55fd23626a4d/opendal-0.45.11-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad22109a3ad837b34ee181222c5c5cd53888f57a57253259024357f668e8224a", size = 15459912 }, - { url = "https://files.pythonhosted.org/packages/3d/61/a9dfe04443585967e313c68083644bffcb485cfc00f639845ff99e5b56c4/opendal-0.45.11-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e984f317ab871dc75b65028ec0c1451cc6faa41d105443b749d7d6a3440cd31d", size = 16334398 }, - { url = "https://files.pythonhosted.org/packages/f8/68/80b17a403dcddd8be342b348cb007ef2c151d4fb7fa9f9c71fe354a5ac4b/opendal-0.45.11-cp311-abi3-win_amd64.whl", hash = "sha256:9bd4bdac96a6f0d21cc933f0ea11100c0c8be0c157e0d81f138a66a56c8ca789", size = 14395052 }, -] - -[[package]] -name = "packaging" -version = "24.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, -] - -[[package]] -name = "paramiko" -version = "3.5.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "bcrypt" }, - { name = "cryptography" }, - { name = "pynacl" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1b/0f/c00296e36ff7485935b83d466c4f2cf5934b84b0ad14e81796e1d9d3609b/paramiko-3.5.0.tar.gz", hash = "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124", size = 1704305 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/66/14b2c030fcce69cba482d205c2d1462ca5c77303a263260dcb1192801c85/paramiko-3.5.0-py3-none-any.whl", hash = "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9", size = 227143 }, -] - -[[package]] -name = "pexpect" -version = "4.9.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ptyprocess" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772 }, -] - -[[package]] -name = "pluggy" -version = "1.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, -] - -[[package]] -name = "propcache" -version = "0.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a9/4d/5e5a60b78dbc1d464f8a7bbaeb30957257afdc8512cbb9dfd5659304f5cd/propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70", size = 40951 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/46/a41ca1097769fc548fc9216ec4c1471b772cc39720eb47ed7e38ef0006a9/propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2", size = 80800 }, - { url = "https://files.pythonhosted.org/packages/75/4f/93df46aab9cc473498ff56be39b5f6ee1e33529223d7a4d8c0a6101a9ba2/propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7", size = 46443 }, - { url = "https://files.pythonhosted.org/packages/0b/17/308acc6aee65d0f9a8375e36c4807ac6605d1f38074b1581bd4042b9fb37/propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8", size = 45676 }, - { url = "https://files.pythonhosted.org/packages/65/44/626599d2854d6c1d4530b9a05e7ff2ee22b790358334b475ed7c89f7d625/propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793", size = 246191 }, - { url = "https://files.pythonhosted.org/packages/f2/df/5d996d7cb18df076debae7d76ac3da085c0575a9f2be6b1f707fe227b54c/propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09", size = 251791 }, - { url = "https://files.pythonhosted.org/packages/2e/6d/9f91e5dde8b1f662f6dd4dff36098ed22a1ef4e08e1316f05f4758f1576c/propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89", size = 253434 }, - { url = "https://files.pythonhosted.org/packages/3c/e9/1b54b7e26f50b3e0497cd13d3483d781d284452c2c50dd2a615a92a087a3/propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e", size = 248150 }, - { url = "https://files.pythonhosted.org/packages/a7/ef/a35bf191c8038fe3ce9a414b907371c81d102384eda5dbafe6f4dce0cf9b/propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9", size = 233568 }, - { url = "https://files.pythonhosted.org/packages/97/d9/d00bb9277a9165a5e6d60f2142cd1a38a750045c9c12e47ae087f686d781/propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4", size = 229874 }, - { url = "https://files.pythonhosted.org/packages/8e/78/c123cf22469bdc4b18efb78893e69c70a8b16de88e6160b69ca6bdd88b5d/propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c", size = 225857 }, - { url = "https://files.pythonhosted.org/packages/31/1b/fd6b2f1f36d028820d35475be78859d8c89c8f091ad30e377ac49fd66359/propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887", size = 227604 }, - { url = "https://files.pythonhosted.org/packages/99/36/b07be976edf77a07233ba712e53262937625af02154353171716894a86a6/propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57", size = 238430 }, - { url = "https://files.pythonhosted.org/packages/0d/64/5822f496c9010e3966e934a011ac08cac8734561842bc7c1f65586e0683c/propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23", size = 244814 }, - { url = "https://files.pythonhosted.org/packages/fd/bd/8657918a35d50b18a9e4d78a5df7b6c82a637a311ab20851eef4326305c1/propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348", size = 235922 }, - { url = "https://files.pythonhosted.org/packages/a8/6f/ec0095e1647b4727db945213a9f395b1103c442ef65e54c62e92a72a3f75/propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5", size = 40177 }, - { url = "https://files.pythonhosted.org/packages/20/a2/bd0896fdc4f4c1db46d9bc361c8c79a9bf08ccc08ba054a98e38e7ba1557/propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3", size = 44446 }, - { url = "https://files.pythonhosted.org/packages/a8/a7/5f37b69197d4f558bfef5b4bceaff7c43cc9b51adf5bd75e9081d7ea80e4/propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7", size = 78120 }, - { url = "https://files.pythonhosted.org/packages/c8/cd/48ab2b30a6b353ecb95a244915f85756d74f815862eb2ecc7a518d565b48/propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763", size = 45127 }, - { url = "https://files.pythonhosted.org/packages/a5/ba/0a1ef94a3412aab057bd996ed5f0ac7458be5bf469e85c70fa9ceb43290b/propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d", size = 44419 }, - { url = "https://files.pythonhosted.org/packages/b4/6c/ca70bee4f22fa99eacd04f4d2f1699be9d13538ccf22b3169a61c60a27fa/propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a", size = 229611 }, - { url = "https://files.pythonhosted.org/packages/19/70/47b872a263e8511ca33718d96a10c17d3c853aefadeb86dc26e8421184b9/propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b", size = 234005 }, - { url = "https://files.pythonhosted.org/packages/4f/be/3b0ab8c84a22e4a3224719099c1229ddfdd8a6a1558cf75cb55ee1e35c25/propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb", size = 237270 }, - { url = "https://files.pythonhosted.org/packages/04/d8/f071bb000d4b8f851d312c3c75701e586b3f643fe14a2e3409b1b9ab3936/propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf", size = 231877 }, - { url = "https://files.pythonhosted.org/packages/93/e7/57a035a1359e542bbb0a7df95aad6b9871ebee6dce2840cb157a415bd1f3/propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2", size = 217848 }, - { url = "https://files.pythonhosted.org/packages/f0/93/d1dea40f112ec183398fb6c42fde340edd7bab202411c4aa1a8289f461b6/propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f", size = 216987 }, - { url = "https://files.pythonhosted.org/packages/62/4c/877340871251145d3522c2b5d25c16a1690ad655fbab7bb9ece6b117e39f/propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136", size = 212451 }, - { url = "https://files.pythonhosted.org/packages/7c/bb/a91b72efeeb42906ef58ccf0cdb87947b54d7475fee3c93425d732f16a61/propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325", size = 212879 }, - { url = "https://files.pythonhosted.org/packages/9b/7f/ee7fea8faac57b3ec5d91ff47470c6c5d40d7f15d0b1fccac806348fa59e/propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44", size = 222288 }, - { url = "https://files.pythonhosted.org/packages/ff/d7/acd67901c43d2e6b20a7a973d9d5fd543c6e277af29b1eb0e1f7bd7ca7d2/propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83", size = 228257 }, - { url = "https://files.pythonhosted.org/packages/8d/6f/6272ecc7a8daad1d0754cfc6c8846076a8cb13f810005c79b15ce0ef0cf2/propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544", size = 221075 }, - { url = "https://files.pythonhosted.org/packages/7c/bd/c7a6a719a6b3dd8b3aeadb3675b5783983529e4a3185946aa444d3e078f6/propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032", size = 39654 }, - { url = "https://files.pythonhosted.org/packages/88/e7/0eef39eff84fa3e001b44de0bd41c7c0e3432e7648ffd3d64955910f002d/propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e", size = 43705 }, - { url = "https://files.pythonhosted.org/packages/3d/b6/e6d98278f2d49b22b4d033c9f792eda783b9ab2094b041f013fc69bcde87/propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036", size = 11603 }, -] - -[[package]] -name = "protobuf" -version = "5.28.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/74/6e/e69eb906fddcb38f8530a12f4b410699972ab7ced4e21524ece9d546ac27/protobuf-5.28.3.tar.gz", hash = "sha256:64badbc49180a5e401f373f9ce7ab1d18b63f7dd4a9cdc43c92b9f0b481cef7b", size = 422479 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/c5/05163fad52d7c43e124a545f1372d18266db36036377ad29de4271134a6a/protobuf-5.28.3-cp310-abi3-win32.whl", hash = "sha256:0c4eec6f987338617072592b97943fdbe30d019c56126493111cf24344c1cc24", size = 419624 }, - { url = "https://files.pythonhosted.org/packages/9c/4c/4563ebe001ff30dca9d7ed12e471fa098d9759712980cde1fd03a3a44fb7/protobuf-5.28.3-cp310-abi3-win_amd64.whl", hash = "sha256:91fba8f445723fcf400fdbe9ca796b19d3b1242cd873907979b9ed71e4afe868", size = 431464 }, - { url = "https://files.pythonhosted.org/packages/1c/f2/baf397f3dd1d3e4af7e3f5a0382b868d25ac068eefe1ebde05132333436c/protobuf-5.28.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a3f6857551e53ce35e60b403b8a27b0295f7d6eb63d10484f12bc6879c715687", size = 414743 }, - { url = "https://files.pythonhosted.org/packages/85/50/cd61a358ba1601f40e7d38bcfba22e053f40ef2c50d55b55926aecc8fec7/protobuf-5.28.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:3fa2de6b8b29d12c61911505d893afe7320ce7ccba4df913e2971461fa36d584", size = 316511 }, - { url = "https://files.pythonhosted.org/packages/5d/ae/3257b09328c0b4e59535e497b0c7537d4954038bdd53a2f0d2f49d15a7c4/protobuf-5.28.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:712319fbdddb46f21abb66cd33cb9e491a5763b2febd8f228251add221981135", size = 316624 }, - { url = "https://files.pythonhosted.org/packages/ad/c3/2377c159e28ea89a91cf1ca223f827ae8deccb2c9c401e5ca233cd73002f/protobuf-5.28.3-py3-none-any.whl", hash = "sha256:cee1757663fa32a1ee673434fcf3bf24dd54763c79690201208bafec62f19eed", size = 169511 }, -] - -[[package]] -name = "ptyprocess" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993 }, -] - -[[package]] -name = "pycparser" -version = "2.22" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 }, -] - -[[package]] -name = "pydantic" -version = "2.9.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "annotated-types" }, - { name = "pydantic-core" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a9/b7/d9e3f12af310e1120c21603644a1cd86f59060e040ec5c3a80b8f05fae30/pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f", size = 769917 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/df/e4/ba44652d562cbf0bf320e0f3810206149c8a4e99cdbf66da82e97ab53a15/pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12", size = 434928 }, -] - -[[package]] -name = "pydantic-core" -version = "2.23.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e2/aa/6b6a9b9f8537b872f552ddd46dd3da230367754b6f707b8e1e963f515ea3/pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863", size = 402156 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/74/7b/8e315f80666194b354966ec84b7d567da77ad927ed6323db4006cf915f3f/pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231", size = 1856459 }, - { url = "https://files.pythonhosted.org/packages/14/de/866bdce10ed808323d437612aca1ec9971b981e1c52e5e42ad9b8e17a6f6/pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee", size = 1770007 }, - { url = "https://files.pythonhosted.org/packages/dc/69/8edd5c3cd48bb833a3f7ef9b81d7666ccddd3c9a635225214e044b6e8281/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87", size = 1790245 }, - { url = "https://files.pythonhosted.org/packages/80/33/9c24334e3af796ce80d2274940aae38dd4e5676298b4398eff103a79e02d/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8", size = 1801260 }, - { url = "https://files.pythonhosted.org/packages/a5/6f/e9567fd90104b79b101ca9d120219644d3314962caa7948dd8b965e9f83e/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327", size = 1996872 }, - { url = "https://files.pythonhosted.org/packages/2d/ad/b5f0fe9e6cfee915dd144edbd10b6e9c9c9c9d7a56b69256d124b8ac682e/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2", size = 2661617 }, - { url = "https://files.pythonhosted.org/packages/06/c8/7d4b708f8d05a5cbfda3243aad468052c6e99de7d0937c9146c24d9f12e9/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36", size = 2071831 }, - { url = "https://files.pythonhosted.org/packages/89/4d/3079d00c47f22c9a9a8220db088b309ad6e600a73d7a69473e3a8e5e3ea3/pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126", size = 1917453 }, - { url = "https://files.pythonhosted.org/packages/e9/88/9df5b7ce880a4703fcc2d76c8c2d8eb9f861f79d0c56f4b8f5f2607ccec8/pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e", size = 1968793 }, - { url = "https://files.pythonhosted.org/packages/e3/b9/41f7efe80f6ce2ed3ee3c2dcfe10ab7adc1172f778cc9659509a79518c43/pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24", size = 2116872 }, - { url = "https://files.pythonhosted.org/packages/63/08/b59b7a92e03dd25554b0436554bf23e7c29abae7cce4b1c459cd92746811/pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84", size = 1738535 }, - { url = "https://files.pythonhosted.org/packages/88/8d/479293e4d39ab409747926eec4329de5b7129beaedc3786eca070605d07f/pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9", size = 1917992 }, - { url = "https://files.pythonhosted.org/packages/ad/ef/16ee2df472bf0e419b6bc68c05bf0145c49247a1095e85cee1463c6a44a1/pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc", size = 1856143 }, - { url = "https://files.pythonhosted.org/packages/da/fa/bc3dbb83605669a34a93308e297ab22be82dfb9dcf88c6cf4b4f264e0a42/pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd", size = 1770063 }, - { url = "https://files.pythonhosted.org/packages/4e/48/e813f3bbd257a712303ebdf55c8dc46f9589ec74b384c9f652597df3288d/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05", size = 1790013 }, - { url = "https://files.pythonhosted.org/packages/b4/e0/56eda3a37929a1d297fcab1966db8c339023bcca0b64c5a84896db3fcc5c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d", size = 1801077 }, - { url = "https://files.pythonhosted.org/packages/04/be/5e49376769bfbf82486da6c5c1683b891809365c20d7c7e52792ce4c71f3/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510", size = 1996782 }, - { url = "https://files.pythonhosted.org/packages/bc/24/e3ee6c04f1d58cc15f37bcc62f32c7478ff55142b7b3e6d42ea374ea427c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6", size = 2661375 }, - { url = "https://files.pythonhosted.org/packages/c1/f8/11a9006de4e89d016b8de74ebb1db727dc100608bb1e6bbe9d56a3cbbcce/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b", size = 2071635 }, - { url = "https://files.pythonhosted.org/packages/7c/45/bdce5779b59f468bdf262a5bc9eecbae87f271c51aef628d8c073b4b4b4c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327", size = 1916994 }, - { url = "https://files.pythonhosted.org/packages/d8/fa/c648308fe711ee1f88192cad6026ab4f925396d1293e8356de7e55be89b5/pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6", size = 1968877 }, - { url = "https://files.pythonhosted.org/packages/16/16/b805c74b35607d24d37103007f899abc4880923b04929547ae68d478b7f4/pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f", size = 2116814 }, - { url = "https://files.pythonhosted.org/packages/d1/58/5305e723d9fcdf1c5a655e6a4cc2a07128bf644ff4b1d98daf7a9dbf57da/pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769", size = 1738360 }, - { url = "https://files.pythonhosted.org/packages/a5/ae/e14b0ff8b3f48e02394d8acd911376b7b66e164535687ef7dc24ea03072f/pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5", size = 1919411 }, -] - -[[package]] -name = "pynacl" -version = "1.5.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cffi" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a7/22/27582568be639dfe22ddb3902225f91f2f17ceff88ce80e4db396c8986da/PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba", size = 3392854 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1", size = 349920 }, - { url = "https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92", size = 601722 }, - { url = "https://files.pythonhosted.org/packages/5d/70/87a065c37cca41a75f2ce113a5a2c2aa7533be648b184ade58971b5f7ccc/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394", size = 680087 }, - { url = "https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d", size = 856678 }, - { url = "https://files.pythonhosted.org/packages/66/28/ca86676b69bf9f90e710571b67450508484388bfce09acf8a46f0b8c785f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858", size = 1133660 }, - { url = "https://files.pythonhosted.org/packages/3d/85/c262db650e86812585e2bc59e497a8f59948a005325a11bbbc9ecd3fe26b/PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b", size = 663824 }, - { url = "https://files.pythonhosted.org/packages/fd/1a/cc308a884bd299b651f1633acb978e8596c71c33ca85e9dc9fa33a5399b9/PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff", size = 1117912 }, - { url = "https://files.pythonhosted.org/packages/25/2d/b7df6ddb0c2a33afdb358f8af6ea3b8c4d1196ca45497dd37a56f0c122be/PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543", size = 204624 }, - { url = "https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93", size = 212141 }, -] - -[[package]] -name = "pyserial" -version = "3.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1e/7d/ae3f0a63f41e4d2f6cb66a5b57197850f919f59e558159a4dd3a818f5082/pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb", size = 159125 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0", size = 90585 }, -] - -[[package]] -name = "pytest" -version = "8.3.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "iniconfig" }, - { name = "packaging" }, - { name = "pluggy" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, -] - -[[package]] -name = "pytest-cov" -version = "6.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "coverage" }, - { name = "pytest" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 }, -] - -[[package]] -name = "pyyaml" -version = "6.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, - { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, - { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, - { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, - { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, - { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, - { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, - { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, - { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, - { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, - { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, - { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, - { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, - { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, - { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, - { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, - { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, - { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, -] - -[[package]] -name = "ruff" -version = "0.8.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5e/2b/01245f4f3a727d60bebeacd7ee6d22586c7f62380a2597ddb22c2f45d018/ruff-0.8.2.tar.gz", hash = "sha256:b84f4f414dda8ac7f75075c1fa0b905ac0ff25361f42e6d5da681a465e0f78e5", size = 3349020 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/91/29/366be70216dba1731a00a41f2f030822b0c96c7c4f3b2c0cdce15cbace74/ruff-0.8.2-py3-none-linux_armv6l.whl", hash = "sha256:c49ab4da37e7c457105aadfd2725e24305ff9bc908487a9bf8d548c6dad8bb3d", size = 10530649 }, - { url = "https://files.pythonhosted.org/packages/63/82/a733956540bb388f00df5a3e6a02467b16c0e529132625fe44ce4c5fb9c7/ruff-0.8.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ec016beb69ac16be416c435828be702ee694c0d722505f9c1f35e1b9c0cc1bf5", size = 10274069 }, - { url = "https://files.pythonhosted.org/packages/3d/12/0b3aa14d1d71546c988a28e1b412981c1b80c8a1072e977a2f30c595cc4a/ruff-0.8.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f05cdf8d050b30e2ba55c9b09330b51f9f97d36d4673213679b965d25a785f3c", size = 9909400 }, - { url = "https://files.pythonhosted.org/packages/23/08/f9f08cefb7921784c891c4151cce6ed357ff49e84b84978440cffbc87408/ruff-0.8.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60f578c11feb1d3d257b2fb043ddb47501ab4816e7e221fbb0077f0d5d4e7b6f", size = 10766782 }, - { url = "https://files.pythonhosted.org/packages/e4/71/bf50c321ec179aa420c8ec40adac5ae9cc408d4d37283a485b19a2331ceb/ruff-0.8.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cbd5cf9b0ae8f30eebc7b360171bd50f59ab29d39f06a670b3e4501a36ba5897", size = 10286316 }, - { url = "https://files.pythonhosted.org/packages/f2/83/c82688a2a6117539aea0ce63fdf6c08e60fe0202779361223bcd7f40bd74/ruff-0.8.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b402ddee3d777683de60ff76da801fa7e5e8a71038f57ee53e903afbcefdaa58", size = 11338270 }, - { url = "https://files.pythonhosted.org/packages/7f/d7/bc6a45e5a22e627640388e703160afb1d77c572b1d0fda8b4349f334fc66/ruff-0.8.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:705832cd7d85605cb7858d8a13d75993c8f3ef1397b0831289109e953d833d29", size = 12058579 }, - { url = "https://files.pythonhosted.org/packages/da/3b/64150c93946ec851e6f1707ff586bb460ca671581380c919698d6a9267dc/ruff-0.8.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:32096b41aaf7a5cc095fa45b4167b890e4c8d3fd217603f3634c92a541de7248", size = 11615172 }, - { url = "https://files.pythonhosted.org/packages/e4/9e/cf12b697ea83cfe92ec4509ae414dc4c9b38179cc681a497031f0d0d9a8e/ruff-0.8.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e769083da9439508833cfc7c23e351e1809e67f47c50248250ce1ac52c21fb93", size = 12882398 }, - { url = "https://files.pythonhosted.org/packages/a9/27/96d10863accf76a9c97baceac30b0a52d917eb985a8ac058bd4636aeede0/ruff-0.8.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fe716592ae8a376c2673fdfc1f5c0c193a6d0411f90a496863c99cd9e2ae25d", size = 11176094 }, - { url = "https://files.pythonhosted.org/packages/eb/10/cd2fd77d4a4e7f03c29351be0f53278a393186b540b99df68beb5304fddd/ruff-0.8.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:81c148825277e737493242b44c5388a300584d73d5774defa9245aaef55448b0", size = 10771884 }, - { url = "https://files.pythonhosted.org/packages/71/5d/beabb2ff18870fc4add05fa3a69a4cb1b1d2d6f83f3cf3ae5ab0d52f455d/ruff-0.8.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d261d7850c8367704874847d95febc698a950bf061c9475d4a8b7689adc4f7fa", size = 10382535 }, - { url = "https://files.pythonhosted.org/packages/ae/29/6b3fdf3ad3e35b28d87c25a9ff4c8222ad72485ab783936b2b267250d7a7/ruff-0.8.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1ca4e3a87496dc07d2427b7dd7ffa88a1e597c28dad65ae6433ecb9f2e4f022f", size = 10886995 }, - { url = "https://files.pythonhosted.org/packages/e9/dc/859d889b4d9356a1a2cdbc1e4a0dda94052bc5b5300098647e51a58c430b/ruff-0.8.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:729850feed82ef2440aa27946ab39c18cb4a8889c1128a6d589ffa028ddcfc22", size = 11220750 }, - { url = "https://files.pythonhosted.org/packages/0b/08/e8f519f61f1d624264bfd6b8829e4c5f31c3c61193bc3cff1f19dbe7626a/ruff-0.8.2-py3-none-win32.whl", hash = "sha256:ac42caaa0411d6a7d9594363294416e0e48fc1279e1b0e948391695db2b3d5b1", size = 8729396 }, - { url = "https://files.pythonhosted.org/packages/f8/d4/ba1c7ab72aba37a2b71fe48ab95b80546dbad7a7f35ea28cf66fc5cea5f6/ruff-0.8.2-py3-none-win_amd64.whl", hash = "sha256:2aae99ec70abf43372612a838d97bfe77d45146254568d94926e8ed5bbb409ea", size = 9594729 }, - { url = "https://files.pythonhosted.org/packages/23/34/db20e12d3db11b8a2a8874258f0f6d96a9a4d631659d54575840557164c8/ruff-0.8.2-py3-none-win_arm64.whl", hash = "sha256:fb88e2a506b70cfbc2de6fae6681c4f944f7dd5f2fe87233a7233d888bad73e8", size = 9035131 }, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, -] - -[[package]] -name = "tftpy" -version = "0.8.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c1/8f/4325ea65896b59cbc861aee971b7095dcbf2f753b30b2ae0da389166e444/tftpy-0.8.2.tar.gz", hash = "sha256:e1d1a680efd88eba176b351175844253067392a9b0f8b81588e3ff2b9e7bbb5b", size = 34036 } - -[[package]] -name = "tqdm" -version = "4.66.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e9/34/bef135b27fe1864993a5284ad001157ee9b5538e859ac90f5b0e8cc8c9ec/tqdm-4.66.6.tar.gz", hash = "sha256:4bdd694238bef1485ce839d67967ab50af8f9272aab687c0d7702a01da0be090", size = 169533 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/41/73/02342de9c2d20922115f787e101527b831c0cffd2105c946c4a4826bcfd4/tqdm-4.66.6-py3-none-any.whl", hash = "sha256:223e8b5359c2efc4b30555531f09e9f2f3589bcd7fdd389271191031b49b7a63", size = 78326 }, -] - -[[package]] -name = "typing-extensions" -version = "4.12.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, -] - -[[package]] -name = "wrapt" -version = "1.16.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/95/4c/063a912e20bcef7124e0df97282a8af3ff3e4b603ce84c481d6d7346be0a/wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d", size = 53972 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/17/224132494c1e23521868cdd57cd1e903f3b6a7ba6996b7b8f077ff8ac7fe/wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b", size = 37614 }, - { url = "https://files.pythonhosted.org/packages/6a/d7/cfcd73e8f4858079ac59d9db1ec5a1349bc486ae8e9ba55698cc1f4a1dff/wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36", size = 38316 }, - { url = "https://files.pythonhosted.org/packages/7e/79/5ff0a5c54bda5aec75b36453d06be4f83d5cd4932cc84b7cb2b52cee23e2/wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73", size = 86322 }, - { url = "https://files.pythonhosted.org/packages/c4/81/e799bf5d419f422d8712108837c1d9bf6ebe3cb2a81ad94413449543a923/wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809", size = 79055 }, - { url = "https://files.pythonhosted.org/packages/62/62/30ca2405de6a20448ee557ab2cd61ab9c5900be7cbd18a2639db595f0b98/wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b", size = 87291 }, - { url = "https://files.pythonhosted.org/packages/49/4e/5d2f6d7b57fc9956bf06e944eb00463551f7d52fc73ca35cfc4c2cdb7aed/wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81", size = 90374 }, - { url = "https://files.pythonhosted.org/packages/a6/9b/c2c21b44ff5b9bf14a83252a8b973fb84923764ff63db3e6dfc3895cf2e0/wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9", size = 83896 }, - { url = "https://files.pythonhosted.org/packages/14/26/93a9fa02c6f257df54d7570dfe8011995138118d11939a4ecd82cb849613/wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c", size = 91738 }, - { url = "https://files.pythonhosted.org/packages/a2/5b/4660897233eb2c8c4de3dc7cefed114c61bacb3c28327e64150dc44ee2f6/wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc", size = 35568 }, - { url = "https://files.pythonhosted.org/packages/5c/cc/8297f9658506b224aa4bd71906447dea6bb0ba629861a758c28f67428b91/wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8", size = 37653 }, - { url = "https://files.pythonhosted.org/packages/ff/21/abdedb4cdf6ff41ebf01a74087740a709e2edb146490e4d9beea054b0b7a/wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1", size = 23362 }, -] - -[[package]] -name = "wsproto" -version = "1.2.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "h11" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226 }, -] - -[[package]] -name = "yarl" -version = "1.17.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, - { name = "multidict" }, - { name = "propcache" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/54/9c/9c0a9bfa683fc1be7fdcd9687635151544d992cccd48892dc5e0a5885a29/yarl-1.17.1.tar.gz", hash = "sha256:067a63fcfda82da6b198fa73079b1ca40b7c9b7994995b6ee38acda728b64d47", size = 178163 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/af/e25615c7920396219b943b9ff8b34636ae3e1ad30777649371317d7f05f8/yarl-1.17.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:327828786da2006085a4d1feb2594de6f6d26f8af48b81eb1ae950c788d97f61", size = 141839 }, - { url = "https://files.pythonhosted.org/packages/83/5e/363d9de3495c7c66592523f05d21576a811015579e0c87dd38c7b5788afd/yarl-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cc353841428d56b683a123a813e6a686e07026d6b1c5757970a877195f880c2d", size = 94125 }, - { url = "https://files.pythonhosted.org/packages/e3/a2/b65447626227ebe36f18f63ac551790068bf42c69bb22dfa3ae986170728/yarl-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c73df5b6e8fabe2ddb74876fb82d9dd44cbace0ca12e8861ce9155ad3c886139", size = 92048 }, - { url = "https://files.pythonhosted.org/packages/a1/f5/2ef86458446f85cde10582054fd5113495ef8ce8477da35aaaf26d2970ef/yarl-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bdff5e0995522706c53078f531fb586f56de9c4c81c243865dd5c66c132c3b5", size = 331472 }, - { url = "https://files.pythonhosted.org/packages/f3/6b/1ba79758ba352cdf2ad4c20cab1b982dd369aa595bb0d7601fc89bf82bee/yarl-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:06157fb3c58f2736a5e47c8fcbe1afc8b5de6fb28b14d25574af9e62150fcaac", size = 341260 }, - { url = "https://files.pythonhosted.org/packages/2d/41/4e07c2afca3f9ed3da5b0e38d43d0280d9b624a3d5c478c425e5ce17775c/yarl-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1654ec814b18be1af2c857aa9000de7a601400bd4c9ca24629b18486c2e35463", size = 340882 }, - { url = "https://files.pythonhosted.org/packages/c3/c0/cd8e94618983c1b811af082e1a7ad7764edb3a6af2bc6b468e0e686238ba/yarl-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f6595c852ca544aaeeb32d357e62c9c780eac69dcd34e40cae7b55bc4fb1147", size = 336648 }, - { url = "https://files.pythonhosted.org/packages/ac/fc/73ec4340d391ffbb8f34eb4c55429784ec9f5bd37973ce86d52d67135418/yarl-1.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:459e81c2fb920b5f5df744262d1498ec2c8081acdcfe18181da44c50f51312f7", size = 325019 }, - { url = "https://files.pythonhosted.org/packages/57/48/da3ebf418fc239d0a156b3bdec6b17a5446f8d2dea752299c6e47b143a85/yarl-1.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e48cdb8226644e2fbd0bdb0a0f87906a3db07087f4de77a1b1b1ccfd9e93685", size = 342841 }, - { url = "https://files.pythonhosted.org/packages/5d/79/107272745a470a8167924e353a5312eb52b5a9bb58e22686adc46c94f7ec/yarl-1.17.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d9b6b28a57feb51605d6ae5e61a9044a31742db557a3b851a74c13bc61de5172", size = 341433 }, - { url = "https://files.pythonhosted.org/packages/30/9c/6459668b3b8dcc11cd061fc53e12737e740fb6b1575b49c84cbffb387b3a/yarl-1.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e594b22688d5747b06e957f1ef822060cb5cb35b493066e33ceac0cf882188b7", size = 344927 }, - { url = "https://files.pythonhosted.org/packages/c5/0b/93a17ed733aca8164fc3a01cb7d47b3f08854ce4f957cce67a6afdb388a0/yarl-1.17.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5f236cb5999ccd23a0ab1bd219cfe0ee3e1c1b65aaf6dd3320e972f7ec3a39da", size = 355732 }, - { url = "https://files.pythonhosted.org/packages/9a/63/ead2ed6aec3c59397e135cadc66572330325a0c24cd353cd5c94f5e63463/yarl-1.17.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a2a64e62c7a0edd07c1c917b0586655f3362d2c2d37d474db1a509efb96fea1c", size = 362123 }, - { url = "https://files.pythonhosted.org/packages/89/bf/f6b75b4c2fcf0e7bb56edc0ed74e33f37fac45dc40e5a52a3be66b02587a/yarl-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d0eea830b591dbc68e030c86a9569826145df485b2b4554874b07fea1275a199", size = 356355 }, - { url = "https://files.pythonhosted.org/packages/45/1f/50a0257cd07eef65c8c65ad6a21f5fb230012d659e021aeb6ac8a7897bf6/yarl-1.17.1-cp312-cp312-win32.whl", hash = "sha256:46ddf6e0b975cd680eb83318aa1d321cb2bf8d288d50f1754526230fcf59ba96", size = 83279 }, - { url = "https://files.pythonhosted.org/packages/bc/82/fafb2c1268d63d54ec08b3a254fbe51f4ef098211501df646026717abee3/yarl-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:117ed8b3732528a1e41af3aa6d4e08483c2f0f2e3d3d7dca7cf538b3516d93df", size = 89590 }, - { url = "https://files.pythonhosted.org/packages/06/1e/5a93e3743c20eefbc68bd89334d9c9f04f3f2334380f7bbf5e950f29511b/yarl-1.17.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5d1d42556b063d579cae59e37a38c61f4402b47d70c29f0ef15cee1acaa64488", size = 139974 }, - { url = "https://files.pythonhosted.org/packages/a1/be/4e0f6919013c7c5eaea5c31811c551ccd599d2fc80aa3dd6962f1bbdcddd/yarl-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0167540094838ee9093ef6cc2c69d0074bbf84a432b4995835e8e5a0d984374", size = 93364 }, - { url = "https://files.pythonhosted.org/packages/73/f0/650f994bc491d0cb85df8bb45392780b90eab1e175f103a5edc61445ff67/yarl-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2f0a6423295a0d282d00e8701fe763eeefba8037e984ad5de44aa349002562ac", size = 91177 }, - { url = "https://files.pythonhosted.org/packages/f3/e8/9945ed555d14b43ede3ae8b1bd73e31068a694cad2b9d3cad0a28486c2eb/yarl-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5b078134f48552c4d9527db2f7da0b5359abd49393cdf9794017baec7506170", size = 333086 }, - { url = "https://files.pythonhosted.org/packages/a6/c0/7d167e48e14d26639ca066825af8da7df1d2fcdba827e3fd6341aaf22a3b/yarl-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d401f07261dc5aa36c2e4efc308548f6ae943bfff20fcadb0a07517a26b196d8", size = 343661 }, - { url = "https://files.pythonhosted.org/packages/fa/81/80a266517531d4e3553aecd141800dbf48d02e23ebd52909e63598a80134/yarl-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5f1ac7359e17efe0b6e5fec21de34145caef22b260e978336f325d5c84e6938", size = 345196 }, - { url = "https://files.pythonhosted.org/packages/b0/77/6adc482ba7f2dc6c0d9b3b492e7cd100edfac4cfc3849c7ffa26fd7beb1a/yarl-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f63d176a81555984e91f2c84c2a574a61cab7111cc907e176f0f01538e9ff6e", size = 338743 }, - { url = "https://files.pythonhosted.org/packages/6d/cc/f0c4c0b92ff3ada517ffde2b127406c001504b225692216d969879ada89a/yarl-1.17.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e275792097c9f7e80741c36de3b61917aebecc08a67ae62899b074566ff8556", size = 326719 }, - { url = "https://files.pythonhosted.org/packages/18/3b/7bfc80d3376b5fa162189993a87a5a6a58057f88315bd0ea00610055b57a/yarl-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:81713b70bea5c1386dc2f32a8f0dab4148a2928c7495c808c541ee0aae614d67", size = 345826 }, - { url = "https://files.pythonhosted.org/packages/2e/66/cf0b0338107a5c370205c1a572432af08f36ca12ecce127f5b558398b4fd/yarl-1.17.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:aa46dce75078fceaf7cecac5817422febb4355fbdda440db55206e3bd288cfb8", size = 340335 }, - { url = "https://files.pythonhosted.org/packages/2f/52/b084b0eec0fd4d2490e1d33ace3320fad704c5f1f3deaa709f929d2d87fc/yarl-1.17.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1ce36ded585f45b1e9bb36d0ae94765c6608b43bd2e7f5f88079f7a85c61a4d3", size = 345301 }, - { url = "https://files.pythonhosted.org/packages/ef/38/9e2036d948efd3bafcdb4976cb212166fded76615f0dfc6c1492c4ce4784/yarl-1.17.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2d374d70fdc36f5863b84e54775452f68639bc862918602d028f89310a034ab0", size = 354205 }, - { url = "https://files.pythonhosted.org/packages/81/c1/13dfe1e70b86811733316221c696580725ceb1c46d4e4db852807e134310/yarl-1.17.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:2d9f0606baaec5dd54cb99667fcf85183a7477f3766fbddbe3f385e7fc253299", size = 360501 }, - { url = "https://files.pythonhosted.org/packages/91/87/756e05c74cd8bf9e71537df4a2cae7e8211a9ebe0d2350a3e26949e1e41c/yarl-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b0341e6d9a0c0e3cdc65857ef518bb05b410dbd70d749a0d33ac0f39e81a4258", size = 359452 }, - { url = "https://files.pythonhosted.org/packages/06/b2/b2bb09c1e6d59e1c9b1b36a86caa473e22c3dbf26d1032c030e9bfb554dc/yarl-1.17.1-cp313-cp313-win32.whl", hash = "sha256:2e7ba4c9377e48fb7b20dedbd473cbcbc13e72e1826917c185157a137dac9df2", size = 308904 }, - { url = "https://files.pythonhosted.org/packages/f3/27/f084d9a5668853c1f3b246620269b14ee871ef3c3cc4f3a1dd53645b68ec/yarl-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:949681f68e0e3c25377462be4b658500e85ca24323d9619fdc41f68d46a1ffda", size = 314637 }, - { url = "https://files.pythonhosted.org/packages/52/ad/1fe7ff5f3e8869d4c5070f47b96bac2b4d15e67c100a8278d8e7876329fc/yarl-1.17.1-py3-none-any.whl", hash = "sha256:f1790a4b1e8e8e028c391175433b9c8122c39b46e1663228158e61e6f915bf06", size = 44352 }, -] diff --git a/examples/soc-pytest/pyproject.toml b/examples/soc-pytest/pyproject.toml index c0e196a98..0919aaa39 100644 --- a/examples/soc-pytest/pyproject.toml +++ b/examples/soc-pytest/pyproject.toml @@ -17,10 +17,6 @@ dependencies = [ "jumpstarter_driver_dutlink", ] -[tool.uv.sources] -jumpstarter-imagehash = { workspace = true } -jumpstarter-driver-dutlink = { workspace = true } - [tool.pytest.ini_options] addopts = "-s --ignore examples/pytest/test_on_rpi4.py" log_cli = 1 diff --git a/jumpstarter/client/adapters/__init__.py b/jumpstarter/client/adapters/__init__.py deleted file mode 100644 index 0bbfd7f59..000000000 --- a/jumpstarter/client/adapters/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -from .common import ClientAdapter -from .fabric import FabricAdapter -from .novnc import NovncAdapter -from .opendal import OpendalAdapter -from .pexpect import PexpectAdapter -from .portforward import PortforwardAdapter - -__all__ = ["ClientAdapter", "PortforwardAdapter", "NovncAdapter", "OpendalAdapter", "PexpectAdapter", "FabricAdapter"] diff --git a/packages/jumpstarter/README.md b/packages/jumpstarter/README.md new file mode 100644 index 000000000..ae4322f2c --- /dev/null +++ b/packages/jumpstarter/README.md @@ -0,0 +1 @@ +# Jumpstarter Core \ No newline at end of file diff --git a/conftest.py b/packages/jumpstarter/conftest.py similarity index 96% rename from conftest.py rename to packages/jumpstarter/conftest.py index 1ba8d1d47..159b28ab1 100644 --- a/conftest.py +++ b/packages/jumpstarter/conftest.py @@ -2,6 +2,7 @@ from dataclasses import dataclass, field from datetime import datetime, timedelta from ipaddress import IPv4Address +from typing import Tuple from uuid import uuid4 import grpc @@ -13,9 +14,8 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import rsa - from jumpstarter.streams import RouterStream, forward_stream -from jumpstarter.v1 import ( +from jumpstarter_protocol import ( jumpstarter_pb2, jumpstarter_pb2_grpc, kubernetes_pb2, @@ -44,11 +44,11 @@ async def Stream(self, _request_iterator, context): @dataclass(kw_only=True) class MockController(jumpstarter_pb2_grpc.ControllerServiceServicer): router_endpoint: str - status: ( + status: Tuple[ MemoryObjectSendStream[jumpstarter_pb2.StatusResponse], MemoryObjectReceiveStream[jumpstarter_pb2.StatusResponse], - ) = field(init=False, default_factory=lambda: create_memory_object_stream[jumpstarter_pb2.StatusResponse](32)) - queue: (MemoryObjectSendStream[str], MemoryObjectReceiveStream[str]) = field( + ] = field(init=False, default_factory=lambda: create_memory_object_stream[jumpstarter_pb2.StatusResponse](32)) + queue: Tuple[MemoryObjectSendStream[str], MemoryObjectReceiveStream[str]] = field( init=False, default_factory=lambda: create_memory_object_stream[str](32) ) leases: dict[str, int | str] = field(init=False, default_factory=dict) diff --git a/jumpstarter/client/__init__.py b/packages/jumpstarter/jumpstarter/client/__init__.py similarity index 100% rename from jumpstarter/client/__init__.py rename to packages/jumpstarter/jumpstarter/client/__init__.py diff --git a/jumpstarter/client/adapters/common.py b/packages/jumpstarter/jumpstarter/client/adapters.py similarity index 100% rename from jumpstarter/client/adapters/common.py rename to packages/jumpstarter/jumpstarter/client/adapters.py diff --git a/jumpstarter/client/base.py b/packages/jumpstarter/jumpstarter/client/base.py similarity index 99% rename from jumpstarter/client/base.py rename to packages/jumpstarter/jumpstarter/client/base.py index 5b4e7cfd1..22f236447 100644 --- a/jumpstarter/client/base.py +++ b/packages/jumpstarter/jumpstarter/client/base.py @@ -8,11 +8,10 @@ from dataclasses import field from anyio.from_thread import BlockingPortal +from jumpstarter.streams import BlockingStream from pydantic import ConfigDict from pydantic.dataclasses import dataclass -from jumpstarter.streams import BlockingStream - from .core import AsyncDriverClient diff --git a/jumpstarter/client/client.py b/packages/jumpstarter/jumpstarter/client/client.py similarity index 96% rename from jumpstarter/client/client.py rename to packages/jumpstarter/jumpstarter/client/client.py index 7a3387512..257dd6b71 100644 --- a/jumpstarter/client/client.py +++ b/packages/jumpstarter/jumpstarter/client/client.py @@ -1,17 +1,14 @@ from collections import OrderedDict, defaultdict from contextlib import asynccontextmanager -from graphlib import TopologicalSorter from uuid import UUID import grpc from anyio.from_thread import BlockingPortal from google.protobuf import empty_pb2 - +from graphlib import TopologicalSorter from jumpstarter.client import DriverClient from jumpstarter.common.importlib import import_class -from jumpstarter.v1 import ( - jumpstarter_pb2_grpc, -) +from jumpstarter_protocol import jumpstarter_pb2_grpc @asynccontextmanager diff --git a/jumpstarter/client/core.py b/packages/jumpstarter/jumpstarter/client/core.py similarity index 97% rename from jumpstarter/client/core.py rename to packages/jumpstarter/jumpstarter/client/core.py index eba4fdb4e..f7deaae52 100644 --- a/jumpstarter/client/core.py +++ b/packages/jumpstarter/jumpstarter/client/core.py @@ -7,7 +7,6 @@ from grpc import StatusCode from grpc.aio import AioRpcError, Channel - from jumpstarter.common import Metadata from jumpstarter.common.resources import ResourceMetadata from jumpstarter.common.serde import decode_value, encode_value @@ -23,7 +22,7 @@ RouterStream, forward_stream, ) -from jumpstarter.v1 import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc +from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc @dataclass(kw_only=True) diff --git a/jumpstarter/client/lease.py b/packages/jumpstarter/jumpstarter/client/lease.py similarity index 98% rename from jumpstarter/client/lease.py rename to packages/jumpstarter/jumpstarter/client/lease.py index fccce10c0..637938005 100644 --- a/jumpstarter/client/lease.py +++ b/packages/jumpstarter/jumpstarter/client/lease.py @@ -6,13 +6,12 @@ from anyio.from_thread import BlockingPortal from google.protobuf import duration_pb2 from grpc.aio import Channel - from jumpstarter.client import client_from_path from jumpstarter.common import MetadataFilter, TemporaryUnixListener from jumpstarter.common.condition import condition_false, condition_present_and_equal, condition_true from jumpstarter.common.streams import connect_router_stream from jumpstarter.config.tls import TLSConfigV1Alpha1 -from jumpstarter.v1 import jumpstarter_pb2, jumpstarter_pb2_grpc, kubernetes_pb2 +from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, kubernetes_pb2 logger = logging.getLogger(__name__) diff --git a/jumpstarter/common/__init__.py b/packages/jumpstarter/jumpstarter/common/__init__.py similarity index 100% rename from jumpstarter/common/__init__.py rename to packages/jumpstarter/jumpstarter/common/__init__.py diff --git a/jumpstarter/common/condition.py b/packages/jumpstarter/jumpstarter/common/condition.py similarity index 94% rename from jumpstarter/common/condition.py rename to packages/jumpstarter/jumpstarter/common/condition.py index 4199b5553..486e6a367 100644 --- a/jumpstarter/common/condition.py +++ b/packages/jumpstarter/jumpstarter/common/condition.py @@ -1,6 +1,6 @@ # Ported from https://github.com/kubernetes/apimachinery/blob/v0.31.1/pkg/api/meta/conditions.go -from jumpstarter.v1 import kubernetes_pb2 +from jumpstarter_protocol import kubernetes_pb2 def condition_present_and_equal(conditions: list[kubernetes_pb2.Condition], diff --git a/jumpstarter/common/grpc.py b/packages/jumpstarter/jumpstarter/common/grpc.py similarity index 100% rename from jumpstarter/common/grpc.py rename to packages/jumpstarter/jumpstarter/common/grpc.py diff --git a/jumpstarter/common/importlib.py b/packages/jumpstarter/jumpstarter/common/importlib.py similarity index 100% rename from jumpstarter/common/importlib.py rename to packages/jumpstarter/jumpstarter/common/importlib.py diff --git a/jumpstarter/common/importlib_test.py b/packages/jumpstarter/jumpstarter/common/importlib_test.py similarity index 100% rename from jumpstarter/common/importlib_test.py rename to packages/jumpstarter/jumpstarter/common/importlib_test.py diff --git a/jumpstarter/common/metadata.py b/packages/jumpstarter/jumpstarter/common/metadata.py similarity index 100% rename from jumpstarter/common/metadata.py rename to packages/jumpstarter/jumpstarter/common/metadata.py diff --git a/jumpstarter/common/resources.py b/packages/jumpstarter/jumpstarter/common/resources.py similarity index 100% rename from jumpstarter/common/resources.py rename to packages/jumpstarter/jumpstarter/common/resources.py diff --git a/jumpstarter/common/serde.py b/packages/jumpstarter/jumpstarter/common/serde.py similarity index 100% rename from jumpstarter/common/serde.py rename to packages/jumpstarter/jumpstarter/common/serde.py diff --git a/jumpstarter/common/streams.py b/packages/jumpstarter/jumpstarter/common/streams.py similarity index 95% rename from jumpstarter/common/streams.py rename to packages/jumpstarter/jumpstarter/common/streams.py index f1ed59750..e2a9db6ad 100644 --- a/jumpstarter/common/streams.py +++ b/packages/jumpstarter/jumpstarter/common/streams.py @@ -3,11 +3,10 @@ from uuid import UUID import grpc -from pydantic import BaseModel, Field, Json - from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials from jumpstarter.streams import RouterStream, forward_stream -from jumpstarter.v1 import router_pb2_grpc +from jumpstarter_protocol.jumpstarter.v1 import router_pb2_grpc +from pydantic import BaseModel, Field, Json class ResourceStreamRequest(BaseModel): diff --git a/jumpstarter/common/tempfile.py b/packages/jumpstarter/jumpstarter/common/tempfile.py similarity index 100% rename from jumpstarter/common/tempfile.py rename to packages/jumpstarter/jumpstarter/common/tempfile.py diff --git a/jumpstarter/common/utils.py b/packages/jumpstarter/jumpstarter/common/utils.py similarity index 100% rename from jumpstarter/common/utils.py rename to packages/jumpstarter/jumpstarter/common/utils.py diff --git a/jumpstarter/config/__init__.py b/packages/jumpstarter/jumpstarter/config/__init__.py similarity index 100% rename from jumpstarter/config/__init__.py rename to packages/jumpstarter/jumpstarter/config/__init__.py diff --git a/jumpstarter/config/client.py b/packages/jumpstarter/jumpstarter/config/client.py similarity index 99% rename from jumpstarter/config/client.py rename to packages/jumpstarter/jumpstarter/config/client.py index 64ad20b6c..c50d7395d 100644 --- a/jumpstarter/config/client.py +++ b/packages/jumpstarter/jumpstarter/config/client.py @@ -6,11 +6,10 @@ import grpc import yaml from anyio.from_thread import BlockingPortal, start_blocking_portal -from pydantic import BaseModel, Field, ValidationError - from jumpstarter.common import MetadataFilter from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials -from jumpstarter.v1 import jumpstarter_pb2, jumpstarter_pb2_grpc +from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc +from pydantic import BaseModel, Field, ValidationError from .common import CONFIG_PATH from .env import JMP_DRIVERS_ALLOW, JMP_ENDPOINT, JMP_LEASE, JMP_TOKEN diff --git a/jumpstarter/config/common.py b/packages/jumpstarter/jumpstarter/config/common.py similarity index 100% rename from jumpstarter/config/common.py rename to packages/jumpstarter/jumpstarter/config/common.py diff --git a/jumpstarter/config/env.py b/packages/jumpstarter/jumpstarter/config/env.py similarity index 100% rename from jumpstarter/config/env.py rename to packages/jumpstarter/jumpstarter/config/env.py diff --git a/jumpstarter/config/exporter.py b/packages/jumpstarter/jumpstarter/config/exporter.py similarity index 98% rename from jumpstarter/config/exporter.py rename to packages/jumpstarter/jumpstarter/config/exporter.py index ab1ce0126..bad4cc90e 100644 --- a/jumpstarter/config/exporter.py +++ b/packages/jumpstarter/jumpstarter/config/exporter.py @@ -7,17 +7,16 @@ import grpc import yaml from anyio.from_thread import start_blocking_portal -from pydantic import BaseModel, Field - from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials from jumpstarter.common.importlib import import_class from jumpstarter.driver import Driver +from pydantic import BaseModel, Field from .tls import TLSConfigV1Alpha1 class ExporterConfigV1Alpha1DriverInstance(BaseModel): - type: str = Field(default="jumpstarter.drivers.composite.driver.Composite") + type: str = Field(default="jumpstarter_driver_composite.driver.Composite") children: dict[str, ExporterConfigV1Alpha1DriverInstance] = Field(default_factory=dict) config: dict[str, Any] = Field(default_factory=dict) diff --git a/jumpstarter/config/exporter_test.py b/packages/jumpstarter/jumpstarter/config/exporter_test.py similarity index 90% rename from jumpstarter/config/exporter_test.py rename to packages/jumpstarter/jumpstarter/config/exporter_test.py index d3a521e76..03af35897 100644 --- a/jumpstarter/config/exporter_test.py +++ b/packages/jumpstarter/jumpstarter/config/exporter_test.py @@ -3,7 +3,6 @@ import pytest from anyio import create_task_group from anyio.from_thread import start_blocking_portal - from jumpstarter.common import MetadataFilter from .client import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers @@ -21,12 +20,12 @@ async def test_exporter_serve(mock_controller): token="dummy-exporter-token", export={ "power": ExporterConfigV1Alpha1DriverInstance( - type="jumpstarter.drivers.power.driver.MockPower", + type="jumpstarter_driver_power.driver.MockPower", ), "nested": ExporterConfigV1Alpha1DriverInstance( children={ "tcp": ExporterConfigV1Alpha1DriverInstance( - type="jumpstarter.drivers.network.driver.TcpNetwork", + type="jumpstarter_driver_network.driver.TcpNetwork", config={ "host": "127.0.0.1", "port": 8080, @@ -72,7 +71,7 @@ def test_exporter_config(monkeypatch: pytest.MonkeyPatch, tmp_path: Path): export: power: - type: "jumpstarter.drivers.power.PduPower" + type: "jumpstarter_driver_power.driver.PduPower" config: host: "192.168.1.111" port: 1234 @@ -80,7 +79,7 @@ def test_exporter_config(monkeypatch: pytest.MonkeyPatch, tmp_path: Path): username: "admin" password: "secret" serial: - type: "jumpstarter.drivers.serial.Pyserial" + type: "jumpstarter_driver_pyserial.driver.Pyserial" config: port: "/dev/ttyUSB0" baudrate: 115200 @@ -107,7 +106,7 @@ def test_exporter_config(monkeypatch: pytest.MonkeyPatch, tmp_path: Path): tls=TLSConfigV1Alpha1(ca="cacertificatedata", insecure=True), export={ "power": ExporterConfigV1Alpha1DriverInstance( - type="jumpstarter.drivers.power.PduPower", + type="jumpstarter_driver_power.driver.PduPower", children={}, # missing children defaults to empty config={ "host": "192.168.1.111", @@ -119,7 +118,7 @@ def test_exporter_config(monkeypatch: pytest.MonkeyPatch, tmp_path: Path): }, ), "serial": ExporterConfigV1Alpha1DriverInstance( - type="jumpstarter.drivers.serial.Pyserial", + type="jumpstarter_driver_pyserial.driver.Pyserial", children={}, config={ "port": "/dev/ttyUSB0", @@ -127,7 +126,7 @@ def test_exporter_config(monkeypatch: pytest.MonkeyPatch, tmp_path: Path): }, ), "nested": ExporterConfigV1Alpha1DriverInstance( - type="jumpstarter.drivers.composite.driver.Composite", + type="jumpstarter_driver_composite.driver.Composite", children={ "custom": ExporterConfigV1Alpha1DriverInstance( type="vendorpackage.CustomDriver", diff --git a/jumpstarter/config/tls.py b/packages/jumpstarter/jumpstarter/config/tls.py similarity index 100% rename from jumpstarter/config/tls.py rename to packages/jumpstarter/jumpstarter/config/tls.py diff --git a/jumpstarter/config/user.py b/packages/jumpstarter/jumpstarter/config/user.py similarity index 100% rename from jumpstarter/config/user.py rename to packages/jumpstarter/jumpstarter/config/user.py diff --git a/jumpstarter/driver/__init__.py b/packages/jumpstarter/jumpstarter/driver/__init__.py similarity index 100% rename from jumpstarter/driver/__init__.py rename to packages/jumpstarter/jumpstarter/driver/__init__.py diff --git a/jumpstarter/driver/base.py b/packages/jumpstarter/jumpstarter/driver/base.py similarity index 98% rename from jumpstarter/driver/base.py rename to packages/jumpstarter/jumpstarter/driver/base.py index 651e03f8e..712b21a12 100644 --- a/jumpstarter/driver/base.py +++ b/packages/jumpstarter/jumpstarter/driver/base.py @@ -15,9 +15,6 @@ import aiohttp from anyio import to_thread from grpc import StatusCode -from pydantic import TypeAdapter -from pydantic.dataclasses import dataclass - from jumpstarter.common import Metadata from jumpstarter.common.resources import ClientStreamResource, PresignedRequestResource, Resource, ResourceMetadata from jumpstarter.common.serde import decode_value, encode_value @@ -26,7 +23,9 @@ ResourceStreamRequest, ) from jumpstarter.streams import AiohttpStreamReaderStream, MetadataStream, create_memory_stream -from jumpstarter.v1 import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc +from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc +from pydantic import TypeAdapter +from pydantic.dataclasses import dataclass from .decorators import ( MARKER_DRIVERCALL, diff --git a/jumpstarter/driver/decorators.py b/packages/jumpstarter/jumpstarter/driver/decorators.py similarity index 100% rename from jumpstarter/driver/decorators.py rename to packages/jumpstarter/jumpstarter/driver/decorators.py diff --git a/jumpstarter/driver/decorators_test.py b/packages/jumpstarter/jumpstarter/driver/decorators_test.py similarity index 100% rename from jumpstarter/driver/decorators_test.py rename to packages/jumpstarter/jumpstarter/driver/decorators_test.py diff --git a/jumpstarter/exporter/__init__.py b/packages/jumpstarter/jumpstarter/exporter/__init__.py similarity index 100% rename from jumpstarter/exporter/__init__.py rename to packages/jumpstarter/jumpstarter/exporter/__init__.py diff --git a/jumpstarter/exporter/exporter.py b/packages/jumpstarter/jumpstarter/exporter/exporter.py similarity index 99% rename from jumpstarter/exporter/exporter.py rename to packages/jumpstarter/jumpstarter/exporter/exporter.py index 6b5cb59b9..1420215cb 100644 --- a/jumpstarter/exporter/exporter.py +++ b/packages/jumpstarter/jumpstarter/exporter/exporter.py @@ -6,13 +6,12 @@ import grpc from anyio import connect_unix, create_task_group from google.protobuf import empty_pb2 - from jumpstarter.common import Metadata from jumpstarter.common.streams import connect_router_stream from jumpstarter.config.tls import TLSConfigV1Alpha1 from jumpstarter.driver import Driver from jumpstarter.exporter.session import Session -from jumpstarter.v1 import ( +from jumpstarter_protocol import ( jumpstarter_pb2, jumpstarter_pb2_grpc, ) diff --git a/jumpstarter/exporter/session.py b/packages/jumpstarter/jumpstarter/exporter/session.py similarity index 99% rename from jumpstarter/exporter/session.py rename to packages/jumpstarter/jumpstarter/exporter/session.py index 037d8a01c..892e9585b 100644 --- a/jumpstarter/exporter/session.py +++ b/packages/jumpstarter/jumpstarter/exporter/session.py @@ -6,12 +6,11 @@ import grpc from anyio import Event, TypedAttributeLookupError from anyio.from_thread import start_blocking_portal - from jumpstarter.common import Metadata, TemporarySocket from jumpstarter.common.streams import StreamRequestMetadata from jumpstarter.driver import Driver from jumpstarter.streams import MetadataStreamAttributes, RouterStream, forward_stream -from jumpstarter.v1 import ( +from jumpstarter_protocol import ( jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc, diff --git a/jumpstarter/streams/__init__.py b/packages/jumpstarter/jumpstarter/streams/__init__.py similarity index 86% rename from jumpstarter/streams/__init__.py rename to packages/jumpstarter/jumpstarter/streams/__init__.py index f4779f47b..6fa9c68d7 100644 --- a/jumpstarter/streams/__init__.py +++ b/packages/jumpstarter/jumpstarter/streams/__init__.py @@ -4,14 +4,12 @@ from .metadata import MetadataStream, MetadataStreamAttributes from .progress import ProgressStream from .router import RouterStream -from .websocket import WebsocketServerStream __all__ = [ "create_memory_stream", "forward_stream", "BlockingStream", "RouterStream", - "WebsocketServerStream", "ProgressStream", "MetadataStream", "MetadataStreamAttributes", diff --git a/jumpstarter/streams/aiohttp.py b/packages/jumpstarter/jumpstarter/streams/aiohttp.py similarity index 100% rename from jumpstarter/streams/aiohttp.py rename to packages/jumpstarter/jumpstarter/streams/aiohttp.py diff --git a/jumpstarter/streams/blocking.py b/packages/jumpstarter/jumpstarter/streams/blocking.py similarity index 100% rename from jumpstarter/streams/blocking.py rename to packages/jumpstarter/jumpstarter/streams/blocking.py diff --git a/jumpstarter/streams/common.py b/packages/jumpstarter/jumpstarter/streams/common.py similarity index 100% rename from jumpstarter/streams/common.py rename to packages/jumpstarter/jumpstarter/streams/common.py diff --git a/jumpstarter/streams/metadata.py b/packages/jumpstarter/jumpstarter/streams/metadata.py similarity index 100% rename from jumpstarter/streams/metadata.py rename to packages/jumpstarter/jumpstarter/streams/metadata.py diff --git a/jumpstarter/streams/progress.py b/packages/jumpstarter/jumpstarter/streams/progress.py similarity index 100% rename from jumpstarter/streams/progress.py rename to packages/jumpstarter/jumpstarter/streams/progress.py diff --git a/jumpstarter/streams/router.py b/packages/jumpstarter/jumpstarter/streams/router.py similarity index 98% rename from jumpstarter/streams/router.py rename to packages/jumpstarter/jumpstarter/streams/router.py index 9ef735636..b626ad6b3 100644 --- a/jumpstarter/streams/router.py +++ b/packages/jumpstarter/jumpstarter/streams/router.py @@ -9,8 +9,7 @@ EndOfStream, ) from anyio.abc import ObjectStream - -from jumpstarter.v1 import router_pb2 +from jumpstarter_protocol import router_pb2 logger = logging.getLogger(__name__) diff --git a/cli/admin/pyproject.toml b/packages/jumpstarter/pyproject.toml similarity index 54% rename from cli/admin/pyproject.toml rename to packages/jumpstarter/pyproject.toml index d031b1e03..36d995918 100644 --- a/cli/admin/pyproject.toml +++ b/packages/jumpstarter/pyproject.toml @@ -1,39 +1,38 @@ [project] -name = "jumpstarter-admin-cli" +name = "jumpstarter" dynamic = ["version", "urls"] description = "" authors = [ - { name = "Nick Cao", email = "ncao@redhat.com" }, - { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, - { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Nick Cao", email = "ncao@redhat.com" }, + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, ] readme = "README.md" license = { text = "Apache-2.0" } requires-python = ">=3.11" dependencies = [ - "jumpstarter", - "jumpstarter-cli-common", - "kubernetes>=31.0.0", - "kubernetes-asyncio>=31.1.0", - "asyncclick>=8.1.7.2", + "jumpstarter-protocol", + "pyyaml>=6.0.2", + "anyio>=4.4.0,!=4.6.2", + "aiohttp>=3.10.5", + "tqdm>=4.66.5", + "pydantic>=2.8.2" ] [dependency-groups] dev = [ "pytest>=8.3.2", + "pytest-cov>=6.0.0", "pytest-anyio>=0.0.0", "pytest-asyncio>=0.0.0", - "pytest-cov>=5.0.0", + "cryptography>=43.0.3", + "jumpstarter-driver-power", + "jumpstarter-driver-network", + "jumpstarter-driver-composite" ] -[tool.uv.sources] -jumpstarter-cli-common = { workspace = true } - -[project.scripts] -jmp-admin = "jumpstarter_admin_cli:admin" - [tool.hatch.build.targets.wheel] -packages = ["jumpstarter_admin_cli"] +packages = ["jumpstarter"] [tool.hatch.metadata.hooks.vcs.urls] Homepage = "https://jumpstarter.dev" diff --git a/cli/jmp/README.md b/packages/jumpstarter_cli/README.md similarity index 100% rename from cli/jmp/README.md rename to packages/jumpstarter_cli/README.md diff --git a/cli/jmp/jumpstarter_cli/__init__.py b/packages/jumpstarter_cli/jumpstarter_cli/__init__.py similarity index 69% rename from cli/jmp/jumpstarter_cli/__init__.py rename to packages/jumpstarter_cli/jumpstarter_cli/__init__.py index 42f8ba05f..2f5da97d2 100644 --- a/cli/jmp/jumpstarter_cli/__init__.py +++ b/packages/jumpstarter_cli/jumpstarter_cli/__init__.py @@ -1,8 +1,8 @@ import asyncclick as click -from jumpstarter_admin_cli import admin +from jumpstarter_cli_admin import admin +from jumpstarter_cli_client import client from jumpstarter_cli_common import AliasedGroup, version -from jumpstarter_client_cli import client -from jumpstarter_exporter_cli import exporter +from jumpstarter_cli_exporter import exporter @click.group(cls=AliasedGroup) diff --git a/cli/jmp/jumpstarter_cli/__main__.py b/packages/jumpstarter_cli/jumpstarter_cli/__main__.py similarity index 100% rename from cli/jmp/jumpstarter_cli/__main__.py rename to packages/jumpstarter_cli/jumpstarter_cli/__main__.py diff --git a/packages/jumpstarter_cli/jumpstarter_cli/cli_test.py b/packages/jumpstarter_cli/jumpstarter_cli/cli_test.py new file mode 100644 index 000000000..1a585ce36 --- /dev/null +++ b/packages/jumpstarter_cli/jumpstarter_cli/cli_test.py @@ -0,0 +1,18 @@ +import pytest +from asyncclick.testing import CliRunner + +from . import jmp + + +@pytest.mark.anyio +async def test_cli(): + runner = CliRunner() + result = await runner.invoke(jmp, []) + assert "admin" in result.output + assert "client" in result.output + assert "exporter" in result.output + assert "version" in result.output + +@pytest.fixture +def anyio_backend(): + return "asyncio" diff --git a/packages/jumpstarter_cli/pyproject.toml b/packages/jumpstarter_cli/pyproject.toml new file mode 100644 index 000000000..97b3a63b5 --- /dev/null +++ b/packages/jumpstarter_cli/pyproject.toml @@ -0,0 +1,43 @@ +[project] +name = "jumpstarter-cli" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Nick Cao", email = "ncao@redhat.com" }, + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter-cli-admin", + "jumpstarter-cli-client", + "jumpstarter-cli-exporter", +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "pytest-cov>=5.0.0", +] + +[project.scripts] +jmp = "jumpstarter_cli:jmp" + +[tool.hatch.build.targets.wheel] +packages = ["jumpstarter_cli"] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../' } + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/cli/admin/README.md b/packages/jumpstarter_cli_admin/README.md similarity index 100% rename from cli/admin/README.md rename to packages/jumpstarter_cli_admin/README.md diff --git a/cli/admin/jumpstarter_admin_cli/__init__.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/__init__.py similarity index 100% rename from cli/admin/jumpstarter_admin_cli/__init__.py rename to packages/jumpstarter_cli_admin/jumpstarter_cli_admin/__init__.py index be376e61a..1878b5469 100644 --- a/cli/admin/jumpstarter_admin_cli/__init__.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/__init__.py @@ -1,6 +1,6 @@ import asyncclick as click - from jumpstarter_cli_common import AliasedGroup, version + from .create import create from .delete import delete from .get import get diff --git a/cli/admin/jumpstarter_admin_cli/create.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py similarity index 98% rename from cli/admin/jumpstarter_admin_cli/create.py rename to packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py index 71516d28c..d5ebcf7aa 100644 --- a/cli/admin/jumpstarter_admin_cli/create.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py @@ -2,20 +2,22 @@ from typing import Optional import asyncclick as click +from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 from jumpstarter_cli_common import ( AliasedGroup, - handle_k8s_api_exception, - handle_k8s_config_exception, opt_context, opt_kubeconfig, opt_log_level, opt_namespace, ) +from jumpstarter_kubernetes import ClientsV1Alpha1Api, ExportersV1Alpha1Api from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.config.config_exception import ConfigException -from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 -from jumpstarter.k8s import ClientsV1Alpha1Api, ExportersV1Alpha1Api +from .k8s import ( + handle_k8s_api_exception, + handle_k8s_config_exception, +) @click.group(cls=AliasedGroup) diff --git a/cli/admin/jumpstarter_admin_cli/create_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py similarity index 99% rename from cli/admin/jumpstarter_admin_cli/create_test.py rename to packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py index 3acb6882d..f7fd3ecff 100644 --- a/cli/admin/jumpstarter_admin_cli/create_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py @@ -3,14 +3,12 @@ import pytest from asyncclick.testing import CliRunner -from kubernetes_asyncio.client.models import V1ObjectMeta - from jumpstarter.config import ( ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, ExporterConfigV1Alpha1, ) -from jumpstarter.k8s import ( +from jumpstarter_kubernetes import ( ClientsV1Alpha1Api, ExportersV1Alpha1Api, V1Alpha1Client, @@ -18,6 +16,7 @@ V1Alpha1Exporter, V1Alpha1ExporterStatus, ) +from kubernetes_asyncio.client.models import V1ObjectMeta from .create import create diff --git a/cli/admin/jumpstarter_admin_cli/delete.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py similarity index 97% rename from cli/admin/jumpstarter_admin_cli/delete.py rename to packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py index dcd08c30d..3df7151f9 100644 --- a/cli/admin/jumpstarter_admin_cli/delete.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py @@ -2,20 +2,22 @@ from typing import Optional import asyncclick as click +from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 from jumpstarter_cli_common import ( AliasedGroup, - handle_k8s_api_exception, - handle_k8s_config_exception, opt_context, opt_kubeconfig, opt_log_level, opt_namespace, ) +from jumpstarter_kubernetes import ClientsV1Alpha1Api, ExportersV1Alpha1Api from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.config.config_exception import ConfigException -from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 -from jumpstarter.k8s import ClientsV1Alpha1Api, ExportersV1Alpha1Api +from .k8s import ( + handle_k8s_api_exception, + handle_k8s_config_exception, +) @click.group(cls=AliasedGroup) diff --git a/cli/admin/jumpstarter_admin_cli/delete_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py similarity index 99% rename from cli/admin/jumpstarter_admin_cli/delete_test.py rename to packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py index d8f3477c5..521966906 100644 --- a/cli/admin/jumpstarter_admin_cli/delete_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py @@ -2,8 +2,6 @@ import pytest from asyncclick.testing import CliRunner -from kubernetes_asyncio.client.models import V1ObjectMeta - from jumpstarter.config import ( ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, @@ -11,12 +9,13 @@ UserConfigV1Alpha1, UserConfigV1Alpha1Config, ) -from jumpstarter.k8s import ( +from jumpstarter_kubernetes import ( ClientsV1Alpha1Api, ExportersV1Alpha1Api, V1Alpha1Exporter, V1Alpha1ExporterStatus, ) +from kubernetes_asyncio.client.models import V1ObjectMeta from .delete import delete diff --git a/cli/admin/jumpstarter_admin_cli/get.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get.py similarity index 99% rename from cli/admin/jumpstarter_admin_cli/get.py rename to packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get.py index 60c1955fd..0de9211fb 100644 --- a/cli/admin/jumpstarter_admin_cli/get.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get.py @@ -4,8 +4,6 @@ import asyncclick as click from jumpstarter_cli_common import ( AliasedGroup, - handle_k8s_api_exception, - handle_k8s_config_exception, make_table, opt_context, opt_kubeconfig, @@ -13,10 +11,7 @@ opt_namespace, time_since, ) -from kubernetes_asyncio.client.exceptions import ApiException -from kubernetes_asyncio.config.config_exception import ConfigException - -from jumpstarter.k8s import ( +from jumpstarter_kubernetes import ( ClientsV1Alpha1Api, ExportersV1Alpha1Api, LeasesV1Alpha1Api, @@ -24,6 +19,13 @@ V1Alpha1Exporter, V1Alpha1Lease, ) +from kubernetes_asyncio.client.exceptions import ApiException +from kubernetes_asyncio.config.config_exception import ConfigException + +from .k8s import ( + handle_k8s_api_exception, + handle_k8s_config_exception, +) @click.group(cls=AliasedGroup) diff --git a/cli/admin/jumpstarter_admin_cli/get_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get_test.py similarity index 99% rename from cli/admin/jumpstarter_admin_cli/get_test.py rename to packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get_test.py index 07eb726d8..f9790f3f1 100644 --- a/cli/admin/jumpstarter_admin_cli/get_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get_test.py @@ -5,7 +5,7 @@ from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.client.models import V1Condition, V1ObjectMeta, V1ObjectReference -from jumpstarter.k8s import ( +from jumpstarter_kubernetes import ( ClientsV1Alpha1Api, ExportersV1Alpha1Api, LeasesV1Alpha1Api, diff --git a/cli/admin/jumpstarter_admin_cli/import_res.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py similarity index 95% rename from cli/admin/jumpstarter_admin_cli/import_res.py rename to packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py index 79c9ec726..10dd4aa8b 100644 --- a/cli/admin/jumpstarter_admin_cli/import_res.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py @@ -1,22 +1,24 @@ from typing import Optional import asyncclick as click +from jumpstarter.config import ( + ClientConfigV1Alpha1, + UserConfigV1Alpha1, +) +from jumpstarter.config.exporter import ExporterConfigV1Alpha1 from jumpstarter_cli_common import ( - handle_k8s_api_exception, - handle_k8s_config_exception, opt_context, opt_kubeconfig, opt_namespace, ) +from jumpstarter_kubernetes import ClientsV1Alpha1Api, ExportersV1Alpha1Api from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.config.config_exception import ConfigException -from jumpstarter.config import ( - ClientConfigV1Alpha1, - UserConfigV1Alpha1, +from .k8s import ( + handle_k8s_api_exception, + handle_k8s_config_exception, ) -from jumpstarter.config.exporter import ExporterConfigV1Alpha1 -from jumpstarter.k8s import ClientsV1Alpha1Api, ExportersV1Alpha1Api @click.group("import") @@ -42,9 +44,7 @@ def import_res(): help="A comma-separated list of driver client packages to load.", default=None, ) -@click.option( - "--unsafe", is_flag=True, help="Should all driver client packages be allowed to load (UNSAFE!)." -) +@click.option("--unsafe", is_flag=True, help="Should all driver client packages be allowed to load (UNSAFE!).") async def import_client( name: str, namespace: str, diff --git a/cli/admin/jumpstarter_admin_cli/import_res_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py similarity index 99% rename from cli/admin/jumpstarter_admin_cli/import_res_test.py rename to packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py index 8aac5452d..99deb5124 100644 --- a/cli/admin/jumpstarter_admin_cli/import_res_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py @@ -9,7 +9,7 @@ ClientConfigV1Alpha1Drivers, ExporterConfigV1Alpha1, ) -from jumpstarter.k8s import ( +from jumpstarter_kubernetes import ( ClientsV1Alpha1Api, ExportersV1Alpha1Api, ) diff --git a/cli/admin/jumpstarter_admin_cli/install.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/install.py similarity index 97% rename from cli/admin/jumpstarter_admin_cli/install.py rename to packages/jumpstarter_cli_admin/jumpstarter_cli_admin/install.py index 270c37f9d..c94804ecd 100644 --- a/cli/admin/jumpstarter_admin_cli/install.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/install.py @@ -2,8 +2,7 @@ import asyncclick as click from jumpstarter_cli_common import get_client_version, opt_context, opt_kubeconfig - -from jumpstarter.k8s import get_ip_address, helm_installed, install_helm_chart +from jumpstarter_kubernetes import get_ip_address, helm_installed, install_helm_chart def get_chart_version() -> str: diff --git a/cli/common/jumpstarter_cli_common/k8s.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/k8s.py similarity index 100% rename from cli/common/jumpstarter_cli_common/k8s.py rename to packages/jumpstarter_cli_admin/jumpstarter_cli_admin/k8s.py diff --git a/cli/client/pyproject.toml b/packages/jumpstarter_cli_admin/pyproject.toml similarity index 66% rename from cli/client/pyproject.toml rename to packages/jumpstarter_cli_admin/pyproject.toml index 51bc5302d..bca898518 100644 --- a/cli/client/pyproject.toml +++ b/packages/jumpstarter_cli_admin/pyproject.toml @@ -1,19 +1,16 @@ [project] -name = "jumpstarter-client-cli" +name = "jumpstarter-cli-admin" dynamic = ["version", "urls"] description = "" authors = [ - { name = "Nick Cao", email = "ncao@redhat.com" }, - { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, ] readme = "README.md" license = { text = "Apache-2.0" } requires-python = ">=3.11" dependencies = [ - "jumpstarter", "jumpstarter-cli-common", - "asyncclick>=8.1.7.2", + "jumpstarter-kubernetes", ] [dependency-groups] @@ -24,15 +21,11 @@ dev = [ "pytest-cov>=5.0.0", ] -[tool.uv.sources] -jumpstarter-cli-common = { workspace = true } - [project.scripts] -jmp-client = "jumpstarter_client_cli:client" -j = "jumpstarter_client_cli:j" +jmp-admin = "jumpstarter_cli_admin:admin" [tool.hatch.build.targets.wheel] -packages = ["jumpstarter_client_cli"] +packages = ["jumpstarter_cli_admin"] [tool.hatch.metadata.hooks.vcs.urls] Homepage = "https://jumpstarter.dev" diff --git a/cli/client/README.md b/packages/jumpstarter_cli_client/README.md similarity index 100% rename from cli/client/README.md rename to packages/jumpstarter_cli_client/README.md diff --git a/cli/client/jumpstarter_client_cli/__init__.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py similarity index 99% rename from cli/client/jumpstarter_client_cli/__init__.py rename to packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py index 7812d3d8e..e0a2f19f3 100644 --- a/cli/client/jumpstarter_client_cli/__init__.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py @@ -1,7 +1,6 @@ import asyncclick as click -from jumpstarter_cli_common import AliasedGroup, version - from jumpstarter.common.utils import env +from jumpstarter_cli_common import AliasedGroup, version from .client_config import create_client_config, delete_client_config, list_client_configs, use_client_config from .client_shell import client_shell diff --git a/cli/client/jumpstarter_client_cli/client_config.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py similarity index 99% rename from cli/client/jumpstarter_client_cli/client_config.py rename to packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py index 5a08aa25f..bed794ea0 100644 --- a/cli/client/jumpstarter_client_cli/client_config.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py @@ -1,9 +1,8 @@ from typing import Optional import asyncclick as click -from jumpstarter_cli_common import make_table - from jumpstarter.config import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, UserConfigV1Alpha1 +from jumpstarter_cli_common import make_table @click.command("create-config", short_help="Create a client config.") diff --git a/cli/client/jumpstarter_client_cli/client_shell.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py similarity index 99% rename from cli/client/jumpstarter_client_cli/client_shell.py rename to packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py index ec5c11857..fc1eb856c 100644 --- a/cli/client/jumpstarter_client_cli/client_shell.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py @@ -1,5 +1,4 @@ import asyncclick as click - from jumpstarter.common import MetadataFilter from jumpstarter.common.utils import launch_shell from jumpstarter.config import ( diff --git a/cli/client/jumpstarter_client_cli/client_test.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py similarity index 71% rename from cli/client/jumpstarter_client_cli/client_test.py rename to packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py index a869c4bd9..1440e5adf 100644 --- a/cli/client/jumpstarter_client_cli/client_test.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py @@ -1,9 +1,8 @@ import pytest from asyncclick.testing import CliRunner - from jumpstarter.config import ClientConfigV1Alpha1, UserConfigV1Alpha1 -from .client_config import client +from . import client @pytest.fixture @@ -18,46 +17,48 @@ async def test_client(tmp_config_path): # create client non-interactively result = await runner.invoke( - client, ["create", "test1", "--endpoint", "example.com:443", "--token", "dummy", "--allow", "jumpstarter.*"] + client, + ["create-config", "test1", "--endpoint", "example.com:443", "--token", "dummy", "--allow", "jumpstarter.*"], ) assert result.exit_code == 0 # create duplicate client result = await runner.invoke( - client, ["create", "test1", "--endpoint", "example.com:443", "--token", "dummy", "--allow", "jumpstarter.*"] + client, + ["create-config", "test1", "--endpoint", "example.com:443", "--token", "dummy", "--allow", "jumpstarter.*"], ) assert result.exit_code != 0 # create client interactively result = await runner.invoke( client, - ["create", "test2"], + ["create-config", "test2"], input="example.org:443\ndummytoken\njumpstarter.*,com.example.*\n", ) assert result.exit_code == 0 # list clients - result = await runner.invoke(client, ["list"]) + result = await runner.invoke(client, ["list-configs"]) assert result.exit_code == 0 assert "* test1 example.com:443" in result.output assert " test2 example.org:443" in result.output # set default client - result = await runner.invoke(client, ["use", "test2"]) + result = await runner.invoke(client, ["use-config", "test2"]) assert result.exit_code == 0 # list clients - result = await runner.invoke(client, ["list"]) + result = await runner.invoke(client, ["list-configs"]) assert result.exit_code == 0 assert " test1 example.com:443" in result.output assert "* test2 example.org:443" in result.output # delete default client - result = await runner.invoke(client, ["delete", "test2"]) + result = await runner.invoke(client, ["delete-config", "test2"]) assert result.exit_code == 0 # list clients - result = await runner.invoke(client, ["list"]) + result = await runner.invoke(client, ["list-configs"]) assert result.exit_code == 0 assert "* test1 example.com:443" in result.output assert "* test2 example.org:443" not in result.output diff --git a/cli/client/jumpstarter_client_cli/j.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/j.py similarity index 100% rename from cli/client/jumpstarter_client_cli/j.py rename to packages/jumpstarter_cli_client/jumpstarter_cli_client/j.py diff --git a/cli/client/jumpstarter_client_cli/lease.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py similarity index 99% rename from cli/client/jumpstarter_client_cli/lease.py rename to packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py index 24b20ed1f..0ec567229 100644 --- a/cli/client/jumpstarter_client_cli/lease.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py @@ -1,10 +1,9 @@ import asyncclick as click -from jumpstarter_cli_common import AliasedGroup - from jumpstarter.config import ( ClientConfigV1Alpha1, UserConfigV1Alpha1, ) +from jumpstarter_cli_common import AliasedGroup @click.group(cls=AliasedGroup, short_help="") diff --git a/cli/exporter/pyproject.toml b/packages/jumpstarter_cli_client/pyproject.toml similarity index 79% rename from cli/exporter/pyproject.toml rename to packages/jumpstarter_cli_client/pyproject.toml index 0e5c87d27..e40329cf0 100644 --- a/cli/exporter/pyproject.toml +++ b/packages/jumpstarter_cli_client/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "jumpstarter-exporter-cli" +name = "jumpstarter-cli-client" dynamic = ["version", "urls"] description = "" authors = [ @@ -11,9 +11,7 @@ readme = "README.md" license = { text = "Apache-2.0" } requires-python = ">=3.11" dependencies = [ - "jumpstarter", "jumpstarter-cli-common", - "asyncclick>=8.1.7.2", ] [dependency-groups] @@ -25,13 +23,11 @@ dev = [ ] [project.scripts] -jmp-client = "jumpstarter_exporter_cli:exporter" - -[tool.uv.sources] -jumpstarter-cli-common = { workspace = true } +jmp-client = "jumpstarter_cli_client:client" +j = "jumpstarter_cli_client:j" [tool.hatch.build.targets.wheel] -packages = ["jumpstarter_exporter_cli"] +packages = ["jumpstarter_cli_client"] [tool.hatch.metadata.hooks.vcs.urls] Homepage = "https://jumpstarter.dev" diff --git a/cli/common/README.md b/packages/jumpstarter_cli_common/README.md similarity index 100% rename from cli/common/README.md rename to packages/jumpstarter_cli_common/README.md diff --git a/cli/common/jumpstarter_cli_common/__init__.py b/packages/jumpstarter_cli_common/jumpstarter_cli_common/__init__.py similarity index 74% rename from cli/common/jumpstarter_cli_common/__init__.py rename to packages/jumpstarter_cli_common/jumpstarter_cli_common/__init__.py index 25c96f8a2..5ab756911 100644 --- a/cli/common/jumpstarter_cli_common/__init__.py +++ b/packages/jumpstarter_cli_common/jumpstarter_cli_common/__init__.py @@ -1,5 +1,4 @@ from .alias import AliasedGroup -from .k8s import handle_k8s_api_exception, handle_k8s_config_exception from .opt import opt_context, opt_kubeconfig, opt_log_level, opt_namespace from .table import make_table from .time import time_since @@ -13,8 +12,6 @@ "opt_kubeconfig", "opt_namespace", "time_since", - "handle_k8s_api_exception", - "handle_k8s_config_exception", "version", "get_client_version" ] diff --git a/cli/common/jumpstarter_cli_common/alias.py b/packages/jumpstarter_cli_common/jumpstarter_cli_common/alias.py similarity index 100% rename from cli/common/jumpstarter_cli_common/alias.py rename to packages/jumpstarter_cli_common/jumpstarter_cli_common/alias.py diff --git a/cli/common/jumpstarter_cli_common/opt.py b/packages/jumpstarter_cli_common/jumpstarter_cli_common/opt.py similarity index 100% rename from cli/common/jumpstarter_cli_common/opt.py rename to packages/jumpstarter_cli_common/jumpstarter_cli_common/opt.py diff --git a/cli/common/jumpstarter_cli_common/table.py b/packages/jumpstarter_cli_common/jumpstarter_cli_common/table.py similarity index 100% rename from cli/common/jumpstarter_cli_common/table.py rename to packages/jumpstarter_cli_common/jumpstarter_cli_common/table.py diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/table_test.py b/packages/jumpstarter_cli_common/jumpstarter_cli_common/table_test.py new file mode 100644 index 000000000..c4798eab7 --- /dev/null +++ b/packages/jumpstarter_cli_common/jumpstarter_cli_common/table_test.py @@ -0,0 +1,9 @@ +from .table import make_table + +EXPECTED_TABLE = "TEST HELLO \n123456 There " + +def test_make_table(): + COLUMNS = ["TEST", "HELLO"] + DATA = [{"TEST": "123456", "HELLO": "There"}] + table = make_table(COLUMNS, DATA) + assert table == EXPECTED_TABLE diff --git a/cli/common/jumpstarter_cli_common/time.py b/packages/jumpstarter_cli_common/jumpstarter_cli_common/time.py similarity index 100% rename from cli/common/jumpstarter_cli_common/time.py rename to packages/jumpstarter_cli_common/jumpstarter_cli_common/time.py diff --git a/cli/common/jumpstarter_cli_common/version.py b/packages/jumpstarter_cli_common/jumpstarter_cli_common/version.py similarity index 100% rename from cli/common/jumpstarter_cli_common/version.py rename to packages/jumpstarter_cli_common/jumpstarter_cli_common/version.py diff --git a/packages/jumpstarter_cli_common/pyproject.toml b/packages/jumpstarter_cli_common/pyproject.toml new file mode 100644 index 000000000..2b68995d6 --- /dev/null +++ b/packages/jumpstarter_cli_common/pyproject.toml @@ -0,0 +1,37 @@ +[project] +name = "jumpstarter-cli-common" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "asyncclick>=8.1.7.2", +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "pytest-cov>=5.0.0", +] + +[tool.hatch.build.targets.wheel] +packages = ["jumpstarter_cli_common"] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/cli/exporter/README.md b/packages/jumpstarter_cli_exporter/README.md similarity index 100% rename from cli/exporter/README.md rename to packages/jumpstarter_cli_exporter/README.md diff --git a/cli/exporter/jumpstarter_exporter_cli/__init__.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/__init__.py similarity index 100% rename from cli/exporter/jumpstarter_exporter_cli/__init__.py rename to packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/__init__.py diff --git a/cli/exporter/jumpstarter_exporter_cli/exporter.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py similarity index 99% rename from cli/exporter/jumpstarter_exporter_cli/exporter.py rename to packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py index 945587535..0944b7d19 100644 --- a/cli/exporter/jumpstarter_exporter_cli/exporter.py +++ b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py @@ -3,7 +3,6 @@ from pathlib import Path import asyncclick as click - from jumpstarter.common.utils import launch_shell from jumpstarter.config.exporter import ExporterConfigV1Alpha1 diff --git a/cli/exporter/jumpstarter_exporter_cli/exporter_config.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py similarity index 99% rename from cli/exporter/jumpstarter_exporter_cli/exporter_config.py rename to packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py index 6283f6098..074ec2662 100644 --- a/cli/exporter/jumpstarter_exporter_cli/exporter_config.py +++ b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py @@ -1,7 +1,6 @@ import asyncclick as click -from jumpstarter_cli_common import make_table - from jumpstarter.config.exporter import ExporterConfigV1Alpha1 +from jumpstarter_cli_common import make_table arg_alias = click.argument("alias", default="default") diff --git a/cli/exporter/jumpstarter_exporter_cli/exporter_test.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py similarity index 60% rename from cli/exporter/jumpstarter_exporter_cli/exporter_test.py rename to packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py index e940690c3..f3824fd21 100644 --- a/cli/exporter/jumpstarter_exporter_cli/exporter_test.py +++ b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py @@ -1,47 +1,52 @@ import pytest from asyncclick.testing import CliRunner - from jumpstarter.config.exporter import ExporterConfigV1Alpha1 -from .exporter_config import exporter +from . import exporter @pytest.fixture def tmp_config_path(tmp_path, monkeypatch): monkeypatch.setattr(ExporterConfigV1Alpha1, "BASE_PATH", tmp_path) + @pytest.mark.anyio async def test_exporter(tmp_config_path): runner = CliRunner() # create exporter non-interactively - result = await runner.invoke(exporter, ["create", "test1", "--endpoint", "example.com:443", "--token", "dummy"]) + result = await runner.invoke( + exporter, ["create-config", "test1", "--endpoint", "example.com:443", "--token", "dummy"] + ) assert result.exit_code == 0 # create duplicate exporter - result = await runner.invoke(exporter, ["create", "test1", "--endpoint", "example.com:443", "--token", "dummy"]) + result = await runner.invoke( + exporter, ["create-config", "test1", "--endpoint", "example.com:443", "--token", "dummy"] + ) assert result.exit_code != 0 # create exporter interactively - result = await runner.invoke(exporter, ["create", "test2"], input="example.org:443\ndummytoken\n") + result = await runner.invoke(exporter, ["create-config", "test2"], input="example.org:443\ndummytoken\n") assert result.exit_code == 0 # list exporters - result = await runner.invoke(exporter, ["list"]) + result = await runner.invoke(exporter, ["list-configs"]) assert result.exit_code == 0 assert "test1" in result.output assert "test2" in result.output # delete exporter - result = await runner.invoke(exporter, ["delete", "test2"]) + result = await runner.invoke(exporter, ["delete-config", "test2"]) assert result.exit_code == 0 ## list exporters - result = await runner.invoke(exporter, ["list"]) + result = await runner.invoke(exporter, ["list-configs"]) assert result.exit_code == 0 assert "test1" in result.output assert "test2" not in result.output + @pytest.fixture def anyio_backend(): return "asyncio" diff --git a/cli/common/pyproject.toml b/packages/jumpstarter_cli_exporter/pyproject.toml similarity index 83% rename from cli/common/pyproject.toml rename to packages/jumpstarter_cli_exporter/pyproject.toml index 56b55b1f2..15fe94fc6 100644 --- a/cli/common/pyproject.toml +++ b/packages/jumpstarter_cli_exporter/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "jumpstarter-cli-common" +name = "jumpstarter-cli-exporter" dynamic = ["version", "urls"] description = "" authors = [ @@ -11,7 +11,7 @@ readme = "README.md" license = { text = "Apache-2.0" } requires-python = ">=3.11" dependencies = [ - "jumpstarter", + "jumpstarter-cli-common", "asyncclick>=8.1.7.2", ] @@ -23,11 +23,11 @@ dev = [ "pytest-cov>=5.0.0", ] -[tool.uv.sources] -jumpstarter-cli-common = { workspace = true } +[project.scripts] +jmp-client = "jumpstarter_cli_exporter:exporter" [tool.hatch.build.targets.wheel] -packages = ["jumpstarter_cli_common"] +packages = ["jumpstarter_cli_exporter"] [tool.hatch.metadata.hooks.vcs.urls] Homepage = "https://jumpstarter.dev" diff --git a/contrib/drivers/can/README.md b/packages/jumpstarter_driver_can/README.md similarity index 100% rename from contrib/drivers/can/README.md rename to packages/jumpstarter_driver_can/README.md diff --git a/contrib/drivers/can/jumpstarter_driver_can/__init__.py b/packages/jumpstarter_driver_can/jumpstarter_driver_can/__init__.py similarity index 100% rename from contrib/drivers/can/jumpstarter_driver_can/__init__.py rename to packages/jumpstarter_driver_can/jumpstarter_driver_can/__init__.py diff --git a/contrib/drivers/can/jumpstarter_driver_can/client.py b/packages/jumpstarter_driver_can/jumpstarter_driver_can/client.py similarity index 100% rename from contrib/drivers/can/jumpstarter_driver_can/client.py rename to packages/jumpstarter_driver_can/jumpstarter_driver_can/client.py diff --git a/contrib/drivers/can/jumpstarter_driver_can/client_test.py b/packages/jumpstarter_driver_can/jumpstarter_driver_can/client_test.py similarity index 100% rename from contrib/drivers/can/jumpstarter_driver_can/client_test.py rename to packages/jumpstarter_driver_can/jumpstarter_driver_can/client_test.py diff --git a/contrib/drivers/can/jumpstarter_driver_can/common.py b/packages/jumpstarter_driver_can/jumpstarter_driver_can/common.py similarity index 100% rename from contrib/drivers/can/jumpstarter_driver_can/common.py rename to packages/jumpstarter_driver_can/jumpstarter_driver_can/common.py diff --git a/contrib/drivers/can/jumpstarter_driver_can/driver.py b/packages/jumpstarter_driver_can/jumpstarter_driver_can/driver.py similarity index 100% rename from contrib/drivers/can/jumpstarter_driver_can/driver.py rename to packages/jumpstarter_driver_can/jumpstarter_driver_can/driver.py diff --git a/contrib/drivers/can/pyproject.toml b/packages/jumpstarter_driver_can/pyproject.toml similarity index 95% rename from contrib/drivers/can/pyproject.toml rename to packages/jumpstarter_driver_can/pyproject.toml index c41cf7247..4162bae1f 100644 --- a/contrib/drivers/can/pyproject.toml +++ b/packages/jumpstarter_driver_can/pyproject.toml @@ -28,7 +28,8 @@ source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}. [tool.hatch.version] source = "vcs" -raw-options = { 'root' = '../../../'} +raw-options = { 'root' = '../../'} + [build-system] requires = ["hatchling", "hatch-vcs"] build-backend = "hatchling.build" diff --git a/packages/jumpstarter_driver_composite/README.md b/packages/jumpstarter_driver_composite/README.md new file mode 100644 index 000000000..8b8344e69 --- /dev/null +++ b/packages/jumpstarter_driver_composite/README.md @@ -0,0 +1 @@ +# Jumpstarter Composite Driver \ No newline at end of file diff --git a/contrib/drivers/dutlink/jumpstarter_driver_dutlink/__init__.py b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/__init__.py similarity index 100% rename from contrib/drivers/dutlink/jumpstarter_driver_dutlink/__init__.py rename to packages/jumpstarter_driver_composite/jumpstarter_driver_composite/__init__.py diff --git a/jumpstarter/drivers/composite/client.py b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py similarity index 99% rename from jumpstarter/drivers/composite/client.py rename to packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py index fed7d169e..273e0434f 100644 --- a/jumpstarter/drivers/composite/client.py +++ b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py @@ -1,7 +1,6 @@ from dataclasses import dataclass import asyncclick as click - from jumpstarter.client import DriverClient diff --git a/jumpstarter/drivers/composite/driver.py b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py similarity index 76% rename from jumpstarter/drivers/composite/driver.py rename to packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py index 57cdb878c..438ce317b 100644 --- a/jumpstarter/drivers/composite/driver.py +++ b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py @@ -1,12 +1,11 @@ -from pydantic.dataclasses import dataclass - from jumpstarter.driver import Driver +from pydantic.dataclasses import dataclass class CompositeInterface: @classmethod def client(cls) -> str: - return "jumpstarter.drivers.composite.client.CompositeClient" + return "jumpstarter_driver_composite.client.CompositeClient" @dataclass(kw_only=True) diff --git a/jumpstarter/drivers/composite/driver_test.py b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py similarity index 80% rename from jumpstarter/drivers/composite/driver_test.py rename to packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py index 05614c21b..b2adf6d02 100644 --- a/jumpstarter/drivers/composite/driver_test.py +++ b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py @@ -1,6 +1,7 @@ from jumpstarter.common.utils import serve -from jumpstarter.drivers.composite.driver import Composite -from jumpstarter.drivers.power.driver import MockPower +from jumpstarter_driver_power.driver import MockPower + +from .driver import Composite def test_drivers_composite(): diff --git a/contrib/drivers/dutlink/pyproject.toml b/packages/jumpstarter_driver_composite/pyproject.toml similarity index 79% rename from contrib/drivers/dutlink/pyproject.toml rename to packages/jumpstarter_driver_composite/pyproject.toml index 8b2d3a83a..e5e2015ef 100644 --- a/contrib/drivers/dutlink/pyproject.toml +++ b/packages/jumpstarter_driver_composite/pyproject.toml @@ -1,25 +1,24 @@ [project] -name = "jumpstarter-driver-dutlink" +name = "jumpstarter-driver-composite" dynamic = ["version", "urls"] description = "" authors = [ { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, { name = "Nick Cao", email = "ncao@redhat.com" }, - { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, ] readme = "README.md" license = { text = "Apache-2.0" } requires-python = ">=3.11" dependencies = [ "jumpstarter", - "pyudev>=0.24.3", - "pyusb>=1.2.1", + "asyncclick>=8.1.7.2" ] [dependency-groups] dev = [ "pytest>=8.3.2", "pytest-cov>=5.0.0", + "jumpstarter-driver-power" ] [tool.hatch.metadata.hooks.vcs.urls] @@ -28,7 +27,7 @@ source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}. [tool.hatch.version] source = "vcs" -raw-options = { 'root' = '../../../'} +raw-options = { 'root' = '../../'} [build-system] requires = ["hatchling", "hatch-vcs"] diff --git a/contrib/drivers/dutlink/README.md b/packages/jumpstarter_driver_dutlink/README.md similarity index 100% rename from contrib/drivers/dutlink/README.md rename to packages/jumpstarter_driver_dutlink/README.md diff --git a/contrib/drivers/dutlink/examples/dutlink.py b/packages/jumpstarter_driver_dutlink/examples/dutlink.py similarity index 96% rename from contrib/drivers/dutlink/examples/dutlink.py rename to packages/jumpstarter_driver_dutlink/examples/dutlink.py index 02cec55ec..b04840f40 100755 --- a/contrib/drivers/dutlink/examples/dutlink.py +++ b/packages/jumpstarter_driver_dutlink/examples/dutlink.py @@ -3,9 +3,8 @@ import time import asyncclick as click - -from jumpstarter.client.adapters import PexpectAdapter from jumpstarter.common.utils import env +from jumpstarter_driver_network.adapters import PexpectAdapter # initialize client from exporter config # from jumpstarter.common import MetadataFilter diff --git a/contrib/drivers/dutlink/examples/exporter.yaml b/packages/jumpstarter_driver_dutlink/examples/exporter.yaml similarity index 100% rename from contrib/drivers/dutlink/examples/exporter.yaml rename to packages/jumpstarter_driver_dutlink/examples/exporter.yaml diff --git a/contrib/drivers/http/src/jumpstarter_driver_http/__init__.py b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/__init__.py similarity index 100% rename from contrib/drivers/http/src/jumpstarter_driver_http/__init__.py rename to packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/__init__.py diff --git a/contrib/drivers/dutlink/jumpstarter_driver_dutlink/driver.py b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py similarity index 97% rename from contrib/drivers/dutlink/jumpstarter_driver_dutlink/driver.py rename to packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py index a0d3b114b..00ce088a6 100644 --- a/contrib/drivers/dutlink/jumpstarter_driver_dutlink/driver.py +++ b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py @@ -11,13 +11,12 @@ import usb.util from anyio import fail_after, sleep from anyio.streams.file import FileReadStream, FileWriteStream -from serial.serialutil import SerialException - from jumpstarter.driver import Driver, export -from jumpstarter.drivers.composite.driver import CompositeInterface -from jumpstarter.drivers.power.driver import PowerInterface, PowerReading -from jumpstarter.drivers.pyserial.driver import PySerial -from jumpstarter.drivers.storage.driver import StorageMuxInterface +from jumpstarter_driver_composite.driver import CompositeInterface +from jumpstarter_driver_opendal.driver import StorageMuxInterface +from jumpstarter_driver_power.driver import PowerInterface, PowerReading +from jumpstarter_driver_pyserial.driver import PySerial +from serial.serialutil import SerialException log = logging.getLogger(__name__) diff --git a/contrib/drivers/dutlink/jumpstarter_driver_dutlink/driver_test.py b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py similarity index 94% rename from contrib/drivers/dutlink/jumpstarter_driver_dutlink/driver_test.py rename to packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py index c877bbb39..efab289d4 100644 --- a/contrib/drivers/dutlink/jumpstarter_driver_dutlink/driver_test.py +++ b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py @@ -1,8 +1,8 @@ import pytest import usb - -from jumpstarter.client.adapters import PexpectAdapter from jumpstarter.common.utils import serve +from jumpstarter_driver_network.adapters import PexpectAdapter + from jumpstarter_driver_dutlink.driver import Dutlink diff --git a/packages/jumpstarter_driver_dutlink/pyproject.toml b/packages/jumpstarter_driver_dutlink/pyproject.toml new file mode 100644 index 000000000..7878a2267 --- /dev/null +++ b/packages/jumpstarter_driver_dutlink/pyproject.toml @@ -0,0 +1,41 @@ +[project] +name = "jumpstarter-driver-dutlink" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Nick Cao", email = "ncao@redhat.com" }, + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "jumpstarter-driver-composite", + "jumpstarter-driver-pyserial", + "jumpstarter-driver-opendal", + "jumpstarter-driver-network", + "jumpstarter-driver-power", + "pyudev>=0.24.3", + "pyusb>=1.2.1", + "asyncclick>=8.1.7.2" +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-cov>=5.0.0", +] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/contrib/drivers/http/README.md b/packages/jumpstarter_driver_http/README.md similarity index 100% rename from contrib/drivers/http/README.md rename to packages/jumpstarter_driver_http/README.md diff --git a/contrib/drivers/raspberrypi/jumpstarter_driver_raspberrypi/__init__.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/__init__.py similarity index 100% rename from contrib/drivers/raspberrypi/jumpstarter_driver_raspberrypi/__init__.py rename to packages/jumpstarter_driver_http/jumpstarter_driver_http/__init__.py diff --git a/contrib/drivers/http/src/jumpstarter_driver_http/client.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py similarity index 97% rename from contrib/drivers/http/src/jumpstarter_driver_http/client.py rename to packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py index d718bc4a2..ceb1702dd 100644 --- a/contrib/drivers/http/src/jumpstarter_driver_http/client.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py @@ -1,10 +1,9 @@ from dataclasses import dataclass from pathlib import Path -from opendal import Operator - from jumpstarter.client import DriverClient -from jumpstarter.client.adapters.opendal import OpendalAdapter +from jumpstarter_driver_opendal.adapter import OpendalAdapter +from opendal import Operator @dataclass(kw_only=True) diff --git a/contrib/drivers/http/src/jumpstarter_driver_http/driver.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py similarity index 99% rename from contrib/drivers/http/src/jumpstarter_driver_http/driver.py rename to packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py index 060e1a5a9..f55feb096 100644 --- a/contrib/drivers/http/src/jumpstarter_driver_http/driver.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py @@ -7,7 +7,6 @@ import anyio from aiohttp import web from anyio.streams.file import FileWriteStream - from jumpstarter.driver import Driver, export logger = logging.getLogger(__name__) diff --git a/contrib/drivers/http/src/jumpstarter_driver_http/driver_test.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py similarity index 99% rename from contrib/drivers/http/src/jumpstarter_driver_http/driver_test.py rename to packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py index 2a47da734..73d3ec61d 100644 --- a/contrib/drivers/http/src/jumpstarter_driver_http/driver_test.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py @@ -6,7 +6,6 @@ import anyio import pytest from anyio import create_memory_object_stream - from jumpstarter.common.resources import ClientStreamResource from .driver import HttpServer diff --git a/contrib/drivers/http/pyproject.toml b/packages/jumpstarter_driver_http/pyproject.toml similarity index 92% rename from contrib/drivers/http/pyproject.toml rename to packages/jumpstarter_driver_http/pyproject.toml index 07b0452d5..ace8135ed 100644 --- a/contrib/drivers/http/pyproject.toml +++ b/packages/jumpstarter_driver_http/pyproject.toml @@ -10,11 +10,12 @@ requires-python = ">=3.12" dependencies = [ "anyio>=4.6.2.post1", "jumpstarter", + "jumpstarter-driver-opendal" ] [tool.hatch.version] source = "vcs" -raw-options = { 'root' = '../../../'} +raw-options = { 'root' = '../../'} [tool.hatch.metadata.hooks.vcs.urls] Homepage = "https://jumpstarter.dev" diff --git a/packages/jumpstarter_driver_network/README.md b/packages/jumpstarter_driver_network/README.md new file mode 100644 index 000000000..3de611b91 --- /dev/null +++ b/packages/jumpstarter_driver_network/README.md @@ -0,0 +1 @@ +# Jumpstarter Generic Network Driver \ No newline at end of file diff --git a/contrib/drivers/sdwire/jumpstarter_driver_sdwire/__init__.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/__init__.py similarity index 100% rename from contrib/drivers/sdwire/jumpstarter_driver_sdwire/__init__.py rename to packages/jumpstarter_driver_network/jumpstarter_driver_network/__init__.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/__init__.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/__init__.py new file mode 100644 index 000000000..cc043bced --- /dev/null +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/__init__.py @@ -0,0 +1,6 @@ +from .fabric import FabricAdapter +from .novnc import NovncAdapter +from .pexpect import PexpectAdapter +from .portforward import PortforwardAdapter + +__all__ = ["FabricAdapter", "NovncAdapter", "PexpectAdapter", "PortforwardAdapter"] diff --git a/jumpstarter/client/adapters/fabric.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric.py similarity index 100% rename from jumpstarter/client/adapters/fabric.py rename to packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric.py diff --git a/jumpstarter/client/adapters/fabric_test.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py similarity index 92% rename from jumpstarter/client/adapters/fabric_test.py rename to packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py index 4bb7cf79d..6845e257b 100644 --- a/jumpstarter/client/adapters/fabric_test.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py @@ -2,12 +2,12 @@ from threading import Thread from time import sleep +from jumpstarter.common.utils import serve from paramiko import AUTH_SUCCESSFUL, OPEN_SUCCEEDED, ServerInterface, Transport from paramiko.rsakey import RSAKey -from jumpstarter.client.adapters import FabricAdapter -from jumpstarter.common.utils import serve -from jumpstarter.drivers.network.driver import TcpNetwork +from ..driver import TcpNetwork +from .fabric import FabricAdapter class SSHServer(ServerInterface): diff --git a/jumpstarter/client/adapters/novnc.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc.py similarity index 90% rename from jumpstarter/client/adapters/novnc.py rename to packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc.py index fcde6108b..46cbcdb54 100644 --- a/jumpstarter/client/adapters/novnc.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc.py @@ -1,8 +1,9 @@ from dataclasses import dataclass from urllib.parse import urlencode, urlunparse -from jumpstarter.streams import WebsocketServerStream, forward_stream +from jumpstarter.streams import forward_stream +from ..streams import WebsocketServerStream from .portforward import PortforwardAdapter diff --git a/jumpstarter/client/adapters/novnc_test.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py similarity index 90% rename from jumpstarter/client/adapters/novnc_test.py rename to packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py index e5ff861e7..f3b5deaab 100644 --- a/jumpstarter/client/adapters/novnc_test.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py @@ -2,12 +2,12 @@ from urllib.parse import parse_qsl, urlparse from anyio.from_thread import start_blocking_portal -from websocket import create_connection - -from jumpstarter.client.adapters import NovncAdapter from jumpstarter.common import TemporaryTcpListener from jumpstarter.common.utils import serve -from jumpstarter.drivers.network.driver import TcpNetwork +from websocket import create_connection + +from ..driver import TcpNetwork +from .novnc import NovncAdapter async def echo_handler(stream): diff --git a/jumpstarter/client/adapters/pexpect.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/pexpect.py similarity index 100% rename from jumpstarter/client/adapters/pexpect.py rename to packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/pexpect.py diff --git a/jumpstarter/client/adapters/portforward.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/portforward.py similarity index 94% rename from jumpstarter/client/adapters/portforward.py rename to packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/portforward.py index b4dca1c71..c180fb340 100644 --- a/jumpstarter/client/adapters/portforward.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/portforward.py @@ -1,10 +1,9 @@ from dataclasses import dataclass +from jumpstarter.client.adapters import ClientAdapter from jumpstarter.common import TemporaryTcpListener from jumpstarter.streams import forward_stream -from .common import ClientAdapter - @dataclass(kw_only=True) class PortforwardAdapter(ClientAdapter): diff --git a/jumpstarter/drivers/network/client.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/client.py similarity index 100% rename from jumpstarter/drivers/network/client.py rename to packages/jumpstarter_driver_network/jumpstarter_driver_network/client.py diff --git a/jumpstarter/drivers/network/driver.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py similarity index 96% rename from jumpstarter/drivers/network/driver.py rename to packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py index b88763606..8b2293ef7 100644 --- a/jumpstarter/drivers/network/driver.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py @@ -10,7 +10,6 @@ create_memory_object_stream, ) from anyio.streams.stapled import StapledObjectStream - from jumpstarter.driver import Driver, exportstream logger = logging.getLogger(__name__) @@ -19,7 +18,7 @@ class NetworkInterface(metaclass=ABCMeta): @classmethod def client(cls) -> str: - return "jumpstarter.drivers.network.client.NetworkClient" + return "jumpstarter_driver_network.client.NetworkClient" @abstractmethod @asynccontextmanager diff --git a/jumpstarter/drivers/network/driver_test.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py similarity index 95% rename from jumpstarter/drivers/network/driver_test.py rename to packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py index 8dd41f083..647e229be 100644 --- a/jumpstarter/drivers/network/driver_test.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py @@ -5,11 +5,11 @@ import pytest from anyio.from_thread import start_blocking_portal - -from jumpstarter.client.adapters import PortforwardAdapter from jumpstarter.common import TemporaryTcpListener, TemporaryUnixListener from jumpstarter.common.utils import serve -from jumpstarter.drivers.network.driver import EchoNetwork, TcpNetwork, UdpNetwork, UnixNetwork + +from .adapters import PortforwardAdapter +from .driver import EchoNetwork, TcpNetwork, UdpNetwork, UnixNetwork def test_echo_network(): diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/streams/__init__.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/streams/__init__.py new file mode 100644 index 000000000..786b8e4e1 --- /dev/null +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/streams/__init__.py @@ -0,0 +1,3 @@ +from .websocket import WebsocketServerStream + +__all__ = ["WebsocketServerStream"] diff --git a/jumpstarter/streams/websocket.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/streams/websocket.py similarity index 95% rename from jumpstarter/streams/websocket.py rename to packages/jumpstarter_driver_network/jumpstarter_driver_network/streams/websocket.py index 49beb43be..e79ed07c8 100644 --- a/jumpstarter/streams/websocket.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/streams/websocket.py @@ -1,5 +1,6 @@ from contextlib import suppress from dataclasses import dataclass, field +from typing import Tuple from anyio import BrokenResourceError, WouldBlock, create_memory_object_stream from anyio.abc import AnyByteStream, ObjectStream @@ -22,7 +23,7 @@ class WebsocketServerStream(ObjectStream[bytes]): stream: AnyByteStream ws: WSConnection = field(init=False, default_factory=lambda: WSConnection(ConnectionType.SERVER)) - queue: (MemoryObjectSendStream[bytes], MemoryObjectReceiveStream[bytes]) = field( + queue: Tuple[MemoryObjectSendStream[bytes], MemoryObjectReceiveStream[bytes]] = field( init=False, default_factory=lambda: create_memory_object_stream[bytes](32) ) diff --git a/packages/jumpstarter_driver_network/pyproject.toml b/packages/jumpstarter_driver_network/pyproject.toml new file mode 100644 index 000000000..1e01f85aa --- /dev/null +++ b/packages/jumpstarter_driver_network/pyproject.toml @@ -0,0 +1,36 @@ +[project] +name = "jumpstarter-driver-network" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Nick Cao", email = "ncao@redhat.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "pexpect>=4.9.0", + "fabric>=3.2.2", + "wsproto>=1.2.0" +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-cov>=5.0.0", + "websocket-client>=1.8.0" +] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/packages/jumpstarter_driver_opendal/README.md b/packages/jumpstarter_driver_opendal/README.md new file mode 100644 index 000000000..e361e0070 --- /dev/null +++ b/packages/jumpstarter_driver_opendal/README.md @@ -0,0 +1 @@ +# Jumpstarter OpenDAL Storage Driver \ No newline at end of file diff --git a/contrib/drivers/tftp/src/jumpstarter_driver_tftp/__init__.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/__init__.py similarity index 100% rename from contrib/drivers/tftp/src/jumpstarter_driver_tftp/__init__.py rename to packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/__init__.py diff --git a/jumpstarter/client/adapters/opendal.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py similarity index 97% rename from jumpstarter/client/adapters/opendal.py rename to packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py index 82a5a7b8e..a94be7948 100644 --- a/jumpstarter/client/adapters/opendal.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py @@ -4,13 +4,11 @@ from anyio import BrokenResourceError, EndOfStream from anyio.abc import ObjectStream +from jumpstarter.client.adapters import ClientAdapter +from jumpstarter.common.resources import PresignedRequestResource from opendal import AsyncFile, Operator from opendal.exceptions import Error -from jumpstarter.common.resources import PresignedRequestResource - -from .common import ClientAdapter - @dataclass(frozen=True, kw_only=True, slots=True) class AsyncFileStream(ObjectStream[bytes]): diff --git a/jumpstarter/drivers/storage/client.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py similarity index 97% rename from jumpstarter/drivers/storage/client.py rename to packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py index 186a0e76c..261a86069 100644 --- a/jumpstarter/drivers/storage/client.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py @@ -1,10 +1,10 @@ from pathlib import Path import asyncclick as click +from jumpstarter.client import DriverClient from opendal import Operator -from jumpstarter.client import DriverClient -from jumpstarter.client.adapters import OpendalAdapter +from .adapter import OpendalAdapter class StorageMuxClient(DriverClient): diff --git a/jumpstarter/drivers/storage/driver.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py similarity index 95% rename from jumpstarter/drivers/storage/driver.py rename to packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py index cd72636f6..47d36f19b 100644 --- a/jumpstarter/drivers/storage/driver.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py @@ -3,14 +3,13 @@ from tempfile import NamedTemporaryFile from anyio.streams.file import FileReadStream, FileWriteStream - from jumpstarter.driver import Driver, export class StorageMuxInterface(metaclass=ABCMeta): @classmethod def client(cls) -> str: - return "jumpstarter.drivers.storage.client.StorageMuxClient" + return "jumpstarter_driver_opendal.client.StorageMuxClient" @abstractmethod async def host(self): ... diff --git a/jumpstarter/drivers/storage/driver_test.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py similarity index 97% rename from jumpstarter/drivers/storage/driver_test.py rename to packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py index 2fe55a336..90221b443 100644 --- a/jumpstarter/drivers/storage/driver_test.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py @@ -5,10 +5,10 @@ from threading import Thread import pytest +from jumpstarter.common.utils import serve from opendal import Operator -from jumpstarter.common.utils import serve -from jumpstarter.drivers.storage.driver import MockStorageMux +from .driver import MockStorageMux def test_drivers_mock_storage_mux_fs(monkeypatch: pytest.MonkeyPatch): diff --git a/packages/jumpstarter_driver_opendal/pyproject.toml b/packages/jumpstarter_driver_opendal/pyproject.toml new file mode 100644 index 000000000..2f89c3934 --- /dev/null +++ b/packages/jumpstarter_driver_opendal/pyproject.toml @@ -0,0 +1,34 @@ +[project] +name = "jumpstarter-driver-opendal" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Nick Cao", email = "ncao@redhat.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "opendal>=0.45.8", + "asyncclick>=8.1.7.2" +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-cov>=5.0.0", +] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/packages/jumpstarter_driver_power/README.md b/packages/jumpstarter_driver_power/README.md new file mode 100644 index 000000000..28e04653a --- /dev/null +++ b/packages/jumpstarter_driver_power/README.md @@ -0,0 +1 @@ +# Jumpstarter Power Driver Interface \ No newline at end of file diff --git a/contrib/drivers/ustreamer/jumpstarter_driver_ustreamer/__init__.py b/packages/jumpstarter_driver_power/jumpstarter_driver_power/__init__.py similarity index 100% rename from contrib/drivers/ustreamer/jumpstarter_driver_ustreamer/__init__.py rename to packages/jumpstarter_driver_power/jumpstarter_driver_power/__init__.py diff --git a/jumpstarter/drivers/power/client.py b/packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py similarity index 99% rename from jumpstarter/drivers/power/client.py rename to packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py index f9aa897d7..be2003773 100644 --- a/jumpstarter/drivers/power/client.py +++ b/packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py @@ -1,7 +1,6 @@ from collections.abc import Generator import asyncclick as click - from jumpstarter.client import DriverClient from .common import PowerReading diff --git a/jumpstarter/drivers/power/client_test.py b/packages/jumpstarter_driver_power/jumpstarter_driver_power/client_test.py similarity index 83% rename from jumpstarter/drivers/power/client_test.py rename to packages/jumpstarter_driver_power/jumpstarter_driver_power/client_test.py index 7422f9196..d8dad4d9d 100644 --- a/jumpstarter/drivers/power/client_test.py +++ b/packages/jumpstarter_driver_power/jumpstarter_driver_power/client_test.py @@ -1,6 +1,7 @@ from jumpstarter.common.utils import serve -from jumpstarter.drivers.power.common import PowerReading -from jumpstarter.drivers.power.driver import MockPower, SyncMockPower + +from .common import PowerReading +from .driver import MockPower, SyncMockPower def test_client_mock_power(): diff --git a/jumpstarter/drivers/power/common.py b/packages/jumpstarter_driver_power/jumpstarter_driver_power/common.py similarity index 100% rename from jumpstarter/drivers/power/common.py rename to packages/jumpstarter_driver_power/jumpstarter_driver_power/common.py diff --git a/jumpstarter/drivers/power/driver.py b/packages/jumpstarter_driver_power/jumpstarter_driver_power/driver.py similarity index 86% rename from jumpstarter/drivers/power/driver.py rename to packages/jumpstarter_driver_power/jumpstarter_driver_power/driver.py index 21bf8a223..c31c9bd0c 100644 --- a/jumpstarter/drivers/power/driver.py +++ b/packages/jumpstarter_driver_power/jumpstarter_driver_power/driver.py @@ -1,5 +1,5 @@ from abc import ABCMeta, abstractmethod -from collections.abc import AsyncGenerator +from collections.abc import AsyncGenerator, Generator from jumpstarter.driver import Driver, export @@ -9,7 +9,7 @@ class PowerInterface(metaclass=ABCMeta): @classmethod def client(cls) -> str: - return "jumpstarter.drivers.power.client.PowerClient" + return "jumpstarter_driver_power.client.PowerClient" @abstractmethod async def on(self) -> str: ... @@ -46,6 +46,6 @@ def off(self) -> str: return "ok" @export - def read(self) -> AsyncGenerator[PowerReading, None]: + def read(self) -> Generator[PowerReading, None]: yield PowerReading(voltage=0.0, current=0.0) yield PowerReading(voltage=5.0, current=2.0) diff --git a/jumpstarter/drivers/power/driver_test.py b/packages/jumpstarter_driver_power/jumpstarter_driver_power/driver_test.py similarity index 82% rename from jumpstarter/drivers/power/driver_test.py rename to packages/jumpstarter_driver_power/jumpstarter_driver_power/driver_test.py index 06807deba..f0824ff47 100644 --- a/jumpstarter/drivers/power/driver_test.py +++ b/packages/jumpstarter_driver_power/jumpstarter_driver_power/driver_test.py @@ -1,7 +1,7 @@ import pytest -from jumpstarter.drivers.power.common import PowerReading -from jumpstarter.drivers.power.driver import MockPower, SyncMockPower +from .common import PowerReading +from .driver import MockPower, SyncMockPower pytestmark = pytest.mark.anyio diff --git a/packages/jumpstarter_driver_power/pyproject.toml b/packages/jumpstarter_driver_power/pyproject.toml new file mode 100644 index 000000000..19e7378a0 --- /dev/null +++ b/packages/jumpstarter_driver_power/pyproject.toml @@ -0,0 +1,35 @@ +[project] +name = "jumpstarter-driver-power" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Nick Cao", email = "ncao@redhat.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "pyserial>=3.5", + "asyncclick>=8.1.7.2" +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-cov>=5.0.0", + "trio>=0.28.0" +] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/packages/jumpstarter_driver_pyserial/README.md b/packages/jumpstarter_driver_pyserial/README.md new file mode 100644 index 000000000..eeb22dae0 --- /dev/null +++ b/packages/jumpstarter_driver_pyserial/README.md @@ -0,0 +1 @@ +# Jumpstarter PySerial Driver \ No newline at end of file diff --git a/jumpstarter/drivers/composite/__init__.py b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/__init__.py similarity index 100% rename from jumpstarter/drivers/composite/__init__.py rename to packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/__init__.py diff --git a/jumpstarter/drivers/pyserial/client.py b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py similarity index 95% rename from jumpstarter/drivers/pyserial/client.py rename to packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py index 5acddd12f..f6640cc49 100644 --- a/jumpstarter/drivers/pyserial/client.py +++ b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py @@ -1,16 +1,14 @@ from contextlib import contextmanager import asyncclick as click -from pexpect.fdpexpect import fdspawn - from jumpstarter.client import DriverClient -from jumpstarter.client.adapters import PexpectAdapter +from jumpstarter_driver_network.adapters import PexpectAdapter +from pexpect.fdpexpect import fdspawn from .console import Console class PySerialClient(DriverClient): - """ A client for handling serial communication using pexpect. diff --git a/jumpstarter/drivers/pyserial/console.py b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/console.py similarity index 100% rename from jumpstarter/drivers/pyserial/console.py rename to packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/console.py diff --git a/jumpstarter/drivers/pyserial/driver.py b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py similarity index 95% rename from jumpstarter/drivers/pyserial/driver.py rename to packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py index 7a0f60d67..69d4d0f88 100644 --- a/jumpstarter/drivers/pyserial/driver.py +++ b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py @@ -4,9 +4,8 @@ from anyio.abc import ObjectStream from anyio.to_thread import run_sync -from serial import Serial, serial_for_url - from jumpstarter.driver import Driver, exportstream +from serial import Serial, serial_for_url log = logging.getLogger(__name__) @@ -41,7 +40,7 @@ def __post_init__(self): @classmethod def client(cls) -> str: - return "jumpstarter.drivers.pyserial.client.PySerialClient" + return "jumpstarter_driver_pyserial.client.PySerialClient" @exportstream @asynccontextmanager diff --git a/jumpstarter/drivers/pyserial/driver_test.py b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver_test.py similarity index 92% rename from jumpstarter/drivers/pyserial/driver_test.py rename to packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver_test.py index 2394edb6d..141000a20 100644 --- a/jumpstarter/drivers/pyserial/driver_test.py +++ b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver_test.py @@ -1,8 +1,9 @@ from typing import cast from jumpstarter.common.utils import serve -from jumpstarter.drivers.pyserial.client import PySerialClient -from jumpstarter.drivers.pyserial.driver import PySerial + +from .client import PySerialClient +from .driver import PySerial def test_bare_pyserial(): diff --git a/packages/jumpstarter_driver_pyserial/pyproject.toml b/packages/jumpstarter_driver_pyserial/pyproject.toml new file mode 100644 index 000000000..5330454c8 --- /dev/null +++ b/packages/jumpstarter_driver_pyserial/pyproject.toml @@ -0,0 +1,35 @@ +[project] +name = "jumpstarter-driver-pyserial" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, + { name = "Nick Cao", email = "ncao@redhat.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "jumpstarter-driver-network", + "pyserial>=3.5", + "asyncclick>=8.1.7.2" +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-cov>=5.0.0", +] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/contrib/drivers/raspberrypi/README.md b/packages/jumpstarter_driver_raspberrypi/README.md similarity index 100% rename from contrib/drivers/raspberrypi/README.md rename to packages/jumpstarter_driver_raspberrypi/README.md diff --git a/jumpstarter/drivers/network/__init__.py b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/__init__.py similarity index 100% rename from jumpstarter/drivers/network/__init__.py rename to packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/__init__.py diff --git a/contrib/drivers/raspberrypi/jumpstarter_driver_raspberrypi/client.py b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/client.py similarity index 100% rename from contrib/drivers/raspberrypi/jumpstarter_driver_raspberrypi/client.py rename to packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/client.py diff --git a/contrib/drivers/raspberrypi/jumpstarter_driver_raspberrypi/driver.py b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py similarity index 100% rename from contrib/drivers/raspberrypi/jumpstarter_driver_raspberrypi/driver.py rename to packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py diff --git a/contrib/drivers/raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py similarity index 100% rename from contrib/drivers/raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py rename to packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py diff --git a/contrib/drivers/raspberrypi/pyproject.toml b/packages/jumpstarter_driver_raspberrypi/pyproject.toml similarity index 95% rename from contrib/drivers/raspberrypi/pyproject.toml rename to packages/jumpstarter_driver_raspberrypi/pyproject.toml index 730287608..2d2665fbb 100644 --- a/contrib/drivers/raspberrypi/pyproject.toml +++ b/packages/jumpstarter_driver_raspberrypi/pyproject.toml @@ -27,7 +27,7 @@ source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}. [tool.hatch.version] source = "vcs" -raw-options = { 'root' = '../../../'} +raw-options = { 'root' = '../../'} [build-system] requires = ["hatchling", "hatch-vcs"] diff --git a/contrib/drivers/sdwire/README.md b/packages/jumpstarter_driver_sdwire/README.md similarity index 100% rename from contrib/drivers/sdwire/README.md rename to packages/jumpstarter_driver_sdwire/README.md diff --git a/jumpstarter/drivers/power/__init__.py b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/__init__.py similarity index 100% rename from jumpstarter/drivers/power/__init__.py rename to packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/__init__.py diff --git a/contrib/drivers/sdwire/jumpstarter_driver_sdwire/driver.py b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py similarity index 98% rename from contrib/drivers/sdwire/jumpstarter_driver_sdwire/driver.py rename to packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py index a73e7068a..ad5d94419 100644 --- a/contrib/drivers/sdwire/jumpstarter_driver_sdwire/driver.py +++ b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py @@ -8,9 +8,8 @@ import usb.util from anyio import fail_after, sleep from anyio.streams.file import FileReadStream, FileWriteStream - from jumpstarter.driver import Driver, export -from jumpstarter.drivers.storage.driver import StorageMuxInterface +from jumpstarter_driver_opendal.driver import StorageMuxInterface @dataclass(kw_only=True) diff --git a/contrib/drivers/sdwire/jumpstarter_driver_sdwire/driver_test.py b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py similarity index 100% rename from contrib/drivers/sdwire/jumpstarter_driver_sdwire/driver_test.py rename to packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py index d6d9c9aed..8f4434d0d 100644 --- a/contrib/drivers/sdwire/jumpstarter_driver_sdwire/driver_test.py +++ b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py @@ -1,7 +1,7 @@ import pytest import usb - from jumpstarter.common.utils import serve + from jumpstarter_driver_sdwire.driver import SDWire diff --git a/contrib/drivers/sdwire/pyproject.toml b/packages/jumpstarter_driver_sdwire/pyproject.toml similarity index 90% rename from contrib/drivers/sdwire/pyproject.toml rename to packages/jumpstarter_driver_sdwire/pyproject.toml index 317468cee..d373c0053 100644 --- a/contrib/drivers/sdwire/pyproject.toml +++ b/packages/jumpstarter_driver_sdwire/pyproject.toml @@ -10,6 +10,7 @@ license = { text = "Apache-2.0" } requires-python = ">=3.11" dependencies = [ "jumpstarter", + "jumpstarter-driver-opendal", "pyusb>=1.2.1", "pyudev>=0.24.3", ] @@ -26,7 +27,7 @@ source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}. [tool.hatch.version] source = "vcs" -raw-options = { 'root' = '../../../'} +raw-options = { 'root' = '../../'} [build-system] requires = ["hatchling", "hatch-vcs"] diff --git a/contrib/drivers/tftp/README.md b/packages/jumpstarter_driver_tftp/README.md similarity index 100% rename from contrib/drivers/tftp/README.md rename to packages/jumpstarter_driver_tftp/README.md diff --git a/contrib/drivers/tftp/examples/exporter.yaml b/packages/jumpstarter_driver_tftp/examples/exporter.yaml similarity index 86% rename from contrib/drivers/tftp/examples/exporter.yaml rename to packages/jumpstarter_driver_tftp/examples/exporter.yaml index 7b7645db6..fc5a2acf5 100644 --- a/contrib/drivers/tftp/examples/exporter.yaml +++ b/packages/jumpstarter_driver_tftp/examples/exporter.yaml @@ -4,7 +4,7 @@ endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082 token: "" export: serial: - type: "jumpstarter.drivers.pyserial.driver.PySerial" + type: "jumpstarter_driver_pyserial.driver.PySerial" config: url: "/dev/ttyUSB0" baudrate: 1843200 diff --git a/contrib/drivers/tftp/examples/tftp_test.py b/packages/jumpstarter_driver_tftp/examples/tftp_test.py similarity index 83% rename from contrib/drivers/tftp/examples/tftp_test.py rename to packages/jumpstarter_driver_tftp/examples/tftp_test.py index 1108b9320..4cd33831e 100644 --- a/contrib/drivers/tftp/examples/tftp_test.py +++ b/packages/jumpstarter_driver_tftp/examples/tftp_test.py @@ -1,12 +1,17 @@ +import logging import time +import pytest from jumpstarter_driver_tftp.driver import FileNotFound, TftpError +from jumpstarter_testing.pytest import JumpstarterTest -from jumpstarter.common.utils import env +log = logging.getLogger(__name__) +class TestResource(JumpstarterTest): + filter_labels = {"board":"rpi4"} -def test_tftp_upload(): - with env() as client: + @pytest.fixture() + def test_tftp_upload(self, client): try: client.tftp.start() print("TFTP server started") @@ -43,7 +48,3 @@ def test_tftp_upload(): print("TFTP server stopped") except Exception as e: print(f"Error stopping server: {e}") - - -if __name__ == "__main__": - test_tftp_upload() diff --git a/jumpstarter/drivers/pyserial/__init__.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/__init__.py similarity index 100% rename from jumpstarter/drivers/pyserial/__init__.py rename to packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/__init__.py diff --git a/contrib/drivers/tftp/src/jumpstarter_driver_tftp/client.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py similarity index 98% rename from contrib/drivers/tftp/src/jumpstarter_driver_tftp/client.py rename to packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py index b06ee7048..06c009c6f 100644 --- a/contrib/drivers/tftp/src/jumpstarter_driver_tftp/client.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py @@ -1,10 +1,9 @@ from dataclasses import dataclass from pathlib import Path -from opendal import Operator - from jumpstarter.client import DriverClient -from jumpstarter.client.adapters import OpendalAdapter +from jumpstarter_driver_opendal.adapter import OpendalAdapter +from opendal import Operator @dataclass(kw_only=True) diff --git a/contrib/drivers/tftp/src/jumpstarter_driver_tftp/driver.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py similarity index 100% rename from contrib/drivers/tftp/src/jumpstarter_driver_tftp/driver.py rename to packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py index bd4fb7580..de0e24a5b 100644 --- a/contrib/drivers/tftp/src/jumpstarter_driver_tftp/driver.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py @@ -8,8 +8,8 @@ from typing import Optional from anyio.streams.file import FileWriteStream - from jumpstarter.driver import Driver, export + from jumpstarter_driver_tftp.server import TftpServer logger = logging.getLogger(__name__) diff --git a/contrib/drivers/tftp/src/jumpstarter_driver_tftp/driver_test.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py similarity index 100% rename from contrib/drivers/tftp/src/jumpstarter_driver_tftp/driver_test.py rename to packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py index 7cb9f2964..28c8274cf 100644 --- a/contrib/drivers/tftp/src/jumpstarter_driver_tftp/driver_test.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py @@ -6,8 +6,8 @@ import anyio import pytest from anyio import create_memory_object_stream - from jumpstarter.common.resources import ClientStreamResource + from jumpstarter_driver_tftp.driver import ( FileNotFound, Tftp, diff --git a/contrib/drivers/tftp/src/jumpstarter_driver_tftp/server.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py similarity index 100% rename from contrib/drivers/tftp/src/jumpstarter_driver_tftp/server.py rename to packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py diff --git a/contrib/drivers/tftp/src/jumpstarter_driver_tftp/server_test.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server_test.py similarity index 96% rename from contrib/drivers/tftp/src/jumpstarter_driver_tftp/server_test.py rename to packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server_test.py index 612f4a8b1..488fd9f98 100644 --- a/contrib/drivers/tftp/src/jumpstarter_driver_tftp/server_test.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server_test.py @@ -33,7 +33,7 @@ async def create_test_client(server_port): ) return transport, protocol -@pytest.mark.asyncio +@pytest.mark.anyio async def test_server_startup_and_shutdown(tftp_server): """Test that server starts up and shuts down cleanly.""" server, _ = tftp_server @@ -48,7 +48,7 @@ async def test_server_startup_and_shutdown(tftp_server): assert True -@pytest.mark.asyncio +@pytest.mark.anyio async def test_read_request_for_existing_file(tftp_server): """Test reading an existing file from the server.""" server, temp_dir = tftp_server @@ -75,7 +75,7 @@ async def test_read_request_for_existing_file(tftp_server): await server.shutdown() await server_task -@pytest.mark.asyncio +@pytest.mark.anyio async def test_read_request_for_nonexistent_file(tftp_server): """Test reading a non-existent file returns appropriate error.""" server, _ = tftp_server @@ -102,7 +102,7 @@ async def test_read_request_for_nonexistent_file(tftp_server): await server.shutdown() await server_task -@pytest.mark.asyncio +@pytest.mark.anyio async def test_write_request_rejection(tftp_server): """Test that write requests are properly rejected (server is read-only).""" server, _ = tftp_server @@ -127,7 +127,7 @@ async def test_write_request_rejection(tftp_server): await server.shutdown() await server_task -@pytest.mark.asyncio +@pytest.mark.anyio async def test_invalid_packet_handling(tftp_server): server, _ = tftp_server server_task = asyncio.create_task(server.start()) @@ -145,7 +145,7 @@ async def test_invalid_packet_handling(tftp_server): await server.shutdown() await server_task -@pytest.mark.asyncio +@pytest.mark.anyio async def test_path_traversal_prevention(tftp_server): """Test that path traversal attempts are blocked.""" server, _ = tftp_server @@ -171,3 +171,7 @@ async def test_path_traversal_prevention(tftp_server): transport.close() await server.shutdown() await server_task + +@pytest.fixture +def anyio_backend(): + return "asyncio" diff --git a/contrib/drivers/tftp/pyproject.toml b/packages/jumpstarter_driver_tftp/pyproject.toml similarity index 62% rename from contrib/drivers/tftp/pyproject.toml rename to packages/jumpstarter_driver_tftp/pyproject.toml index b4846d56a..830c47bb9 100644 --- a/contrib/drivers/tftp/pyproject.toml +++ b/packages/jumpstarter_driver_tftp/pyproject.toml @@ -10,32 +10,35 @@ requires-python = ">=3.12" dependencies = [ "anyio>=4.6.2.post1", "jumpstarter", + "jumpstarter-driver-opendal", "aiofiles>=24.1.0" ] +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-cov>=6.0.0", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "jumpstarter-testing" +] + + [tool.hatch.version] source = "vcs" -raw-options = { 'root' = '../../../'} +raw-options = { 'root' = '../../'} [tool.hatch.metadata.hooks.vcs.urls] Homepage = "https://jumpstarter.dev" source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" -[tool.pytest.ini_options] -#addopts = "--cov --cov-report=html --cov-report=xml" -log_cli = true -log_cli_level = "INFO" -testpaths = ["src"] -asyncio_mode = "auto" +# [tool.pytest.ini_options] +# #addopts = "--cov --cov-report=html --cov-report=xml" +# log_cli = true +# log_cli_level = "INFO" +# # testpaths = ["src"] +# asyncio_mode = "auto" [build-system] requires = ["hatchling", "hatch-vcs"] -build-backend = "hatchling.build" - -[dependency-groups] -dev = [ - "pytest-cov>=6.0.0", - "pytest>=8.3.3", - "ruff>=0.7.1", - -] +build-backend = "hatchling.build" \ No newline at end of file diff --git a/contrib/drivers/tftp/test.txt b/packages/jumpstarter_driver_tftp/test.txt similarity index 100% rename from contrib/drivers/tftp/test.txt rename to packages/jumpstarter_driver_tftp/test.txt diff --git a/contrib/drivers/ustreamer/README.md b/packages/jumpstarter_driver_ustreamer/README.md similarity index 100% rename from contrib/drivers/ustreamer/README.md rename to packages/jumpstarter_driver_ustreamer/README.md diff --git a/jumpstarter/drivers/storage/__init__.py b/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/__init__.py similarity index 100% rename from jumpstarter/drivers/storage/__init__.py rename to packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/__init__.py diff --git a/contrib/drivers/ustreamer/jumpstarter_driver_ustreamer/client.py b/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/client.py similarity index 100% rename from contrib/drivers/ustreamer/jumpstarter_driver_ustreamer/client.py rename to packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/client.py diff --git a/contrib/drivers/ustreamer/jumpstarter_driver_ustreamer/common.py b/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/common.py similarity index 100% rename from contrib/drivers/ustreamer/jumpstarter_driver_ustreamer/common.py rename to packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/common.py diff --git a/contrib/drivers/ustreamer/jumpstarter_driver_ustreamer/driver.py b/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver.py similarity index 100% rename from contrib/drivers/ustreamer/jumpstarter_driver_ustreamer/driver.py rename to packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver.py diff --git a/contrib/drivers/ustreamer/jumpstarter_driver_ustreamer/driver_test.py b/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver_test.py similarity index 100% rename from contrib/drivers/ustreamer/jumpstarter_driver_ustreamer/driver_test.py rename to packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver_test.py diff --git a/contrib/drivers/ustreamer/pyproject.toml b/packages/jumpstarter_driver_ustreamer/pyproject.toml similarity index 95% rename from contrib/drivers/ustreamer/pyproject.toml rename to packages/jumpstarter_driver_ustreamer/pyproject.toml index 3b5238553..1d6d2f606 100644 --- a/contrib/drivers/ustreamer/pyproject.toml +++ b/packages/jumpstarter_driver_ustreamer/pyproject.toml @@ -27,7 +27,7 @@ source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}. [tool.hatch.version] source = "vcs" -raw-options = { 'root' = '../../../'} +raw-options = { 'root' = '../../'} [build-system] requires = ["hatchling", "hatch-vcs"] diff --git a/contrib/libs/imagehash/README.md b/packages/jumpstarter_imagehash/README.md similarity index 100% rename from contrib/libs/imagehash/README.md rename to packages/jumpstarter_imagehash/README.md diff --git a/contrib/libs/imagehash/jumpstarter_imagehash/__init__.py b/packages/jumpstarter_imagehash/jumpstarter_imagehash/__init__.py similarity index 100% rename from contrib/libs/imagehash/jumpstarter_imagehash/__init__.py rename to packages/jumpstarter_imagehash/jumpstarter_imagehash/__init__.py diff --git a/contrib/libs/imagehash/jumpstarter_imagehash/imagehash.py b/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py similarity index 100% rename from contrib/libs/imagehash/jumpstarter_imagehash/imagehash.py rename to packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py diff --git a/contrib/libs/imagehash/jumpstarter_imagehash/imagehash_test.py b/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash_test.py similarity index 100% rename from contrib/libs/imagehash/jumpstarter_imagehash/imagehash_test.py rename to packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash_test.py diff --git a/contrib/libs/imagehash/jumpstarter_imagehash/test_image_a.jpeg b/packages/jumpstarter_imagehash/jumpstarter_imagehash/test_image_a.jpeg similarity index 100% rename from contrib/libs/imagehash/jumpstarter_imagehash/test_image_a.jpeg rename to packages/jumpstarter_imagehash/jumpstarter_imagehash/test_image_a.jpeg diff --git a/contrib/libs/imagehash/jumpstarter_imagehash/test_image_b.jpeg b/packages/jumpstarter_imagehash/jumpstarter_imagehash/test_image_b.jpeg similarity index 100% rename from contrib/libs/imagehash/jumpstarter_imagehash/test_image_b.jpeg rename to packages/jumpstarter_imagehash/jumpstarter_imagehash/test_image_b.jpeg diff --git a/contrib/libs/imagehash/pyproject.toml b/packages/jumpstarter_imagehash/pyproject.toml similarity index 95% rename from contrib/libs/imagehash/pyproject.toml rename to packages/jumpstarter_imagehash/pyproject.toml index ff3095349..d100c3d30 100644 --- a/contrib/libs/imagehash/pyproject.toml +++ b/packages/jumpstarter_imagehash/pyproject.toml @@ -27,7 +27,7 @@ source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}. [tool.hatch.version] source = "vcs" -raw-options = { 'root' = '../../../'} +raw-options = { 'root' = '../../'} [build-system] requires = ["hatchling", "hatch-vcs"] diff --git a/packages/jumpstarter_kubernetes/README.md b/packages/jumpstarter_kubernetes/README.md new file mode 100644 index 000000000..47affcc4e --- /dev/null +++ b/packages/jumpstarter_kubernetes/README.md @@ -0,0 +1 @@ +# Jumpstarter Kubernetes Library \ No newline at end of file diff --git a/jumpstarter/k8s/__init__.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/__init__.py similarity index 96% rename from jumpstarter/k8s/__init__.py rename to packages/jumpstarter_kubernetes/jumpstarter_kubernetes/__init__.py index f1612ea21..9ec397ccb 100644 --- a/jumpstarter/k8s/__init__.py +++ b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/__init__.py @@ -17,5 +17,5 @@ "V1Alpha1LeaseSpec", "get_ip_address", "helm_installed", - "install_helm_chart", + "install_helm_chart" ] diff --git a/jumpstarter/k8s/clients.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py similarity index 99% rename from jumpstarter/k8s/clients.py rename to packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py index cd3d69e37..34d80f356 100644 --- a/jumpstarter/k8s/clients.py +++ b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py @@ -4,9 +4,8 @@ from dataclasses import dataclass from typing import Literal, Optional -from kubernetes_asyncio.client.models import V1ObjectMeta, V1ObjectReference - from jumpstarter.config import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers +from kubernetes_asyncio.client.models import V1ObjectMeta, V1ObjectReference from .util import AbstractAsyncCustomObjectApi diff --git a/jumpstarter/k8s/exporters.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py similarity index 99% rename from jumpstarter/k8s/exporters.py rename to packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py index 27b115e2c..ff23bb216 100644 --- a/jumpstarter/k8s/exporters.py +++ b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py @@ -3,9 +3,8 @@ from dataclasses import dataclass from typing import Literal -from kubernetes_asyncio.client.models import V1ObjectMeta, V1ObjectReference - from jumpstarter.config import ExporterConfigV1Alpha1 +from kubernetes_asyncio.client.models import V1ObjectMeta, V1ObjectReference from .util import AbstractAsyncCustomObjectApi diff --git a/jumpstarter/k8s/install.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/install.py similarity index 100% rename from jumpstarter/k8s/install.py rename to packages/jumpstarter_kubernetes/jumpstarter_kubernetes/install.py diff --git a/jumpstarter/k8s/leases.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/leases.py similarity index 100% rename from jumpstarter/k8s/leases.py rename to packages/jumpstarter_kubernetes/jumpstarter_kubernetes/leases.py diff --git a/jumpstarter/k8s/util/__init__.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/util/__init__.py similarity index 100% rename from jumpstarter/k8s/util/__init__.py rename to packages/jumpstarter_kubernetes/jumpstarter_kubernetes/util/__init__.py diff --git a/jumpstarter/k8s/util/async_custom_object_api.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/util/async_custom_object_api.py similarity index 100% rename from jumpstarter/k8s/util/async_custom_object_api.py rename to packages/jumpstarter_kubernetes/jumpstarter_kubernetes/util/async_custom_object_api.py diff --git a/packages/jumpstarter_kubernetes/pyproject.toml b/packages/jumpstarter_kubernetes/pyproject.toml new file mode 100644 index 000000000..fd1d4045e --- /dev/null +++ b/packages/jumpstarter_kubernetes/pyproject.toml @@ -0,0 +1,35 @@ +[project] +name = "jumpstarter-kubernetes" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "kubernetes>=31.0.0", + "kubernetes-asyncio>=31.1.0", +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "pytest-cov>=5.0.0", +] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/jumpstarter/testing/__init__.py b/packages/jumpstarter_protocol/README.md similarity index 100% rename from jumpstarter/testing/__init__.py rename to packages/jumpstarter_protocol/README.md diff --git a/packages/jumpstarter_protocol/jumpstarter_protocol/__init__.py b/packages/jumpstarter_protocol/jumpstarter_protocol/__init__.py new file mode 100644 index 000000000..f94433757 --- /dev/null +++ b/packages/jumpstarter_protocol/jumpstarter_protocol/__init__.py @@ -0,0 +1,17 @@ +from .jumpstarter.v1 import ( + jumpstarter_pb2, + jumpstarter_pb2_grpc, + kubernetes_pb2, + kubernetes_pb2_grpc, + router_pb2, + router_pb2_grpc, +) + +__all__ = [ + "jumpstarter_pb2", + "jumpstarter_pb2_grpc", + "kubernetes_pb2", + "kubernetes_pb2_grpc", + "router_pb2", + "router_pb2_grpc" +] diff --git a/jumpstarter/v1/jumpstarter_pb2.py b/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py similarity index 99% rename from jumpstarter/v1/jumpstarter_pb2.py rename to packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py index 156eb2840..d8b4bcf55 100644 --- a/jumpstarter/v1/jumpstarter_pb2.py +++ b/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: jumpstarter/v1/jumpstarter.proto -# Protobuf Python Version: 5.28.2 +# Protobuf Python Version: 5.29.3 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -12,8 +12,8 @@ _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, 5, - 28, - 2, + 29, + 3, '', 'jumpstarter/v1/jumpstarter.proto' ) @@ -26,7 +26,7 @@ from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -from jumpstarter.v1 import kubernetes_pb2 as jumpstarter_dot_v1_dot_kubernetes__pb2 +from . import kubernetes_pb2 as jumpstarter_dot_v1_dot_kubernetes__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n jumpstarter/v1/jumpstarter.proto\x12\x0ejumpstarter.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1fjumpstarter/v1/kubernetes.proto\"\xd1\x01\n\x0fRegisterRequest\x12\x43\n\x06labels\x18\x01 \x03(\x0b\x32+.jumpstarter.v1.RegisterRequest.LabelsEntryR\x06labels\x12>\n\x07reports\x18\x02 \x03(\x0b\x32$.jumpstarter.v1.DriverInstanceReportR\x07reports\x1a\x39\n\x0bLabelsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xe5\x01\n\x14\x44riverInstanceReport\x12\x12\n\x04uuid\x18\x01 \x01(\tR\x04uuid\x12$\n\x0bparent_uuid\x18\x02 \x01(\tH\x00R\nparentUuid\x88\x01\x01\x12H\n\x06labels\x18\x03 \x03(\x0b\x32\x30.jumpstarter.v1.DriverInstanceReport.LabelsEntryR\x06labels\x1a\x39\n\x0bLabelsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\x0e\n\x0c_parent_uuid\"&\n\x10RegisterResponse\x12\x12\n\x04uuid\x18\x01 \x01(\tR\x04uuid\"+\n\x11UnregisterRequest\x12\x16\n\x06reason\x18\x02 \x01(\tR\x06reason\"\x14\n\x12UnregisterResponse\".\n\rListenRequest\x12\x1d\n\nlease_name\x18\x01 \x01(\tR\tleaseName\"\\\n\x0eListenResponse\x12\'\n\x0frouter_endpoint\x18\x01 \x01(\tR\x0erouterEndpoint\x12!\n\x0crouter_token\x18\x02 \x01(\tR\x0brouterToken\"\x0f\n\rStatusRequest\"\x91\x01\n\x0eStatusResponse\x12\x16\n\x06leased\x18\x01 \x01(\x08R\x06leased\x12\"\n\nlease_name\x18\x02 \x01(\tH\x00R\tleaseName\x88\x01\x01\x12$\n\x0b\x63lient_name\x18\x03 \x01(\tH\x01R\nclientName\x88\x01\x01\x42\r\n\x0b_lease_nameB\x0e\n\x0c_client_name\",\n\x0b\x44ialRequest\x12\x1d\n\nlease_name\x18\x01 \x01(\tR\tleaseName\"Z\n\x0c\x44ialResponse\x12\'\n\x0frouter_endpoint\x18\x01 \x01(\tR\x0erouterEndpoint\x12!\n\x0crouter_token\x18\x02 \x01(\tR\x0brouterToken\"\xa1\x01\n\x12\x41uditStreamRequest\x12#\n\rexporter_uuid\x18\x01 \x01(\tR\x0c\x65xporterUuid\x12\x30\n\x14\x64river_instance_uuid\x18\x02 \x01(\tR\x12\x64riverInstanceUuid\x12\x1a\n\x08severity\x18\x03 \x01(\tR\x08severity\x12\x18\n\x07message\x18\x04 \x01(\tR\x07message\"\xe9\x01\n\x11GetReportResponse\x12\x12\n\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x45\n\x06labels\x18\x02 \x03(\x0b\x32-.jumpstarter.v1.GetReportResponse.LabelsEntryR\x06labels\x12>\n\x07reports\x18\x03 \x03(\x0b\x32$.jumpstarter.v1.DriverInstanceReportR\x07reports\x1a\x39\n\x0bLabelsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"k\n\x11\x44riverCallRequest\x12\x12\n\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x16\n\x06method\x18\x02 \x01(\tR\x06method\x12*\n\x04\x61rgs\x18\x03 \x03(\x0b\x32\x16.google.protobuf.ValueR\x04\x61rgs\"X\n\x12\x44riverCallResponse\x12\x12\n\x04uuid\x18\x01 \x01(\tR\x04uuid\x12.\n\x06result\x18\x02 \x01(\x0b\x32\x16.google.protobuf.ValueR\x06result\"t\n\x1aStreamingDriverCallRequest\x12\x12\n\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x16\n\x06method\x18\x02 \x01(\tR\x06method\x12*\n\x04\x61rgs\x18\x03 \x03(\x0b\x32\x16.google.protobuf.ValueR\x04\x61rgs\"a\n\x1bStreamingDriverCallResponse\x12\x12\n\x04uuid\x18\x01 \x01(\tR\x04uuid\x12.\n\x06result\x18\x02 \x01(\x0b\x32\x16.google.protobuf.ValueR\x06result\"]\n\x11LogStreamResponse\x12\x12\n\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x1a\n\x08severity\x18\x02 \x01(\tR\x08severity\x12\x18\n\x07message\x18\x03 \x01(\tR\x07message\"\x0e\n\x0cResetRequest\"\x0f\n\rResetResponse\"\x9b\x01\n\x14ListExportersRequest\x12H\n\x06labels\x18\x01 \x03(\x0b\x32\x30.jumpstarter.v1.ListExportersRequest.LabelsEntryR\x06labels\x1a\x39\n\x0bLabelsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"X\n\x15ListExportersResponse\x12?\n\texporters\x18\x01 \x03(\x0b\x32!.jumpstarter.v1.GetReportResponseR\texporters\"(\n\x12GetExporterRequest\x12\x12\n\x04uuid\x18\x01 \x01(\tR\x04uuid\"T\n\x13GetExporterResponse\x12=\n\x08\x65xporter\x18\x01 \x01(\x0b\x32!.jumpstarter.v1.GetReportResponseR\x08\x65xporter\"%\n\x0fGetLeaseRequest\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\"\x93\x03\n\x10GetLeaseResponse\x12\x35\n\x08\x64uration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationR\x08\x64uration\x12\x39\n\x08selector\x18\x02 \x01(\x0b\x32\x1d.jumpstarter.v1.LabelSelectorR\x08selector\x12>\n\nbegin_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00R\tbeginTime\x88\x01\x01\x12:\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01R\x07\x65ndTime\x88\x01\x01\x12(\n\rexporter_uuid\x18\x05 \x01(\tH\x02R\x0c\x65xporterUuid\x88\x01\x01\x12\x39\n\nconditions\x18\x06 \x03(\x0b\x32\x19.jumpstarter.v1.ConditionR\nconditionsB\r\n\x0b_begin_timeB\x0b\n\t_end_timeB\x10\n\x0e_exporter_uuid\"\x87\x01\n\x13RequestLeaseRequest\x12\x35\n\x08\x64uration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationR\x08\x64uration\x12\x39\n\x08selector\x18\x02 \x01(\x0b\x32\x1d.jumpstarter.v1.LabelSelectorR\x08selector\"*\n\x14RequestLeaseResponse\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\")\n\x13ReleaseLeaseRequest\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\"\x16\n\x14ReleaseLeaseResponse\"\x13\n\x11ListLeasesRequest\"*\n\x12ListLeasesResponse\x12\x14\n\x05names\x18\x01 \x03(\tR\x05names2\xed\x07\n\x11\x43ontrollerService\x12M\n\x08Register\x12\x1f.jumpstarter.v1.RegisterRequest\x1a .jumpstarter.v1.RegisterResponse\x12S\n\nUnregister\x12!.jumpstarter.v1.UnregisterRequest\x1a\".jumpstarter.v1.UnregisterResponse\x12I\n\x06Listen\x12\x1d.jumpstarter.v1.ListenRequest\x1a\x1e.jumpstarter.v1.ListenResponse0\x01\x12I\n\x06Status\x12\x1d.jumpstarter.v1.StatusRequest\x1a\x1e.jumpstarter.v1.StatusResponse0\x01\x12\x41\n\x04\x44ial\x12\x1b.jumpstarter.v1.DialRequest\x1a\x1c.jumpstarter.v1.DialResponse\x12K\n\x0b\x41uditStream\x12\".jumpstarter.v1.AuditStreamRequest\x1a\x16.google.protobuf.Empty(\x01\x12\\\n\rListExporters\x12$.jumpstarter.v1.ListExportersRequest\x1a%.jumpstarter.v1.ListExportersResponse\x12V\n\x0bGetExporter\x12\".jumpstarter.v1.GetExporterRequest\x1a#.jumpstarter.v1.GetExporterResponse\x12M\n\x08GetLease\x12\x1f.jumpstarter.v1.GetLeaseRequest\x1a .jumpstarter.v1.GetLeaseResponse\x12Y\n\x0cRequestLease\x12#.jumpstarter.v1.RequestLeaseRequest\x1a$.jumpstarter.v1.RequestLeaseResponse\x12Y\n\x0cReleaseLease\x12#.jumpstarter.v1.ReleaseLeaseRequest\x1a$.jumpstarter.v1.ReleaseLeaseResponse\x12S\n\nListLeases\x12!.jumpstarter.v1.ListLeasesRequest\x1a\".jumpstarter.v1.ListLeasesResponse2\xb0\x03\n\x0f\x45xporterService\x12\x46\n\tGetReport\x12\x16.google.protobuf.Empty\x1a!.jumpstarter.v1.GetReportResponse\x12S\n\nDriverCall\x12!.jumpstarter.v1.DriverCallRequest\x1a\".jumpstarter.v1.DriverCallResponse\x12p\n\x13StreamingDriverCall\x12*.jumpstarter.v1.StreamingDriverCallRequest\x1a+.jumpstarter.v1.StreamingDriverCallResponse0\x01\x12H\n\tLogStream\x12\x16.google.protobuf.Empty\x1a!.jumpstarter.v1.LogStreamResponse0\x01\x12\x44\n\x05Reset\x12\x1c.jumpstarter.v1.ResetRequest\x1a\x1d.jumpstarter.v1.ResetResponseB\x7f\n\x12\x63om.jumpstarter.v1B\x10JumpstarterProtoP\x01\xa2\x02\x03JXX\xaa\x02\x0eJumpstarter.V1\xca\x02\x0eJumpstarter\\V1\xe2\x02\x1aJumpstarter\\V1\\GPBMetadata\xea\x02\x0fJumpstarter::V1b\x06proto3') diff --git a/jumpstarter/v1/jumpstarter_pb2_grpc.py b/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py similarity index 99% rename from jumpstarter/v1/jumpstarter_pb2_grpc.py rename to packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py index ac199a432..227d63404 100644 --- a/jumpstarter/v1/jumpstarter_pb2_grpc.py +++ b/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py @@ -3,7 +3,7 @@ import grpc from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 -from jumpstarter.v1 import jumpstarter_pb2 as jumpstarter_dot_v1_dot_jumpstarter__pb2 +from . import jumpstarter_pb2 as jumpstarter_dot_v1_dot_jumpstarter__pb2 class ControllerServiceStub(object): diff --git a/jumpstarter/v1/kubernetes_pb2.py b/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.py similarity index 98% rename from jumpstarter/v1/kubernetes_pb2.py rename to packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.py index 5f4e60dcc..bfeeae908 100644 --- a/jumpstarter/v1/kubernetes_pb2.py +++ b/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: jumpstarter/v1/kubernetes.proto -# Protobuf Python Version: 5.28.2 +# Protobuf Python Version: 5.29.3 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -12,8 +12,8 @@ _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, 5, - 28, - 2, + 29, + 3, '', 'jumpstarter/v1/kubernetes.proto' ) diff --git a/jumpstarter/v1/kubernetes_pb2_grpc.py b/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2_grpc.py similarity index 100% rename from jumpstarter/v1/kubernetes_pb2_grpc.py rename to packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2_grpc.py diff --git a/jumpstarter/v1/router_pb2.py b/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.py similarity index 98% rename from jumpstarter/v1/router_pb2.py rename to packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.py index 66b8ae110..eff53189e 100644 --- a/jumpstarter/v1/router_pb2.py +++ b/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: jumpstarter/v1/router.proto -# Protobuf Python Version: 5.28.2 +# Protobuf Python Version: 5.29.3 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -12,8 +12,8 @@ _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, 5, - 28, - 2, + 29, + 3, '', 'jumpstarter/v1/router.proto' ) diff --git a/jumpstarter/v1/router_pb2_grpc.py b/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py similarity index 97% rename from jumpstarter/v1/router_pb2_grpc.py rename to packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py index 8f3995c0d..81393a572 100644 --- a/jumpstarter/v1/router_pb2_grpc.py +++ b/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from jumpstarter.v1 import router_pb2 as jumpstarter_dot_v1_dot_router__pb2 +from . import router_pb2 as jumpstarter_dot_v1_dot_router__pb2 class RouterServiceStub(object): diff --git a/packages/jumpstarter_protocol/pyproject.toml b/packages/jumpstarter_protocol/pyproject.toml new file mode 100644 index 000000000..45c7e562b --- /dev/null +++ b/packages/jumpstarter_protocol/pyproject.toml @@ -0,0 +1,37 @@ +[project] +name = "jumpstarter-protocol" +dynamic = ["version", "urls"] +description = "" +authors = [ + { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, +] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "grpcio>=1.66.1", + "protobuf>=5.29.3", +] + +[dependency-groups] +dev = [ + "pytest>=8.3.2", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "pytest-cov>=5.0.0", +] + +[tool.hatch.build.targets.wheel] +packages = ["jumpstarter_protocol"] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../'} + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/packages/jumpstarter_testing/README.md b/packages/jumpstarter_testing/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/jumpstarter_testing/conftest.py b/packages/jumpstarter_testing/conftest.py new file mode 100644 index 000000000..9fd31378a --- /dev/null +++ b/packages/jumpstarter_testing/conftest.py @@ -0,0 +1,7 @@ +import pytest + +pytest_plugins = ["pytester"] + +@pytest.fixture +def anyio_backend(): + return "asyncio" diff --git a/packages/jumpstarter_testing/jumpstarter_testing/__init__.py b/packages/jumpstarter_testing/jumpstarter_testing/__init__.py new file mode 100644 index 000000000..8975fd655 --- /dev/null +++ b/packages/jumpstarter_testing/jumpstarter_testing/__init__.py @@ -0,0 +1,3 @@ +from .pytest import JumpstarterTest + +__all__ = ["JumpstarterTest"] diff --git a/jumpstarter/testing/pytest.py b/packages/jumpstarter_testing/jumpstarter_testing/pytest.py similarity index 96% rename from jumpstarter/testing/pytest.py rename to packages/jumpstarter_testing/jumpstarter_testing/pytest.py index ebe71f911..12315c388 100644 --- a/jumpstarter/testing/pytest.py +++ b/packages/jumpstarter_testing/jumpstarter_testing/pytest.py @@ -3,7 +3,6 @@ from typing import ClassVar import pytest - from jumpstarter.common import MetadataFilter from jumpstarter.common.utils import env from jumpstarter.config.client import ClientConfigV1Alpha1 @@ -27,7 +26,7 @@ class JumpstarterTest: import pytest import logging - from jumpstarter.testing.pytest import JumpstarterTest + from jumpstarter_testing.pytest import JumpstarterTest log = logging.getLogger(__name__) diff --git a/jumpstarter/testing/pytest_test.py b/packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py similarity index 76% rename from jumpstarter/testing/pytest_test.py rename to packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py index 0cee1b2b7..60be99a0d 100644 --- a/jumpstarter/testing/pytest_test.py +++ b/packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py @@ -1,12 +1,13 @@ from jumpstarter.config.env import JMP_DRIVERS_ALLOW, JUMPSTARTER_HOST -from jumpstarter.drivers.power.driver import MockPower from jumpstarter.exporter import Session +from jumpstarter_driver_power.driver import MockPower +from pytest import Pytester -def test_env(pytester, monkeypatch): +def test_env(pytester: Pytester, monkeypatch): pytester.makepyfile( """ - from jumpstarter.testing.pytest import JumpstarterTest + from jumpstarter_testing import JumpstarterTest class TestSample(JumpstarterTest): def test_simple(self, client): diff --git a/packages/jumpstarter_testing/pyproject.toml b/packages/jumpstarter_testing/pyproject.toml new file mode 100644 index 000000000..a77b5cb30 --- /dev/null +++ b/packages/jumpstarter_testing/pyproject.toml @@ -0,0 +1,30 @@ +[project] +name = "jumpstarter-testing" +dynamic = ["version", "urls"] +description = "" +authors = [{ name = "Kirk Brauer", email = "kbrauer@hatci.com" }] +readme = "README.md" +license = { text = "Apache-2.0" } +requires-python = ">=3.11" +dependencies = [ + "jumpstarter", + "pytest>=8.3.2", + "pytest-anyio>=0.0.0", + "pytest-asyncio>=0.0.0", + "pytest-cov>=5.0.0" +] + +[dependency-groups] +dev = ["jumpstarter-driver-power"] + +[tool.hatch.metadata.hooks.vcs.urls] +Homepage = "https://jumpstarter.dev" +source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" + +[tool.hatch.version] +source = "vcs" +raw-options = { 'root' = '../../' } + +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" diff --git a/pyproject.toml b/pyproject.toml index 6eae78956..31c6be0a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,30 +1,29 @@ -[project] -name = "jumpstarter" -dynamic = ["version", "urls"] -description = "" -authors = [ - { name = "Miguel Angel Ajo Pelayo", email = "majopela@redhat.com" }, - { name = "Nick Cao", email = "ncao@redhat.com" }, - { name = "Kirk Brauer", email = "kbrauer@hatci.com" }, -] -readme = "README.md" -license = { text = "Apache-2.0" } -requires-python = ">=3.11" -dependencies = [ - "pexpect>=4.9.0", - "httpx>=0.27.0", - "pyyaml>=6.0.2", - "anyio>=4.4.0,!=4.6.2", - "aiohttp>=3.10.5", - "tqdm>=4.66.5", - "opendal>=0.45.8", - "pydantic>=2.8.2", - "pyserial>=3.5", - "wsproto>=1.2.0", - "fabric>=3.2.2", - "grpcio>=1.66.1", - "protobuf>=5.28.0" -] +[tool.uv.workspace] +members = ["packages/*", "examples/*"] + +[tool.uv.sources] +jumpstarter = { workspace = true } +jumpstarter-cli = { workspace = true } +jumpstarter-cli-admin = { workspace = true } +jumpstarter-cli-client = { workspace = true } +jumpstarter-cli-common = { workspace = true } +jumpstarter-cli-exporter = { workspace = true } +jumpstarter-driver-can = { workspace = true } +jumpstarter-driver-composite = { workspace = true } +jumpstarter-driver-dutlink = { workspace = true } +jumpstarter-driver-http = { workspace = true } +jumpstarter-driver-raspberrypi = { workspace = true } +jumpstarter-driver-network = { workspace = true } +jumpstarter-driver-opendal = { workspace = true } +jumpstarter-driver-power = { workspace = true } +jumpstarter-driver-pyserial = { workspace = true } +jumpstarter-driver-sdwire = { workspace = true } +jumpstarter-driver-tftp = { workspace = true } +jumpstarter-driver-ustreamer = { workspace = true } +jumpstarter-imagehash = { workspace = true } +jumpstarter-kubernetes = { workspace = true } +jumpstarter-protocol = { workspace = true } +jumpstarter-testing = { workspace = true } [dependency-groups] docs = [ @@ -38,34 +37,12 @@ docs = [ "sphinx-substitution-extensions>=2024.10.17", ] dev = [ - "pytest>=8.3.2", - "pytest-anyio>=0.0.0", - "pytest-asyncio>=0.0.0", - "pytest-cov>=5.0.0", "ruff>=0.6.1", "typos>=1.23.6", "pre-commit>=3.8.0", - "cryptography>=43.0.1", - "websocket-client>=1.8.0", "esbonio>=0.16.5", ] -[tool.hatch.version] -source = "vcs" - -[tool.hatch.build.targets.wheel] -packages = ["jumpstarter"] - -[tool.hatch.metadata.hooks.vcs.urls] -Homepage = "https://jumpstarter.dev" -source_archive = "https://github.com/jumpstarter-dev/repo/archive/{commit_hash}.zip" - -[tool.uv.workspace] -members = ["contrib/drivers/*", "contrib/libs/*", "examples/*", "cli/*"] - -[tool.uv.sources] -jumpstarter = { workspace = true } - [tool.ruff] exclude = ["jumpstarter/v1"] line-length = 120 @@ -82,7 +59,3 @@ omit = ["conftest.py", "test_*.py", "*_test.py", "*_pb2.py", "*_pb2_grpc.py"] [tool.pytest.ini_options] addopts = "--capture=no --verbose --cov --cov-report=html --cov-report=xml --cov-append" - -[build-system] -requires = ["hatchling", "hatch-vcs"] -build-backend = "hatchling.build" diff --git a/tests/test_client_config.py b/tests/test_client_config.py index fbdc1e9ae..325873477 100644 --- a/tests/test_client_config.py +++ b/tests/test_client_config.py @@ -5,13 +5,12 @@ import pytest import yaml -from pydantic import ValidationError - from jumpstarter.config import ( ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, ) from jumpstarter.config.env import JMP_DRIVERS_ALLOW, JMP_ENDPOINT, JMP_TOKEN +from pydantic import ValidationError def test_client_ensure_exists_makes_dir(monkeypatch: pytest.MonkeyPatch): diff --git a/tests/test_listener.py b/tests/test_listener.py index 1100db758..565cceffd 100644 --- a/tests/test_listener.py +++ b/tests/test_listener.py @@ -7,13 +7,12 @@ import pytest from anyio import create_task_group from anyio.from_thread import start_blocking_portal - from jumpstarter.client import Lease from jumpstarter.common import MetadataFilter from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials from jumpstarter.common.streams import connect_router_stream -from jumpstarter.drivers.power.driver import MockPower from jumpstarter.exporter import Exporter, Session +from jumpstarter_driver_power.driver import MockPower pytestmark = pytest.mark.anyio diff --git a/uv.lock b/uv.lock index 7fc084a77..f05e74381 100644 --- a/uv.lock +++ b/uv.lock @@ -8,21 +8,43 @@ resolution-markers = [ [manifest] members = [ "jumpstarter", - "jumpstarter-admin-cli", "jumpstarter-cli", + "jumpstarter-cli-admin", + "jumpstarter-cli-client", "jumpstarter-cli-common", - "jumpstarter-client-cli", + "jumpstarter-cli-exporter", "jumpstarter-driver-can", + "jumpstarter-driver-composite", "jumpstarter-driver-dutlink", "jumpstarter-driver-http", + "jumpstarter-driver-network", + "jumpstarter-driver-opendal", + "jumpstarter-driver-power", + "jumpstarter-driver-pyserial", "jumpstarter-driver-raspberrypi", "jumpstarter-driver-sdwire", "jumpstarter-driver-tftp", "jumpstarter-driver-ustreamer", "jumpstarter-example-automotive", "jumpstarter-example-soc-pytest", - "jumpstarter-exporter-cli", "jumpstarter-imagehash", + "jumpstarter-kubernetes", + "jumpstarter-protocol", + "jumpstarter-testing", +] +requirements = [ + { name = "esbonio", specifier = ">=0.16.4" }, + { name = "esbonio", specifier = ">=0.16.5" }, + { name = "furo", specifier = ">=2024.8.6" }, + { name = "myst-parser", specifier = ">=4.0.0" }, + { name = "pre-commit", specifier = ">=3.8.0" }, + { name = "ruff", specifier = ">=0.6.1" }, + { name = "sphinx", specifier = "<8.1.0" }, + { name = "sphinx-autobuild", specifier = ">=2024.4.16" }, + { name = "sphinx-click", specifier = ">=6.0.0" }, + { name = "sphinx-substitution-extensions", specifier = ">=2024.10.17" }, + { name = "sphinxcontrib-mermaid", specifier = ">=0.9.2" }, + { name = "typos", specifier = ">=1.23.6" }, ] [[package]] @@ -637,35 +659,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, ] -[[package]] -name = "httpcore" -version = "1.0.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "h11" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b6/44/ed0fa6a17845fb033bd885c03e842f08c1b9406c86a2e60ac1ae1b9206a6/httpcore-1.0.6.tar.gz", hash = "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f", size = 85180 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/06/89/b161908e2f51be56568184aeb4a880fd287178d176fd1c860d2217f41106/httpcore-1.0.6-py3-none-any.whl", hash = "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f", size = 78011 }, -] - -[[package]] -name = "httpx" -version = "0.27.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "certifi" }, - { name = "httpcore" }, - { name = "idna" }, - { name = "sniffio" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/78/82/08f8c936781f67d9e6b9eeb8a0c8b4e406136ea4c3d1f89a5db71d42e0e6/httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2", size = 144189 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/56/95/9377bcb415797e44274b51d46e3249eba641711cf3348050f76ee7b15ffc/httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0", size = 76395 }, -] - [[package]] name = "identify" version = "2.6.1" @@ -740,99 +733,59 @@ wheels = [ [[package]] name = "jumpstarter" -version = "0.5.1.dev93+gb7ef843.d20250115" -source = { editable = "." } +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter" } dependencies = [ { name = "aiohttp" }, { name = "anyio" }, - { name = "fabric" }, - { name = "grpcio" }, - { name = "httpx" }, - { name = "opendal" }, - { name = "pexpect" }, - { name = "protobuf" }, + { name = "jumpstarter-protocol" }, { name = "pydantic" }, - { name = "pyserial" }, { name = "pyyaml" }, { name = "tqdm" }, - { name = "wsproto" }, ] [package.dev-dependencies] dev = [ { name = "cryptography" }, - { name = "esbonio" }, - { name = "pre-commit" }, + { name = "jumpstarter-driver-composite" }, + { name = "jumpstarter-driver-network" }, + { name = "jumpstarter-driver-power" }, { name = "pytest" }, { name = "pytest-anyio" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, - { name = "ruff" }, - { name = "typos" }, - { name = "websocket-client" }, -] -docs = [ - { name = "esbonio" }, - { name = "furo" }, - { name = "myst-parser" }, - { name = "sphinx" }, - { name = "sphinx-autobuild" }, - { name = "sphinx-click" }, - { name = "sphinx-substitution-extensions" }, - { name = "sphinxcontrib-mermaid" }, ] [package.metadata] requires-dist = [ { name = "aiohttp", specifier = ">=3.10.5" }, { name = "anyio", specifier = ">=4.4.0,!=4.6.2" }, - { name = "fabric", specifier = ">=3.2.2" }, - { name = "grpcio", specifier = ">=1.66.1" }, - { name = "httpx", specifier = ">=0.27.0" }, - { name = "opendal", specifier = ">=0.45.8" }, - { name = "pexpect", specifier = ">=4.9.0" }, - { name = "protobuf", specifier = ">=5.28.0" }, + { name = "jumpstarter-protocol", editable = "packages/jumpstarter_protocol" }, { name = "pydantic", specifier = ">=2.8.2" }, - { name = "pyserial", specifier = ">=3.5" }, { name = "pyyaml", specifier = ">=6.0.2" }, { name = "tqdm", specifier = ">=4.66.5" }, - { name = "wsproto", specifier = ">=1.2.0" }, ] [package.metadata.requires-dev] dev = [ - { name = "cryptography", specifier = ">=43.0.1" }, - { name = "esbonio", specifier = ">=0.16.5" }, - { name = "pre-commit", specifier = ">=3.8.0" }, + { name = "cryptography", specifier = ">=43.0.3" }, + { name = "jumpstarter-driver-composite", editable = "packages/jumpstarter_driver_composite" }, + { name = "jumpstarter-driver-network", editable = "packages/jumpstarter_driver_network" }, + { name = "jumpstarter-driver-power", editable = "packages/jumpstarter_driver_power" }, { name = "pytest", specifier = ">=8.3.2" }, { name = "pytest-anyio", specifier = ">=0.0.0" }, { name = "pytest-asyncio", specifier = ">=0.0.0" }, - { name = "pytest-cov", specifier = ">=5.0.0" }, - { name = "ruff", specifier = ">=0.6.1" }, - { name = "typos", specifier = ">=1.23.6" }, - { name = "websocket-client", specifier = ">=1.8.0" }, -] -docs = [ - { name = "esbonio", specifier = ">=0.16.4" }, - { name = "furo", specifier = ">=2024.8.6" }, - { name = "myst-parser", specifier = ">=4.0.0" }, - { name = "sphinx", specifier = "<8.1.0" }, - { name = "sphinx-autobuild", specifier = ">=2024.4.16" }, - { name = "sphinx-click", specifier = ">=6.0.0" }, - { name = "sphinx-substitution-extensions", specifier = ">=2024.10.17" }, - { name = "sphinxcontrib-mermaid", specifier = ">=0.9.2" }, + { name = "pytest-cov", specifier = ">=6.0.0" }, ] [[package]] -name = "jumpstarter-admin-cli" -version = "0.5.1.dev93+gb7ef843.d20250115" -source = { editable = "cli/admin" } +name = "jumpstarter-cli" +version = "0.5.1.dev94+g3eaebda.d20250118" +source = { editable = "packages/jumpstarter_cli" } dependencies = [ - { name = "asyncclick" }, - { name = "jumpstarter" }, - { name = "jumpstarter-cli-common" }, - { name = "kubernetes" }, - { name = "kubernetes-asyncio" }, + { name = "jumpstarter-cli-admin" }, + { name = "jumpstarter-cli-client" }, + { name = "jumpstarter-cli-exporter" }, ] [package.dev-dependencies] @@ -845,11 +798,9 @@ dev = [ [package.metadata] requires-dist = [ - { name = "asyncclick", specifier = ">=8.1.7.2" }, - { name = "jumpstarter", editable = "." }, - { name = "jumpstarter-cli-common", editable = "cli/common" }, - { name = "kubernetes", specifier = ">=31.0.0" }, - { name = "kubernetes-asyncio", specifier = ">=31.1.0" }, + { name = "jumpstarter-cli-admin", editable = "packages/jumpstarter_cli_admin" }, + { name = "jumpstarter-cli-client", editable = "packages/jumpstarter_cli_client" }, + { name = "jumpstarter-cli-exporter", editable = "packages/jumpstarter_cli_exporter" }, ] [package.metadata.requires-dev] @@ -861,15 +812,12 @@ dev = [ ] [[package]] -name = "jumpstarter-cli" -version = "0.5.1.dev93+gb7ef843.d20250115" -source = { editable = "cli/jmp" } +name = "jumpstarter-cli-admin" +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter_cli_admin" } dependencies = [ - { name = "jumpstarter" }, - { name = "jumpstarter-admin-cli" }, { name = "jumpstarter-cli-common" }, - { name = "jumpstarter-client-cli" }, - { name = "jumpstarter-exporter-cli" }, + { name = "jumpstarter-kubernetes" }, ] [package.dev-dependencies] @@ -882,11 +830,8 @@ dev = [ [package.metadata] requires-dist = [ - { name = "jumpstarter", editable = "." }, - { name = "jumpstarter-admin-cli", editable = "cli/admin" }, - { name = "jumpstarter-cli-common", editable = "cli/common" }, - { name = "jumpstarter-client-cli", editable = "cli/client" }, - { name = "jumpstarter-exporter-cli", editable = "cli/exporter" }, + { name = "jumpstarter-cli-common", editable = "packages/jumpstarter_cli_common" }, + { name = "jumpstarter-kubernetes", editable = "packages/jumpstarter_kubernetes" }, ] [package.metadata.requires-dev] @@ -897,10 +842,37 @@ dev = [ { name = "pytest-cov", specifier = ">=5.0.0" }, ] +[[package]] +name = "jumpstarter-cli-client" +version = "0.5.1.dev94+g3eaebda.d20250117" +source = { editable = "packages/jumpstarter_cli_client" } +dependencies = [ + { name = "jumpstarter-cli-common" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-anyio" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [{ name = "jumpstarter-cli-common", editable = "packages/jumpstarter_cli_common" }] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-anyio", specifier = ">=0.0.0" }, + { name = "pytest-asyncio", specifier = ">=0.0.0" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + [[package]] name = "jumpstarter-cli-common" -version = "0.5.1.dev93+gb7ef843.d20250115" -source = { editable = "cli/common" } +version = "0.5.1.dev94+g3eaebda.d20250117" +source = { editable = "packages/jumpstarter_cli_common" } dependencies = [ { name = "asyncclick" }, { name = "jumpstarter" }, @@ -917,7 +889,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "asyncclick", specifier = ">=8.1.7.2" }, - { name = "jumpstarter", editable = "." }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, ] [package.metadata.requires-dev] @@ -929,12 +901,11 @@ dev = [ ] [[package]] -name = "jumpstarter-client-cli" -version = "0.5.1.dev93+gb7ef843.d20250115" -source = { editable = "cli/client" } +name = "jumpstarter-cli-exporter" +version = "0.5.1.dev94+g3eaebda.d20250117" +source = { editable = "packages/jumpstarter_cli_exporter" } dependencies = [ { name = "asyncclick" }, - { name = "jumpstarter" }, { name = "jumpstarter-cli-common" }, ] @@ -949,8 +920,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "asyncclick", specifier = ">=8.1.7.2" }, - { name = "jumpstarter", editable = "." }, - { name = "jumpstarter-cli-common", editable = "cli/common" }, + { name = "jumpstarter-cli-common", editable = "packages/jumpstarter_cli_common" }, ] [package.metadata.requires-dev] @@ -963,8 +933,8 @@ dev = [ [[package]] name = "jumpstarter-driver-can" -version = "0.5.1.dev16+gc1f555c.d20241209" -source = { editable = "contrib/drivers/can" } +version = "0.5.1.dev94+g3eaebda.d20250117" +source = { editable = "packages/jumpstarter_driver_can" } dependencies = [ { name = "can-isotp" }, { name = "jumpstarter" }, @@ -980,7 +950,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "can-isotp", specifier = ">=2.0.6" }, - { name = "jumpstarter", editable = "." }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, { name = "python-can", specifier = ">=4.4.2" }, ] @@ -990,12 +960,47 @@ dev = [ { name = "pytest-cov", specifier = ">=5.0.0" }, ] +[[package]] +name = "jumpstarter-driver-composite" +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter_driver_composite" } +dependencies = [ + { name = "asyncclick" }, + { name = "jumpstarter" }, +] + +[package.dev-dependencies] +dev = [ + { name = "jumpstarter-driver-power" }, + { name = "pytest" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "asyncclick", specifier = ">=8.1.7.2" }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "jumpstarter-driver-power", editable = "packages/jumpstarter_driver_power" }, + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + [[package]] name = "jumpstarter-driver-dutlink" -version = "0.5.1.dev16+gc1f555c.d20241209" -source = { editable = "contrib/drivers/dutlink" } +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter_driver_dutlink" } dependencies = [ + { name = "asyncclick" }, { name = "jumpstarter" }, + { name = "jumpstarter-driver-composite" }, + { name = "jumpstarter-driver-network" }, + { name = "jumpstarter-driver-opendal" }, + { name = "jumpstarter-driver-power" }, + { name = "jumpstarter-driver-pyserial" }, { name = "pyudev" }, { name = "pyusb" }, ] @@ -1008,7 +1013,13 @@ dev = [ [package.metadata] requires-dist = [ - { name = "jumpstarter", editable = "." }, + { name = "asyncclick", specifier = ">=8.1.7.2" }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "jumpstarter-driver-composite", editable = "packages/jumpstarter_driver_composite" }, + { name = "jumpstarter-driver-network", editable = "packages/jumpstarter_driver_network" }, + { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter_driver_opendal" }, + { name = "jumpstarter-driver-power", editable = "packages/jumpstarter_driver_power" }, + { name = "jumpstarter-driver-pyserial", editable = "packages/jumpstarter_driver_pyserial" }, { name = "pyudev", specifier = ">=0.24.3" }, { name = "pyusb", specifier = ">=1.2.1" }, ] @@ -1022,10 +1033,11 @@ dev = [ [[package]] name = "jumpstarter-driver-http" version = "0.1.0" -source = { editable = "contrib/drivers/http" } +source = { editable = "packages/jumpstarter_driver_http" } dependencies = [ { name = "anyio" }, { name = "jumpstarter" }, + { name = "jumpstarter-driver-opendal" }, ] [package.dev-dependencies] @@ -1039,7 +1051,8 @@ dev = [ [package.metadata] requires-dist = [ { name = "anyio", specifier = ">=4.6.2.post1" }, - { name = "jumpstarter", editable = "." }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter_driver_opendal" }, ] [package.metadata.requires-dev] @@ -1050,10 +1063,134 @@ dev = [ { name = "ruff", specifier = ">=0.7.1" }, ] +[[package]] +name = "jumpstarter-driver-network" +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter_driver_network" } +dependencies = [ + { name = "fabric" }, + { name = "jumpstarter" }, + { name = "pexpect" }, + { name = "wsproto" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "websocket-client" }, +] + +[package.metadata] +requires-dist = [ + { name = "fabric", specifier = ">=3.2.2" }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "pexpect", specifier = ">=4.9.0" }, + { name = "wsproto", specifier = ">=1.2.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, + { name = "websocket-client", specifier = ">=1.8.0" }, +] + +[[package]] +name = "jumpstarter-driver-opendal" +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter_driver_opendal" } +dependencies = [ + { name = "asyncclick" }, + { name = "jumpstarter" }, + { name = "opendal" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "asyncclick", specifier = ">=8.1.7.2" }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "opendal", specifier = ">=0.45.8" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + +[[package]] +name = "jumpstarter-driver-power" +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter_driver_power" } +dependencies = [ + { name = "asyncclick" }, + { name = "jumpstarter" }, + { name = "pyserial" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "trio" }, +] + +[package.metadata] +requires-dist = [ + { name = "asyncclick", specifier = ">=8.1.7.2" }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "pyserial", specifier = ">=3.5" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, + { name = "trio", specifier = ">=0.28.0" }, +] + +[[package]] +name = "jumpstarter-driver-pyserial" +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter_driver_pyserial" } +dependencies = [ + { name = "asyncclick" }, + { name = "jumpstarter" }, + { name = "jumpstarter-driver-network" }, + { name = "pyserial" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "asyncclick", specifier = ">=8.1.7.2" }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "jumpstarter-driver-network", editable = "packages/jumpstarter_driver_network" }, + { name = "pyserial", specifier = ">=3.5" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + [[package]] name = "jumpstarter-driver-raspberrypi" -version = "0.5.1.dev16+gc1f555c.d20241209" -source = { editable = "contrib/drivers/raspberrypi" } +version = "0.5.1.dev94+g3eaebda.d20250117" +source = { editable = "packages/jumpstarter_driver_raspberrypi" } dependencies = [ { name = "gpiozero" }, { name = "jumpstarter" }, @@ -1068,7 +1205,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "gpiozero", specifier = ">=2.0.1" }, - { name = "jumpstarter", editable = "." }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, ] [package.metadata.requires-dev] @@ -1079,10 +1216,11 @@ dev = [ [[package]] name = "jumpstarter-driver-sdwire" -version = "0.5.1.dev16+gc1f555c.d20241209" -source = { editable = "contrib/drivers/sdwire" } +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter_driver_sdwire" } dependencies = [ { name = "jumpstarter" }, + { name = "jumpstarter-driver-opendal" }, { name = "pyudev" }, { name = "pyusb" }, ] @@ -1095,7 +1233,8 @@ dev = [ [package.metadata] requires-dist = [ - { name = "jumpstarter", editable = "." }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter_driver_opendal" }, { name = "pyudev", specifier = ">=0.24.3" }, { name = "pyusb", specifier = ">=1.2.1" }, ] @@ -1109,38 +1248,44 @@ dev = [ [[package]] name = "jumpstarter-driver-tftp" version = "0.1.0" -source = { editable = "contrib/drivers/tftp" } +source = { editable = "packages/jumpstarter_driver_tftp" } dependencies = [ { name = "aiofiles" }, { name = "anyio" }, { name = "jumpstarter" }, + { name = "jumpstarter-driver-opendal" }, ] [package.dev-dependencies] dev = [ + { name = "jumpstarter-testing" }, { name = "pytest" }, + { name = "pytest-anyio" }, + { name = "pytest-asyncio" }, { name = "pytest-cov" }, - { name = "ruff" }, ] [package.metadata] requires-dist = [ { name = "aiofiles", specifier = ">=24.1.0" }, { name = "anyio", specifier = ">=4.6.2.post1" }, - { name = "jumpstarter", editable = "." }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter_driver_opendal" }, ] [package.metadata.requires-dev] dev = [ - { name = "pytest", specifier = ">=8.3.3" }, + { name = "jumpstarter-testing", editable = "packages/jumpstarter_testing" }, + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-anyio", specifier = ">=0.0.0" }, + { name = "pytest-asyncio", specifier = ">=0.0.0" }, { name = "pytest-cov", specifier = ">=6.0.0" }, - { name = "ruff", specifier = ">=0.7.1" }, ] [[package]] name = "jumpstarter-driver-ustreamer" -version = "0.5.1.dev16+gc1f555c.d20241209" -source = { editable = "contrib/drivers/ustreamer" } +version = "0.5.1.dev94+g3eaebda.d20250117" +source = { editable = "packages/jumpstarter_driver_ustreamer" } dependencies = [ { name = "jumpstarter" }, { name = "pillow" }, @@ -1154,7 +1299,7 @@ dev = [ [package.metadata] requires-dist = [ - { name = "jumpstarter", editable = "." }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, { name = "pillow", specifier = ">=10.4.0" }, ] @@ -1173,7 +1318,7 @@ dependencies = [ ] [package.metadata] -requires-dist = [{ name = "jumpstarter", editable = "." }] +requires-dist = [{ name = "jumpstarter", editable = "packages/jumpstarter" }] [[package]] name = "jumpstarter-example-soc-pytest" @@ -1188,20 +1333,47 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "jumpstarter", editable = "." }, - { name = "jumpstarter-driver-dutlink", editable = "contrib/drivers/dutlink" }, - { name = "jumpstarter-imagehash", editable = "contrib/libs/imagehash" }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "jumpstarter-driver-dutlink", editable = "packages/jumpstarter_driver_dutlink" }, + { name = "jumpstarter-imagehash", editable = "packages/jumpstarter_imagehash" }, { name = "pytest", specifier = ">=8.3.2" }, ] [[package]] -name = "jumpstarter-exporter-cli" -version = "0.5.1.dev93+gb7ef843.d20250115" -source = { editable = "cli/exporter" } +name = "jumpstarter-imagehash" +version = "0.5.1.dev94+g3eaebda.d20250117" +source = { editable = "packages/jumpstarter_imagehash" } dependencies = [ - { name = "asyncclick" }, + { name = "imagehash" }, { name = "jumpstarter" }, - { name = "jumpstarter-cli-common" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "imagehash", specifier = ">=4.3.1" }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + +[[package]] +name = "jumpstarter-kubernetes" +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter_kubernetes" } +dependencies = [ + { name = "jumpstarter" }, + { name = "kubernetes" }, + { name = "kubernetes-asyncio" }, ] [package.dev-dependencies] @@ -1214,9 +1386,9 @@ dev = [ [package.metadata] requires-dist = [ - { name = "asyncclick", specifier = ">=8.1.7.2" }, - { name = "jumpstarter", editable = "." }, - { name = "jumpstarter-cli-common", editable = "cli/common" }, + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "kubernetes", specifier = ">=31.0.0" }, + { name = "kubernetes-asyncio", specifier = ">=31.1.0" }, ] [package.metadata.requires-dev] @@ -1228,32 +1400,65 @@ dev = [ ] [[package]] -name = "jumpstarter-imagehash" -version = "0.5.1.dev16+gc1f555c.d20241209" -source = { editable = "contrib/libs/imagehash" } +name = "jumpstarter-protocol" +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter_protocol" } dependencies = [ - { name = "imagehash" }, - { name = "jumpstarter" }, + { name = "grpcio" }, + { name = "protobuf" }, ] [package.dev-dependencies] dev = [ { name = "pytest" }, + { name = "pytest-anyio" }, + { name = "pytest-asyncio" }, { name = "pytest-cov" }, ] [package.metadata] requires-dist = [ - { name = "imagehash", specifier = ">=4.3.1" }, - { name = "jumpstarter", editable = "." }, + { name = "grpcio", specifier = ">=1.66.1" }, + { name = "protobuf", specifier = ">=5.29.3" }, ] [package.metadata.requires-dev] dev = [ { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-anyio", specifier = ">=0.0.0" }, + { name = "pytest-asyncio", specifier = ">=0.0.0" }, { name = "pytest-cov", specifier = ">=5.0.0" }, ] +[[package]] +name = "jumpstarter-testing" +version = "0.5.1.dev94+g3eaebda.d20250121" +source = { editable = "packages/jumpstarter_testing" } +dependencies = [ + { name = "jumpstarter" }, + { name = "pytest" }, + { name = "pytest-anyio" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, +] + +[package.dev-dependencies] +dev = [ + { name = "jumpstarter-driver-power" }, +] + +[package.metadata] +requires-dist = [ + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "pytest", specifier = ">=8.3.2" }, + { name = "pytest-anyio", specifier = ">=0.0.0" }, + { name = "pytest-asyncio", specifier = ">=0.0.0" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, +] + +[package.metadata.requires-dev] +dev = [{ name = "jumpstarter-driver-power", editable = "packages/jumpstarter_driver_power" }] + [[package]] name = "kubernetes" version = "31.0.0" @@ -1519,6 +1724,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ad/63/1bf0426289ef07cc27afb570653669a6a7d57d988d6f877ff852483b38cd/opendal-0.45.12-cp311-abi3-win_amd64.whl", hash = "sha256:c87f488c547e17174d53f98da1c25135595bf93c29bab731d732f55d993534e0", size = 14809759 }, ] +[[package]] +name = "outcome" +version = "1.3.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/df/77698abfac98571e65ffeb0c1fba8ffd692ab8458d617a0eed7d9a8d38f2/outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", size = 21060 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b", size = 10692 }, +] + [[package]] name = "packaging" version = "24.2" @@ -1669,16 +1886,16 @@ wheels = [ [[package]] name = "protobuf" -version = "5.28.3" +version = "5.29.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/74/6e/e69eb906fddcb38f8530a12f4b410699972ab7ced4e21524ece9d546ac27/protobuf-5.28.3.tar.gz", hash = "sha256:64badbc49180a5e401f373f9ce7ab1d18b63f7dd4a9cdc43c92b9f0b481cef7b", size = 422479 } +sdist = { url = "https://files.pythonhosted.org/packages/f7/d1/e0a911544ca9993e0f17ce6d3cc0932752356c1b0a834397f28e63479344/protobuf-5.29.3.tar.gz", hash = "sha256:5da0f41edaf117bde316404bad1a486cb4ededf8e4a54891296f648e8e076620", size = 424945 } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/c5/05163fad52d7c43e124a545f1372d18266db36036377ad29de4271134a6a/protobuf-5.28.3-cp310-abi3-win32.whl", hash = "sha256:0c4eec6f987338617072592b97943fdbe30d019c56126493111cf24344c1cc24", size = 419624 }, - { url = "https://files.pythonhosted.org/packages/9c/4c/4563ebe001ff30dca9d7ed12e471fa098d9759712980cde1fd03a3a44fb7/protobuf-5.28.3-cp310-abi3-win_amd64.whl", hash = "sha256:91fba8f445723fcf400fdbe9ca796b19d3b1242cd873907979b9ed71e4afe868", size = 431464 }, - { url = "https://files.pythonhosted.org/packages/1c/f2/baf397f3dd1d3e4af7e3f5a0382b868d25ac068eefe1ebde05132333436c/protobuf-5.28.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a3f6857551e53ce35e60b403b8a27b0295f7d6eb63d10484f12bc6879c715687", size = 414743 }, - { url = "https://files.pythonhosted.org/packages/85/50/cd61a358ba1601f40e7d38bcfba22e053f40ef2c50d55b55926aecc8fec7/protobuf-5.28.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:3fa2de6b8b29d12c61911505d893afe7320ce7ccba4df913e2971461fa36d584", size = 316511 }, - { url = "https://files.pythonhosted.org/packages/5d/ae/3257b09328c0b4e59535e497b0c7537d4954038bdd53a2f0d2f49d15a7c4/protobuf-5.28.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:712319fbdddb46f21abb66cd33cb9e491a5763b2febd8f228251add221981135", size = 316624 }, - { url = "https://files.pythonhosted.org/packages/ad/c3/2377c159e28ea89a91cf1ca223f827ae8deccb2c9c401e5ca233cd73002f/protobuf-5.28.3-py3-none-any.whl", hash = "sha256:cee1757663fa32a1ee673434fcf3bf24dd54763c79690201208bafec62f19eed", size = 169511 }, + { url = "https://files.pythonhosted.org/packages/dc/7a/1e38f3cafa022f477ca0f57a1f49962f21ad25850c3ca0acd3b9d0091518/protobuf-5.29.3-cp310-abi3-win32.whl", hash = "sha256:3ea51771449e1035f26069c4c7fd51fba990d07bc55ba80701c78f886bf9c888", size = 422708 }, + { url = "https://files.pythonhosted.org/packages/61/fa/aae8e10512b83de633f2646506a6d835b151edf4b30d18d73afd01447253/protobuf-5.29.3-cp310-abi3-win_amd64.whl", hash = "sha256:a4fa6f80816a9a0678429e84973f2f98cbc218cca434abe8db2ad0bffc98503a", size = 434508 }, + { url = "https://files.pythonhosted.org/packages/dd/04/3eaedc2ba17a088961d0e3bd396eac764450f431621b58a04ce898acd126/protobuf-5.29.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a8434404bbf139aa9e1300dbf989667a83d42ddda9153d8ab76e0d5dcaca484e", size = 417825 }, + { url = "https://files.pythonhosted.org/packages/4f/06/7c467744d23c3979ce250397e26d8ad8eeb2bea7b18ca12ad58313c1b8d5/protobuf-5.29.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:daaf63f70f25e8689c072cfad4334ca0ac1d1e05a92fc15c54eb9cf23c3efd84", size = 319573 }, + { url = "https://files.pythonhosted.org/packages/a8/45/2ebbde52ad2be18d3675b6bee50e68cd73c9e0654de77d595540b5129df8/protobuf-5.29.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:c027e08a08be10b67c06bf2370b99c811c466398c357e615ca88c91c07f0910f", size = 319672 }, + { url = "https://files.pythonhosted.org/packages/fd/b2/ab07b09e0f6d143dfb839693aa05765257bceaa13d03bf1a696b78323e7a/protobuf-5.29.3-py3-none-any.whl", hash = "sha256:0a18ed4a24198528f2333802eb075e59dea9d679ab7a6c5efb017a59004d849f", size = 172550 }, ] [[package]] @@ -2125,6 +2342,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002 }, ] +[[package]] +name = "sortedcontainers" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 }, +] + [[package]] name = "soupsieve" version = "2.6" @@ -2309,6 +2535,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2b/78/57043611a16c655c8350b4c01b8d6abfb38cc2acb475238b62c2146186d7/tqdm-4.67.0-py3-none-any.whl", hash = "sha256:0cd8af9d56911acab92182e88d763100d4788bdf421d251616040cc4d44863be", size = 78590 }, ] +[[package]] +name = "trio" +version = "0.28.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "cffi", marker = "implementation_name != 'pypy' and os_name == 'nt'" }, + { name = "idna" }, + { name = "outcome" }, + { name = "sniffio" }, + { name = "sortedcontainers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/73/57efab729506a8d4b89814f1e356ec8f3369de0ed4fd7e7616974d09646d/trio-0.28.0.tar.gz", hash = "sha256:4e547896fe9e8a5658e54e4c7c5fa1db748cbbbaa7c965e7d40505b928c73c05", size = 580318 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b4/04/9954a59e1fb6732f5436225c9af963811d7b24ea62a8bf96991f2cb8c26e/trio-0.28.0-py3-none-any.whl", hash = "sha256:56d58977acc1635735a96581ec70513cc781b8b6decd299c487d3be2a721cd94", size = 486317 }, +] + [[package]] name = "typing-extensions" version = "4.12.2" From eabdbb74a3d69ec27b19e73f225131512462895a Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Wed, 22 Jan 2025 09:11:35 -0500 Subject: [PATCH 03/16] Move jumpstarter tests into jumpstarter package --- .../jumpstarter/jumpstarter/config/client_config_test.py | 0 .../jumpstarter/jumpstarter/config/user_config_test.py | 1 - .../jumpstarter/jumpstarter/listener_test.py | 0 tests/__init__.py | 0 4 files changed, 1 deletion(-) rename tests/test_client_config.py => packages/jumpstarter/jumpstarter/config/client_config_test.py (100%) rename tests/test_user_config.py => packages/jumpstarter/jumpstarter/config/user_config_test.py (99%) rename tests/test_listener.py => packages/jumpstarter/jumpstarter/listener_test.py (100%) delete mode 100644 tests/__init__.py diff --git a/tests/test_client_config.py b/packages/jumpstarter/jumpstarter/config/client_config_test.py similarity index 100% rename from tests/test_client_config.py rename to packages/jumpstarter/jumpstarter/config/client_config_test.py diff --git a/tests/test_user_config.py b/packages/jumpstarter/jumpstarter/config/user_config_test.py similarity index 99% rename from tests/test_user_config.py rename to packages/jumpstarter/jumpstarter/config/user_config_test.py index d7daa9d06..2504ab94b 100644 --- a/tests/test_user_config.py +++ b/packages/jumpstarter/jumpstarter/config/user_config_test.py @@ -3,7 +3,6 @@ from unittest.mock import patch import pytest - from jumpstarter.config import ( ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, diff --git a/tests/test_listener.py b/packages/jumpstarter/jumpstarter/listener_test.py similarity index 100% rename from tests/test_listener.py rename to packages/jumpstarter/jumpstarter/listener_test.py diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 From 07bed5a18f348391ac711fd62bedea29c19afc3b Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 13:16:02 -0500 Subject: [PATCH 04/16] Update lockfile --- uv.lock | 64 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/uv.lock b/uv.lock index 59e742875..63625bc31 100644 --- a/uv.lock +++ b/uv.lock @@ -32,19 +32,23 @@ members = [ "jumpstarter-protocol", "jumpstarter-testing", ] -requirements = [ - { name = "esbonio", specifier = ">=0.16.4" }, + +[manifest.dependency-groups] +dev = [ { name = "esbonio", specifier = ">=0.16.5" }, - { name = "furo", specifier = ">=2024.8.6" }, - { name = "myst-parser", specifier = ">=4.0.0" }, { name = "pre-commit", specifier = ">=3.8.0" }, { name = "ruff", specifier = ">=0.6.1" }, + { name = "typos", specifier = ">=1.23.6" }, +] +docs = [ + { name = "esbonio", specifier = ">=0.16.4" }, + { name = "furo", specifier = ">=2024.8.6" }, + { name = "myst-parser", specifier = ">=4.0.0" }, { name = "sphinx", specifier = "<8.1.0" }, { name = "sphinx-autobuild", specifier = ">=2024.4.16" }, { name = "sphinx-click", specifier = ">=6.0.0" }, { name = "sphinx-substitution-extensions", specifier = ">=2024.10.17" }, { name = "sphinxcontrib-mermaid", specifier = ">=0.9.2" }, - { name = "typos", specifier = ">=1.23.6" }, ] [[package]] @@ -160,7 +164,7 @@ version = "8.1.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cb/b5/e1e5fdf1c1bb7e6e614987c120a98d9324bf8edfaa5f5cd16a6235c9d91b/asyncclick-8.1.8.tar.gz", hash = "sha256:0f0eb0f280e04919d67cf71b9fcdfb4db2d9ff7203669c40284485c149578e4c", size = 232900 } wheels = [ @@ -362,7 +366,7 @@ name = "click" version = "8.1.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } wheels = [ @@ -733,7 +737,7 @@ wheels = [ [[package]] name = "jumpstarter" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter" } dependencies = [ { name = "aiohttp" }, @@ -780,7 +784,7 @@ dev = [ [[package]] name = "jumpstarter-cli" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_cli" } dependencies = [ { name = "jumpstarter-cli-admin" }, @@ -813,7 +817,7 @@ dev = [ [[package]] name = "jumpstarter-cli-admin" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_cli_admin" } dependencies = [ { name = "jumpstarter-cli-common" }, @@ -844,7 +848,7 @@ dev = [ [[package]] name = "jumpstarter-cli-client" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_cli_client" } dependencies = [ { name = "jumpstarter-cli-common" }, @@ -871,7 +875,7 @@ dev = [ [[package]] name = "jumpstarter-cli-common" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_cli_common" } dependencies = [ { name = "asyncclick" }, @@ -902,7 +906,7 @@ dev = [ [[package]] name = "jumpstarter-cli-exporter" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_cli_exporter" } dependencies = [ { name = "asyncclick" }, @@ -933,7 +937,7 @@ dev = [ [[package]] name = "jumpstarter-driver-can" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_can" } dependencies = [ { name = "can-isotp" }, @@ -962,7 +966,7 @@ dev = [ [[package]] name = "jumpstarter-driver-composite" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_composite" } dependencies = [ { name = "asyncclick" }, @@ -991,7 +995,7 @@ dev = [ [[package]] name = "jumpstarter-driver-dutlink" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_dutlink" } dependencies = [ { name = "asyncclick" }, @@ -1066,7 +1070,7 @@ dev = [ [[package]] name = "jumpstarter-driver-network" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_network" } dependencies = [ { name = "fabric" }, @@ -1099,7 +1103,7 @@ dev = [ [[package]] name = "jumpstarter-driver-opendal" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_opendal" } dependencies = [ { name = "asyncclick" }, @@ -1128,7 +1132,7 @@ dev = [ [[package]] name = "jumpstarter-driver-power" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_power" } dependencies = [ { name = "asyncclick" }, @@ -1159,7 +1163,7 @@ dev = [ [[package]] name = "jumpstarter-driver-pyserial" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_pyserial" } dependencies = [ { name = "asyncclick" }, @@ -1190,7 +1194,7 @@ dev = [ [[package]] name = "jumpstarter-driver-raspberrypi" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_raspberrypi" } dependencies = [ { name = "gpiozero" }, @@ -1217,7 +1221,7 @@ dev = [ [[package]] name = "jumpstarter-driver-sdwire" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_sdwire" } dependencies = [ { name = "jumpstarter" }, @@ -1285,7 +1289,7 @@ dev = [ [[package]] name = "jumpstarter-driver-ustreamer" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_ustreamer" } dependencies = [ { name = "jumpstarter" }, @@ -1342,7 +1346,7 @@ requires-dist = [ [[package]] name = "jumpstarter-imagehash" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_imagehash" } dependencies = [ { name = "imagehash" }, @@ -1369,7 +1373,7 @@ dev = [ [[package]] name = "jumpstarter-kubernetes" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_kubernetes" } dependencies = [ { name = "jumpstarter" }, @@ -1402,7 +1406,7 @@ dev = [ [[package]] name = "jumpstarter-protocol" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_protocol" } dependencies = [ { name = "grpcio" }, @@ -1433,7 +1437,7 @@ dev = [ [[package]] name = "jumpstarter-testing" -version = "0.5.1.dev96+geabdbb7.d20250122" +version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_testing" } dependencies = [ { name = "jumpstarter" }, @@ -2105,9 +2109,9 @@ name = "python-can" version = "4.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "msgpack", marker = "platform_system != 'Windows'" }, + { name = "msgpack", marker = "sys_platform != 'win32'" }, { name = "packaging" }, - { name = "pywin32", marker = "platform_python_implementation == 'CPython' and platform_system == 'Windows'" }, + { name = "pywin32", marker = "platform_python_implementation == 'CPython' and sys_platform == 'win32'" }, { name = "typing-extensions" }, { name = "wrapt" }, ] @@ -2529,7 +2533,7 @@ name = "tqdm" version = "4.67.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e8/4f/0153c21dc5779a49a0598c445b1978126b1344bab9ee71e53e44877e14e0/tqdm-4.67.0.tar.gz", hash = "sha256:fe5a6f95e6fe0b9755e9469b77b9c3cf850048224ecaa8293d7d2d31f97d869a", size = 169739 } wheels = [ From a05c9f01e674ab293f5cb9ebd392dfcd57b9eea9 Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 13:20:03 -0500 Subject: [PATCH 05/16] Fix ruff ignore, lint errors, and remove workspace dep versions --- packages/jumpstarter/conftest.py | 3 ++- .../jumpstarter/jumpstarter/client/base.py | 3 ++- .../jumpstarter/jumpstarter/client/client.py | 3 ++- .../jumpstarter/jumpstarter/client/core.py | 3 ++- .../jumpstarter/jumpstarter/client/lease.py | 3 ++- .../jumpstarter/jumpstarter/common/streams.py | 5 +++-- .../jumpstarter/jumpstarter/config/client.py | 5 +++-- .../jumpstarter/config/client_config_test.py | 3 ++- .../jumpstarter/config/exporter.py | 3 ++- .../jumpstarter/config/exporter_test.py | 1 + .../jumpstarter/config/user_config_test.py | 1 + .../jumpstarter/jumpstarter/driver/base.py | 7 ++++--- .../jumpstarter/exporter/exporter.py | 9 +++++---- .../jumpstarter/exporter/session.py | 9 +++++---- .../jumpstarter_cli_admin/create.py | 3 ++- .../jumpstarter_cli_admin/create_test.py | 11 +++++----- .../jumpstarter_cli_admin/delete.py | 3 ++- .../jumpstarter_cli_admin/delete_test.py | 15 +++++++------- .../jumpstarter_cli_admin/get_test.py | 5 ++--- .../jumpstarter_cli_admin/import_res.py | 11 +++++----- .../jumpstarter_cli_admin/import_res_test.py | 8 ++++---- .../jumpstarter_cli_client/__init__.py | 3 ++- .../jumpstarter_cli_client/client_config.py | 3 ++- .../jumpstarter_cli_client/client_shell.py | 1 + .../jumpstarter_cli_client/client_test.py | 1 + .../jumpstarter_cli_client/lease.py | 3 ++- .../jumpstarter_cli_exporter/exporter.py | 1 + .../exporter_config.py | 3 ++- .../jumpstarter_cli_exporter/exporter_test.py | 1 + .../jumpstarter_driver_composite/client.py | 1 + .../jumpstarter_driver_composite/driver.py | 3 ++- .../driver_test.py | 3 ++- .../examples/dutlink.py | 3 ++- .../jumpstarter_driver_dutlink/driver.py | 3 ++- .../jumpstarter_driver_dutlink/driver_test.py | 2 +- .../jumpstarter_driver_http/client.py | 3 ++- .../jumpstarter_driver_http/driver.py | 1 + .../jumpstarter_driver_http/driver_test.py | 1 + .../adapters/fabric_test.py | 3 ++- .../adapters/novnc_test.py | 3 ++- .../jumpstarter_driver_network/driver.py | 1 + .../jumpstarter_driver_network/driver_test.py | 1 + .../jumpstarter_driver_opendal/adapter.py | 5 +++-- .../jumpstarter_driver_opendal/client.py | 3 ++- .../jumpstarter_driver_opendal/driver.py | 1 + .../jumpstarter_driver_opendal/driver_test.py | 3 ++- .../jumpstarter_driver_power/client.py | 1 + .../jumpstarter_driver_pyserial/client.py | 3 ++- .../jumpstarter_driver_pyserial/driver.py | 3 ++- .../jumpstarter_driver_sdwire/driver.py | 3 ++- .../jumpstarter_driver_sdwire/driver_test.py | 2 +- .../jumpstarter_driver_tftp/client.py | 3 ++- .../jumpstarter_driver_tftp/driver.py | 2 +- .../jumpstarter_driver_tftp/driver_test.py | 2 +- .../jumpstarter_kubernetes/clients.py | 3 ++- .../jumpstarter_kubernetes/exporters.py | 3 ++- .../jumpstarter_testing/pytest.py | 1 + .../jumpstarter_testing/pytest_test.py | 5 +++-- pyproject.toml | 4 ++-- uv.lock | 20 ------------------- 60 files changed, 128 insertions(+), 97 deletions(-) diff --git a/packages/jumpstarter/conftest.py b/packages/jumpstarter/conftest.py index 159b28ab1..91a57bc36 100644 --- a/packages/jumpstarter/conftest.py +++ b/packages/jumpstarter/conftest.py @@ -14,7 +14,6 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import rsa -from jumpstarter.streams import RouterStream, forward_stream from jumpstarter_protocol import ( jumpstarter_pb2, jumpstarter_pb2_grpc, @@ -22,6 +21,8 @@ router_pb2_grpc, ) +from jumpstarter.streams import RouterStream, forward_stream + @dataclass(kw_only=True) class MockRouter(router_pb2_grpc.RouterServiceServicer): diff --git a/packages/jumpstarter/jumpstarter/client/base.py b/packages/jumpstarter/jumpstarter/client/base.py index 22f236447..5b4e7cfd1 100644 --- a/packages/jumpstarter/jumpstarter/client/base.py +++ b/packages/jumpstarter/jumpstarter/client/base.py @@ -8,10 +8,11 @@ from dataclasses import field from anyio.from_thread import BlockingPortal -from jumpstarter.streams import BlockingStream from pydantic import ConfigDict from pydantic.dataclasses import dataclass +from jumpstarter.streams import BlockingStream + from .core import AsyncDriverClient diff --git a/packages/jumpstarter/jumpstarter/client/client.py b/packages/jumpstarter/jumpstarter/client/client.py index 257dd6b71..3eec9033b 100644 --- a/packages/jumpstarter/jumpstarter/client/client.py +++ b/packages/jumpstarter/jumpstarter/client/client.py @@ -6,9 +6,10 @@ from anyio.from_thread import BlockingPortal from google.protobuf import empty_pb2 from graphlib import TopologicalSorter +from jumpstarter_protocol import jumpstarter_pb2_grpc + from jumpstarter.client import DriverClient from jumpstarter.common.importlib import import_class -from jumpstarter_protocol import jumpstarter_pb2_grpc @asynccontextmanager diff --git a/packages/jumpstarter/jumpstarter/client/core.py b/packages/jumpstarter/jumpstarter/client/core.py index f7deaae52..193d1e492 100644 --- a/packages/jumpstarter/jumpstarter/client/core.py +++ b/packages/jumpstarter/jumpstarter/client/core.py @@ -7,6 +7,8 @@ from grpc import StatusCode from grpc.aio import AioRpcError, Channel +from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc + from jumpstarter.common import Metadata from jumpstarter.common.resources import ResourceMetadata from jumpstarter.common.serde import decode_value, encode_value @@ -22,7 +24,6 @@ RouterStream, forward_stream, ) -from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc @dataclass(kw_only=True) diff --git a/packages/jumpstarter/jumpstarter/client/lease.py b/packages/jumpstarter/jumpstarter/client/lease.py index 637938005..1ec426df0 100644 --- a/packages/jumpstarter/jumpstarter/client/lease.py +++ b/packages/jumpstarter/jumpstarter/client/lease.py @@ -6,12 +6,13 @@ from anyio.from_thread import BlockingPortal from google.protobuf import duration_pb2 from grpc.aio import Channel +from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, kubernetes_pb2 + from jumpstarter.client import client_from_path from jumpstarter.common import MetadataFilter, TemporaryUnixListener from jumpstarter.common.condition import condition_false, condition_present_and_equal, condition_true from jumpstarter.common.streams import connect_router_stream from jumpstarter.config.tls import TLSConfigV1Alpha1 -from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, kubernetes_pb2 logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter/jumpstarter/common/streams.py b/packages/jumpstarter/jumpstarter/common/streams.py index e2a9db6ad..d1fa265d2 100644 --- a/packages/jumpstarter/jumpstarter/common/streams.py +++ b/packages/jumpstarter/jumpstarter/common/streams.py @@ -3,11 +3,12 @@ from uuid import UUID import grpc -from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials -from jumpstarter.streams import RouterStream, forward_stream from jumpstarter_protocol.jumpstarter.v1 import router_pb2_grpc from pydantic import BaseModel, Field, Json +from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials +from jumpstarter.streams import RouterStream, forward_stream + class ResourceStreamRequest(BaseModel): kind: Literal["resource"] = "resource" diff --git a/packages/jumpstarter/jumpstarter/config/client.py b/packages/jumpstarter/jumpstarter/config/client.py index c50d7395d..82096fb3f 100644 --- a/packages/jumpstarter/jumpstarter/config/client.py +++ b/packages/jumpstarter/jumpstarter/config/client.py @@ -6,11 +6,12 @@ import grpc import yaml from anyio.from_thread import BlockingPortal, start_blocking_portal -from jumpstarter.common import MetadataFilter -from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc from pydantic import BaseModel, Field, ValidationError +from jumpstarter.common import MetadataFilter +from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials + from .common import CONFIG_PATH from .env import JMP_DRIVERS_ALLOW, JMP_ENDPOINT, JMP_LEASE, JMP_TOKEN from .tls import TLSConfigV1Alpha1 diff --git a/packages/jumpstarter/jumpstarter/config/client_config_test.py b/packages/jumpstarter/jumpstarter/config/client_config_test.py index 325873477..fbdc1e9ae 100644 --- a/packages/jumpstarter/jumpstarter/config/client_config_test.py +++ b/packages/jumpstarter/jumpstarter/config/client_config_test.py @@ -5,12 +5,13 @@ import pytest import yaml +from pydantic import ValidationError + from jumpstarter.config import ( ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, ) from jumpstarter.config.env import JMP_DRIVERS_ALLOW, JMP_ENDPOINT, JMP_TOKEN -from pydantic import ValidationError def test_client_ensure_exists_makes_dir(monkeypatch: pytest.MonkeyPatch): diff --git a/packages/jumpstarter/jumpstarter/config/exporter.py b/packages/jumpstarter/jumpstarter/config/exporter.py index bad4cc90e..5cbf0987a 100644 --- a/packages/jumpstarter/jumpstarter/config/exporter.py +++ b/packages/jumpstarter/jumpstarter/config/exporter.py @@ -7,10 +7,11 @@ import grpc import yaml from anyio.from_thread import start_blocking_portal +from pydantic import BaseModel, Field + from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials from jumpstarter.common.importlib import import_class from jumpstarter.driver import Driver -from pydantic import BaseModel, Field from .tls import TLSConfigV1Alpha1 diff --git a/packages/jumpstarter/jumpstarter/config/exporter_test.py b/packages/jumpstarter/jumpstarter/config/exporter_test.py index 03af35897..41028437d 100644 --- a/packages/jumpstarter/jumpstarter/config/exporter_test.py +++ b/packages/jumpstarter/jumpstarter/config/exporter_test.py @@ -3,6 +3,7 @@ import pytest from anyio import create_task_group from anyio.from_thread import start_blocking_portal + from jumpstarter.common import MetadataFilter from .client import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers diff --git a/packages/jumpstarter/jumpstarter/config/user_config_test.py b/packages/jumpstarter/jumpstarter/config/user_config_test.py index 2504ab94b..d7daa9d06 100644 --- a/packages/jumpstarter/jumpstarter/config/user_config_test.py +++ b/packages/jumpstarter/jumpstarter/config/user_config_test.py @@ -3,6 +3,7 @@ from unittest.mock import patch import pytest + from jumpstarter.config import ( ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, diff --git a/packages/jumpstarter/jumpstarter/driver/base.py b/packages/jumpstarter/jumpstarter/driver/base.py index 712b21a12..b425b624f 100644 --- a/packages/jumpstarter/jumpstarter/driver/base.py +++ b/packages/jumpstarter/jumpstarter/driver/base.py @@ -15,6 +15,10 @@ import aiohttp from anyio import to_thread from grpc import StatusCode +from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc +from pydantic import TypeAdapter +from pydantic.dataclasses import dataclass + from jumpstarter.common import Metadata from jumpstarter.common.resources import ClientStreamResource, PresignedRequestResource, Resource, ResourceMetadata from jumpstarter.common.serde import decode_value, encode_value @@ -23,9 +27,6 @@ ResourceStreamRequest, ) from jumpstarter.streams import AiohttpStreamReaderStream, MetadataStream, create_memory_stream -from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc -from pydantic import TypeAdapter -from pydantic.dataclasses import dataclass from .decorators import ( MARKER_DRIVERCALL, diff --git a/packages/jumpstarter/jumpstarter/exporter/exporter.py b/packages/jumpstarter/jumpstarter/exporter/exporter.py index 1420215cb..ff3963d32 100644 --- a/packages/jumpstarter/jumpstarter/exporter/exporter.py +++ b/packages/jumpstarter/jumpstarter/exporter/exporter.py @@ -6,15 +6,16 @@ import grpc from anyio import connect_unix, create_task_group from google.protobuf import empty_pb2 +from jumpstarter_protocol import ( + jumpstarter_pb2, + jumpstarter_pb2_grpc, +) + from jumpstarter.common import Metadata from jumpstarter.common.streams import connect_router_stream from jumpstarter.config.tls import TLSConfigV1Alpha1 from jumpstarter.driver import Driver from jumpstarter.exporter.session import Session -from jumpstarter_protocol import ( - jumpstarter_pb2, - jumpstarter_pb2_grpc, -) logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter/jumpstarter/exporter/session.py b/packages/jumpstarter/jumpstarter/exporter/session.py index 892e9585b..3e8e82b93 100644 --- a/packages/jumpstarter/jumpstarter/exporter/session.py +++ b/packages/jumpstarter/jumpstarter/exporter/session.py @@ -6,16 +6,17 @@ import grpc from anyio import Event, TypedAttributeLookupError from anyio.from_thread import start_blocking_portal -from jumpstarter.common import Metadata, TemporarySocket -from jumpstarter.common.streams import StreamRequestMetadata -from jumpstarter.driver import Driver -from jumpstarter.streams import MetadataStreamAttributes, RouterStream, forward_stream from jumpstarter_protocol import ( jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc, ) +from jumpstarter.common import Metadata, TemporarySocket +from jumpstarter.common.streams import StreamRequestMetadata +from jumpstarter.driver import Driver +from jumpstarter.streams import MetadataStreamAttributes, RouterStream, forward_stream + logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py index d5ebcf7aa..d2fc864a9 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py @@ -2,7 +2,6 @@ from typing import Optional import asyncclick as click -from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 from jumpstarter_cli_common import ( AliasedGroup, opt_context, @@ -14,6 +13,8 @@ from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.config.config_exception import ConfigException +from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 + from .k8s import ( handle_k8s_api_exception, handle_k8s_config_exception, diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py index f7fd3ecff..1ccd58621 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py @@ -3,11 +3,6 @@ import pytest from asyncclick.testing import CliRunner -from jumpstarter.config import ( - ClientConfigV1Alpha1, - ClientConfigV1Alpha1Drivers, - ExporterConfigV1Alpha1, -) from jumpstarter_kubernetes import ( ClientsV1Alpha1Api, ExportersV1Alpha1Api, @@ -18,6 +13,12 @@ ) from kubernetes_asyncio.client.models import V1ObjectMeta +from jumpstarter.config import ( + ClientConfigV1Alpha1, + ClientConfigV1Alpha1Drivers, + ExporterConfigV1Alpha1, +) + from .create import create # Generate a random client name diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py index 3df7151f9..dc0d55b45 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py @@ -2,7 +2,6 @@ from typing import Optional import asyncclick as click -from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 from jumpstarter_cli_common import ( AliasedGroup, opt_context, @@ -14,6 +13,8 @@ from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.config.config_exception import ConfigException +from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 + from .k8s import ( handle_k8s_api_exception, handle_k8s_config_exception, diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py index 521966906..bba248db3 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py @@ -2,13 +2,6 @@ import pytest from asyncclick.testing import CliRunner -from jumpstarter.config import ( - ClientConfigV1Alpha1, - ClientConfigV1Alpha1Drivers, - ExporterConfigV1Alpha1, - UserConfigV1Alpha1, - UserConfigV1Alpha1Config, -) from jumpstarter_kubernetes import ( ClientsV1Alpha1Api, ExportersV1Alpha1Api, @@ -17,6 +10,14 @@ ) from kubernetes_asyncio.client.models import V1ObjectMeta +from jumpstarter.config import ( + ClientConfigV1Alpha1, + ClientConfigV1Alpha1Drivers, + ExporterConfigV1Alpha1, + UserConfigV1Alpha1, + UserConfigV1Alpha1Config, +) + from .delete import delete # Generate a random client name diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get_test.py index f9790f3f1..f4ce22bdb 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get_test.py @@ -2,9 +2,6 @@ import pytest from asyncclick.testing import CliRunner -from kubernetes_asyncio.client.exceptions import ApiException -from kubernetes_asyncio.client.models import V1Condition, V1ObjectMeta, V1ObjectReference - from jumpstarter_kubernetes import ( ClientsV1Alpha1Api, ExportersV1Alpha1Api, @@ -18,6 +15,8 @@ V1Alpha1LeaseSpec, V1Alpha1LeaseStatus, ) +from kubernetes_asyncio.client.exceptions import ApiException +from kubernetes_asyncio.client.models import V1Condition, V1ObjectMeta, V1ObjectReference from .get import get diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py index 10dd4aa8b..0ab62c33e 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py @@ -1,11 +1,6 @@ from typing import Optional import asyncclick as click -from jumpstarter.config import ( - ClientConfigV1Alpha1, - UserConfigV1Alpha1, -) -from jumpstarter.config.exporter import ExporterConfigV1Alpha1 from jumpstarter_cli_common import ( opt_context, opt_kubeconfig, @@ -15,6 +10,12 @@ from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.config.config_exception import ConfigException +from jumpstarter.config import ( + ClientConfigV1Alpha1, + UserConfigV1Alpha1, +) +from jumpstarter.config.exporter import ExporterConfigV1Alpha1 + from .k8s import ( handle_k8s_api_exception, handle_k8s_config_exception, diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py index 99deb5124..e94539bd1 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py @@ -3,16 +3,16 @@ import pytest from asyncclick.testing import CliRunner +from jumpstarter_kubernetes import ( + ClientsV1Alpha1Api, + ExportersV1Alpha1Api, +) from jumpstarter.config import ( ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, ExporterConfigV1Alpha1, ) -from jumpstarter_kubernetes import ( - ClientsV1Alpha1Api, - ExportersV1Alpha1Api, -) from .import_res import import_res diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py index e0a2f19f3..7812d3d8e 100644 --- a/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py @@ -1,7 +1,8 @@ import asyncclick as click -from jumpstarter.common.utils import env from jumpstarter_cli_common import AliasedGroup, version +from jumpstarter.common.utils import env + from .client_config import create_client_config, delete_client_config, list_client_configs, use_client_config from .client_shell import client_shell from .lease import lease diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py index bed794ea0..5a08aa25f 100644 --- a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py @@ -1,9 +1,10 @@ from typing import Optional import asyncclick as click -from jumpstarter.config import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, UserConfigV1Alpha1 from jumpstarter_cli_common import make_table +from jumpstarter.config import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, UserConfigV1Alpha1 + @click.command("create-config", short_help="Create a client config.") @click.argument("name") diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py index fc1eb856c..ec5c11857 100644 --- a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py @@ -1,4 +1,5 @@ import asyncclick as click + from jumpstarter.common import MetadataFilter from jumpstarter.common.utils import launch_shell from jumpstarter.config import ( diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py index 1440e5adf..e717a84bb 100644 --- a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py @@ -1,5 +1,6 @@ import pytest from asyncclick.testing import CliRunner + from jumpstarter.config import ClientConfigV1Alpha1, UserConfigV1Alpha1 from . import client diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py index 0ec567229..24b20ed1f 100644 --- a/packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py @@ -1,9 +1,10 @@ import asyncclick as click +from jumpstarter_cli_common import AliasedGroup + from jumpstarter.config import ( ClientConfigV1Alpha1, UserConfigV1Alpha1, ) -from jumpstarter_cli_common import AliasedGroup @click.group(cls=AliasedGroup, short_help="") diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py index 0944b7d19..945587535 100644 --- a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py +++ b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py @@ -3,6 +3,7 @@ from pathlib import Path import asyncclick as click + from jumpstarter.common.utils import launch_shell from jumpstarter.config.exporter import ExporterConfigV1Alpha1 diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py index 074ec2662..6283f6098 100644 --- a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py +++ b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py @@ -1,7 +1,8 @@ import asyncclick as click -from jumpstarter.config.exporter import ExporterConfigV1Alpha1 from jumpstarter_cli_common import make_table +from jumpstarter.config.exporter import ExporterConfigV1Alpha1 + arg_alias = click.argument("alias", default="default") diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py index f3824fd21..473337db7 100644 --- a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py +++ b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py @@ -1,5 +1,6 @@ import pytest from asyncclick.testing import CliRunner + from jumpstarter.config.exporter import ExporterConfigV1Alpha1 from . import exporter diff --git a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py index 273e0434f..fed7d169e 100644 --- a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py +++ b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py @@ -1,6 +1,7 @@ from dataclasses import dataclass import asyncclick as click + from jumpstarter.client import DriverClient diff --git a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py index 438ce317b..5a8f66990 100644 --- a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py +++ b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py @@ -1,6 +1,7 @@ -from jumpstarter.driver import Driver from pydantic.dataclasses import dataclass +from jumpstarter.driver import Driver + class CompositeInterface: @classmethod diff --git a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py index b2adf6d02..03f4fb580 100644 --- a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py +++ b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py @@ -1,6 +1,7 @@ -from jumpstarter.common.utils import serve from jumpstarter_driver_power.driver import MockPower +from jumpstarter.common.utils import serve + from .driver import Composite diff --git a/packages/jumpstarter_driver_dutlink/examples/dutlink.py b/packages/jumpstarter_driver_dutlink/examples/dutlink.py index b04840f40..dc2fea042 100755 --- a/packages/jumpstarter_driver_dutlink/examples/dutlink.py +++ b/packages/jumpstarter_driver_dutlink/examples/dutlink.py @@ -3,9 +3,10 @@ import time import asyncclick as click -from jumpstarter.common.utils import env from jumpstarter_driver_network.adapters import PexpectAdapter +from jumpstarter.common.utils import env + # initialize client from exporter config # from jumpstarter.common import MetadataFilter # from jumpstarter.config.client import ClientConfigV1Alpha1 diff --git a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py index dc583ee1c..40e287e55 100644 --- a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py +++ b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py @@ -11,13 +11,14 @@ import usb.util from anyio import fail_after, sleep from anyio.streams.file import FileReadStream, FileWriteStream -from jumpstarter.driver import Driver, export from jumpstarter_driver_composite.driver import CompositeInterface from jumpstarter_driver_opendal.driver import StorageMuxInterface from jumpstarter_driver_power.driver import PowerInterface, PowerReading from jumpstarter_driver_pyserial.driver import PySerial from serial.serialutil import SerialException +from jumpstarter.driver import Driver, export + log = logging.getLogger(__name__) diff --git a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py index efab289d4..18c82ae0b 100644 --- a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py +++ b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py @@ -1,8 +1,8 @@ import pytest import usb -from jumpstarter.common.utils import serve from jumpstarter_driver_network.adapters import PexpectAdapter +from jumpstarter.common.utils import serve from jumpstarter_driver_dutlink.driver import Dutlink diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py index ceb1702dd..6ee1f29ba 100644 --- a/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py @@ -1,10 +1,11 @@ from dataclasses import dataclass from pathlib import Path -from jumpstarter.client import DriverClient from jumpstarter_driver_opendal.adapter import OpendalAdapter from opendal import Operator +from jumpstarter.client import DriverClient + @dataclass(kw_only=True) class HttpServerClient(DriverClient): diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py index f55feb096..060e1a5a9 100644 --- a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py @@ -7,6 +7,7 @@ import anyio from aiohttp import web from anyio.streams.file import FileWriteStream + from jumpstarter.driver import Driver, export logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py index 73d3ec61d..2a47da734 100644 --- a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py @@ -6,6 +6,7 @@ import anyio import pytest from anyio import create_memory_object_stream + from jumpstarter.common.resources import ClientStreamResource from .driver import HttpServer diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py index 6845e257b..12d478752 100644 --- a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py @@ -2,10 +2,11 @@ from threading import Thread from time import sleep -from jumpstarter.common.utils import serve from paramiko import AUTH_SUCCESSFUL, OPEN_SUCCEEDED, ServerInterface, Transport from paramiko.rsakey import RSAKey +from jumpstarter.common.utils import serve + from ..driver import TcpNetwork from .fabric import FabricAdapter diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py index f3b5deaab..7f84c9d0e 100644 --- a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py @@ -2,9 +2,10 @@ from urllib.parse import parse_qsl, urlparse from anyio.from_thread import start_blocking_portal +from websocket import create_connection + from jumpstarter.common import TemporaryTcpListener from jumpstarter.common.utils import serve -from websocket import create_connection from ..driver import TcpNetwork from .novnc import NovncAdapter diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py index 8b2293ef7..8b7e64ce5 100644 --- a/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py @@ -10,6 +10,7 @@ create_memory_object_stream, ) from anyio.streams.stapled import StapledObjectStream + from jumpstarter.driver import Driver, exportstream logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py index 647e229be..7dbe04ec9 100644 --- a/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py @@ -5,6 +5,7 @@ import pytest from anyio.from_thread import start_blocking_portal + from jumpstarter.common import TemporaryTcpListener, TemporaryUnixListener from jumpstarter.common.utils import serve diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py index a94be7948..1dde10343 100644 --- a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py @@ -4,11 +4,12 @@ from anyio import BrokenResourceError, EndOfStream from anyio.abc import ObjectStream -from jumpstarter.client.adapters import ClientAdapter -from jumpstarter.common.resources import PresignedRequestResource from opendal import AsyncFile, Operator from opendal.exceptions import Error +from jumpstarter.client.adapters import ClientAdapter +from jumpstarter.common.resources import PresignedRequestResource + @dataclass(frozen=True, kw_only=True, slots=True) class AsyncFileStream(ObjectStream[bytes]): diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py index 261a86069..5905b4538 100644 --- a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py @@ -1,9 +1,10 @@ from pathlib import Path import asyncclick as click -from jumpstarter.client import DriverClient from opendal import Operator +from jumpstarter.client import DriverClient + from .adapter import OpendalAdapter diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py index 47d36f19b..0b2f17934 100644 --- a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py @@ -3,6 +3,7 @@ from tempfile import NamedTemporaryFile from anyio.streams.file import FileReadStream, FileWriteStream + from jumpstarter.driver import Driver, export diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py index 90221b443..1b0536316 100644 --- a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py @@ -5,9 +5,10 @@ from threading import Thread import pytest -from jumpstarter.common.utils import serve from opendal import Operator +from jumpstarter.common.utils import serve + from .driver import MockStorageMux diff --git a/packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py b/packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py index be2003773..f9aa897d7 100644 --- a/packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py +++ b/packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py @@ -1,6 +1,7 @@ from collections.abc import Generator import asyncclick as click + from jumpstarter.client import DriverClient from .common import PowerReading diff --git a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py index f6640cc49..c0080db77 100644 --- a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py +++ b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py @@ -1,10 +1,11 @@ from contextlib import contextmanager import asyncclick as click -from jumpstarter.client import DriverClient from jumpstarter_driver_network.adapters import PexpectAdapter from pexpect.fdpexpect import fdspawn +from jumpstarter.client import DriverClient + from .console import Console diff --git a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py index 69d4d0f88..67505d142 100644 --- a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py +++ b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py @@ -4,9 +4,10 @@ from anyio.abc import ObjectStream from anyio.to_thread import run_sync -from jumpstarter.driver import Driver, exportstream from serial import Serial, serial_for_url +from jumpstarter.driver import Driver, exportstream + log = logging.getLogger(__name__) diff --git a/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py index ad5d94419..f7c6d8269 100644 --- a/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py +++ b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py @@ -8,9 +8,10 @@ import usb.util from anyio import fail_after, sleep from anyio.streams.file import FileReadStream, FileWriteStream -from jumpstarter.driver import Driver, export from jumpstarter_driver_opendal.driver import StorageMuxInterface +from jumpstarter.driver import Driver, export + @dataclass(kw_only=True) class SDWire(StorageMuxInterface, Driver): diff --git a/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py index 8f4434d0d..d6d9c9aed 100644 --- a/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py +++ b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py @@ -1,7 +1,7 @@ import pytest import usb -from jumpstarter.common.utils import serve +from jumpstarter.common.utils import serve from jumpstarter_driver_sdwire.driver import SDWire diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py index 06c009c6f..cc22910cd 100644 --- a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py @@ -1,10 +1,11 @@ from dataclasses import dataclass from pathlib import Path -from jumpstarter.client import DriverClient from jumpstarter_driver_opendal.adapter import OpendalAdapter from opendal import Operator +from jumpstarter.client import DriverClient + @dataclass(kw_only=True) class TftpServerClient(DriverClient): diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py index de0e24a5b..bd4fb7580 100644 --- a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py @@ -8,8 +8,8 @@ from typing import Optional from anyio.streams.file import FileWriteStream -from jumpstarter.driver import Driver, export +from jumpstarter.driver import Driver, export from jumpstarter_driver_tftp.server import TftpServer logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py index 28c8274cf..7cb9f2964 100644 --- a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py @@ -6,8 +6,8 @@ import anyio import pytest from anyio import create_memory_object_stream -from jumpstarter.common.resources import ClientStreamResource +from jumpstarter.common.resources import ClientStreamResource from jumpstarter_driver_tftp.driver import ( FileNotFound, Tftp, diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py index 34d80f356..cd3d69e37 100644 --- a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py +++ b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py @@ -4,9 +4,10 @@ from dataclasses import dataclass from typing import Literal, Optional -from jumpstarter.config import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers from kubernetes_asyncio.client.models import V1ObjectMeta, V1ObjectReference +from jumpstarter.config import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers + from .util import AbstractAsyncCustomObjectApi logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py index ff23bb216..27b115e2c 100644 --- a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py +++ b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py @@ -3,9 +3,10 @@ from dataclasses import dataclass from typing import Literal -from jumpstarter.config import ExporterConfigV1Alpha1 from kubernetes_asyncio.client.models import V1ObjectMeta, V1ObjectReference +from jumpstarter.config import ExporterConfigV1Alpha1 + from .util import AbstractAsyncCustomObjectApi CREATE_EXPORTER_DELAY = 1 diff --git a/packages/jumpstarter_testing/jumpstarter_testing/pytest.py b/packages/jumpstarter_testing/jumpstarter_testing/pytest.py index 12315c388..a841ba7bb 100644 --- a/packages/jumpstarter_testing/jumpstarter_testing/pytest.py +++ b/packages/jumpstarter_testing/jumpstarter_testing/pytest.py @@ -3,6 +3,7 @@ from typing import ClassVar import pytest + from jumpstarter.common import MetadataFilter from jumpstarter.common.utils import env from jumpstarter.config.client import ClientConfigV1Alpha1 diff --git a/packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py b/packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py index 60be99a0d..b026ec5d3 100644 --- a/packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py +++ b/packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py @@ -1,8 +1,9 @@ -from jumpstarter.config.env import JMP_DRIVERS_ALLOW, JUMPSTARTER_HOST -from jumpstarter.exporter import Session from jumpstarter_driver_power.driver import MockPower from pytest import Pytester +from jumpstarter.config.env import JMP_DRIVERS_ALLOW, JUMPSTARTER_HOST +from jumpstarter.exporter import Session + def test_env(pytester: Pytester, monkeypatch): pytester.makepyfile( diff --git a/pyproject.toml b/pyproject.toml index 31c6be0a7..7fd893c84 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,11 +44,11 @@ dev = [ ] [tool.ruff] -exclude = ["jumpstarter/v1"] +exclude = ["packages/jumpstarter_protocol"] line-length = 120 [tool.ruff.lint] -exclude = ["jumpstarter/v1"] +exclude = ["packages/jumpstarter_protocol"] extend-select = ["I", "C", "E", "F", "W", "B"] [tool.typos.default] diff --git a/uv.lock b/uv.lock index 63625bc31..e33672d88 100644 --- a/uv.lock +++ b/uv.lock @@ -737,7 +737,6 @@ wheels = [ [[package]] name = "jumpstarter" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter" } dependencies = [ { name = "aiohttp" }, @@ -784,7 +783,6 @@ dev = [ [[package]] name = "jumpstarter-cli" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_cli" } dependencies = [ { name = "jumpstarter-cli-admin" }, @@ -817,7 +815,6 @@ dev = [ [[package]] name = "jumpstarter-cli-admin" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_cli_admin" } dependencies = [ { name = "jumpstarter-cli-common" }, @@ -848,7 +845,6 @@ dev = [ [[package]] name = "jumpstarter-cli-client" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_cli_client" } dependencies = [ { name = "jumpstarter-cli-common" }, @@ -875,7 +871,6 @@ dev = [ [[package]] name = "jumpstarter-cli-common" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_cli_common" } dependencies = [ { name = "asyncclick" }, @@ -906,7 +901,6 @@ dev = [ [[package]] name = "jumpstarter-cli-exporter" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_cli_exporter" } dependencies = [ { name = "asyncclick" }, @@ -937,7 +931,6 @@ dev = [ [[package]] name = "jumpstarter-driver-can" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_can" } dependencies = [ { name = "can-isotp" }, @@ -966,7 +959,6 @@ dev = [ [[package]] name = "jumpstarter-driver-composite" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_composite" } dependencies = [ { name = "asyncclick" }, @@ -995,7 +987,6 @@ dev = [ [[package]] name = "jumpstarter-driver-dutlink" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_dutlink" } dependencies = [ { name = "asyncclick" }, @@ -1070,7 +1061,6 @@ dev = [ [[package]] name = "jumpstarter-driver-network" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_network" } dependencies = [ { name = "fabric" }, @@ -1103,7 +1093,6 @@ dev = [ [[package]] name = "jumpstarter-driver-opendal" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_opendal" } dependencies = [ { name = "asyncclick" }, @@ -1132,7 +1121,6 @@ dev = [ [[package]] name = "jumpstarter-driver-power" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_power" } dependencies = [ { name = "asyncclick" }, @@ -1163,7 +1151,6 @@ dev = [ [[package]] name = "jumpstarter-driver-pyserial" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_pyserial" } dependencies = [ { name = "asyncclick" }, @@ -1194,7 +1181,6 @@ dev = [ [[package]] name = "jumpstarter-driver-raspberrypi" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_raspberrypi" } dependencies = [ { name = "gpiozero" }, @@ -1221,7 +1207,6 @@ dev = [ [[package]] name = "jumpstarter-driver-sdwire" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_sdwire" } dependencies = [ { name = "jumpstarter" }, @@ -1289,7 +1274,6 @@ dev = [ [[package]] name = "jumpstarter-driver-ustreamer" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_driver_ustreamer" } dependencies = [ { name = "jumpstarter" }, @@ -1346,7 +1330,6 @@ requires-dist = [ [[package]] name = "jumpstarter-imagehash" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_imagehash" } dependencies = [ { name = "imagehash" }, @@ -1373,7 +1356,6 @@ dev = [ [[package]] name = "jumpstarter-kubernetes" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_kubernetes" } dependencies = [ { name = "jumpstarter" }, @@ -1406,7 +1388,6 @@ dev = [ [[package]] name = "jumpstarter-protocol" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_protocol" } dependencies = [ { name = "grpcio" }, @@ -1437,7 +1418,6 @@ dev = [ [[package]] name = "jumpstarter-testing" -version = "0.5.1.dev112+ge72cc41.d20250123" source = { editable = "packages/jumpstarter_testing" } dependencies = [ { name = "jumpstarter" }, From 10f7de52ddccfd30e48e5ce9ce7c9f40c3fd22b8 Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 13:29:23 -0500 Subject: [PATCH 06/16] Fix lint errors in examples --- .../test_on_rpi4.py | 5 ++-- examples/soc-pytest/pyproject.toml | 8 ++++-- uv.lock | 28 +++++++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/examples/soc-pytest/jumpstarter_example_soc_pytest/test_on_rpi4.py b/examples/soc-pytest/jumpstarter_example_soc_pytest/test_on_rpi4.py index 1221ad40b..a152883f3 100644 --- a/examples/soc-pytest/jumpstarter_example_soc_pytest/test_on_rpi4.py +++ b/examples/soc-pytest/jumpstarter_example_soc_pytest/test_on_rpi4.py @@ -6,10 +6,9 @@ import opendal import pexpect import pytest +from jumpstarter_driver_network.adapters import PexpectAdapter from jumpstarter_imagehash import ImageHash - -from jumpstarter.client.adapters import PexpectAdapter -from jumpstarter.testing.pytest import JumpstarterTest +from jumpstarter_testing.pytest import JumpstarterTest log = logging.getLogger(__file__) diff --git a/examples/soc-pytest/pyproject.toml b/examples/soc-pytest/pyproject.toml index 0919aaa39..50667b9a2 100644 --- a/examples/soc-pytest/pyproject.toml +++ b/examples/soc-pytest/pyproject.toml @@ -11,10 +11,12 @@ readme = "README.md" license = { text = "Apache-2.0" } requires-python = ">=3.11" dependencies = [ + "pytest>=8.3.2", "jumpstarter", - "pytest>=8.3.2", - "jumpstarter_imagehash", - "jumpstarter_driver_dutlink", + "jumpstarter-testing", + "jumpstarter-imagehash", + "jumpstarter-driver-network", + "jumpstarter-driver-dutlink" ] [tool.pytest.ini_options] diff --git a/uv.lock b/uv.lock index e33672d88..44a5dd795 100644 --- a/uv.lock +++ b/uv.lock @@ -737,6 +737,7 @@ wheels = [ [[package]] name = "jumpstarter" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter" } dependencies = [ { name = "aiohttp" }, @@ -783,6 +784,7 @@ dev = [ [[package]] name = "jumpstarter-cli" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_cli" } dependencies = [ { name = "jumpstarter-cli-admin" }, @@ -815,6 +817,7 @@ dev = [ [[package]] name = "jumpstarter-cli-admin" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_cli_admin" } dependencies = [ { name = "jumpstarter-cli-common" }, @@ -845,6 +848,7 @@ dev = [ [[package]] name = "jumpstarter-cli-client" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_cli_client" } dependencies = [ { name = "jumpstarter-cli-common" }, @@ -871,6 +875,7 @@ dev = [ [[package]] name = "jumpstarter-cli-common" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_cli_common" } dependencies = [ { name = "asyncclick" }, @@ -901,6 +906,7 @@ dev = [ [[package]] name = "jumpstarter-cli-exporter" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_cli_exporter" } dependencies = [ { name = "asyncclick" }, @@ -931,6 +937,7 @@ dev = [ [[package]] name = "jumpstarter-driver-can" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_driver_can" } dependencies = [ { name = "can-isotp" }, @@ -959,6 +966,7 @@ dev = [ [[package]] name = "jumpstarter-driver-composite" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_driver_composite" } dependencies = [ { name = "asyncclick" }, @@ -987,6 +995,7 @@ dev = [ [[package]] name = "jumpstarter-driver-dutlink" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_driver_dutlink" } dependencies = [ { name = "asyncclick" }, @@ -1061,6 +1070,7 @@ dev = [ [[package]] name = "jumpstarter-driver-network" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_driver_network" } dependencies = [ { name = "fabric" }, @@ -1093,6 +1103,7 @@ dev = [ [[package]] name = "jumpstarter-driver-opendal" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_driver_opendal" } dependencies = [ { name = "asyncclick" }, @@ -1121,6 +1132,7 @@ dev = [ [[package]] name = "jumpstarter-driver-power" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_driver_power" } dependencies = [ { name = "asyncclick" }, @@ -1151,6 +1163,7 @@ dev = [ [[package]] name = "jumpstarter-driver-pyserial" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_driver_pyserial" } dependencies = [ { name = "asyncclick" }, @@ -1181,6 +1194,7 @@ dev = [ [[package]] name = "jumpstarter-driver-raspberrypi" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_driver_raspberrypi" } dependencies = [ { name = "gpiozero" }, @@ -1207,6 +1221,7 @@ dev = [ [[package]] name = "jumpstarter-driver-sdwire" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_driver_sdwire" } dependencies = [ { name = "jumpstarter" }, @@ -1274,6 +1289,7 @@ dev = [ [[package]] name = "jumpstarter-driver-ustreamer" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_driver_ustreamer" } dependencies = [ { name = "jumpstarter" }, @@ -1320,6 +1336,11 @@ dependencies = [ { name = "pytest" }, ] +[package.dev-dependencies] +dev = [ + { name = "jumpstarter-testing" }, +] + [package.metadata] requires-dist = [ { name = "jumpstarter", editable = "packages/jumpstarter" }, @@ -1328,8 +1349,12 @@ requires-dist = [ { name = "pytest", specifier = ">=8.3.2" }, ] +[package.metadata.requires-dev] +dev = [{ name = "jumpstarter-testing", editable = "packages/jumpstarter_testing" }] + [[package]] name = "jumpstarter-imagehash" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_imagehash" } dependencies = [ { name = "imagehash" }, @@ -1356,6 +1381,7 @@ dev = [ [[package]] name = "jumpstarter-kubernetes" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_kubernetes" } dependencies = [ { name = "jumpstarter" }, @@ -1388,6 +1414,7 @@ dev = [ [[package]] name = "jumpstarter-protocol" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_protocol" } dependencies = [ { name = "grpcio" }, @@ -1418,6 +1445,7 @@ dev = [ [[package]] name = "jumpstarter-testing" +version = "0.5.1.dev113+g07bed5a.d20250123" source = { editable = "packages/jumpstarter_testing" } dependencies = [ { name = "jumpstarter" }, From ff1504c796342a8c9601e88940de3f7e9bc310d4 Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 13:31:38 -0500 Subject: [PATCH 07/16] Fix all ruff format errors --- .../jumpstarter/jumpstarter/client/lease.py | 6 +- .../jumpstarter/common/condition.py | 5 +- .../jumpstarter/jumpstarter/common/utils.py | 5 +- .../jumpstarter/config/__init__.py | 2 +- .../jumpstarter/jumpstarter/config/client.py | 7 +- .../jumpstarter/jumpstarter/config/env.py | 2 +- .../jumpstarter/config/exporter.py | 3 + .../jumpstarter/config/exporter_test.py | 2 +- .../jumpstarter_cli/__init__.py | 1 + .../jumpstarter_cli/cli_test.py | 1 + .../jumpstarter_cli_admin/__init__.py | 1 + .../jumpstarter_cli_admin/get.py | 2 + .../jumpstarter_cli_admin/import_res_test.py | 4 +- .../jumpstarter_cli_client/__init__.py | 1 + .../jumpstarter_cli_common/__init__.py | 2 +- .../jumpstarter_cli_common/alias.py | 7 +- .../jumpstarter_cli_common/opt.py | 29 ++---- .../jumpstarter_cli_common/table_test.py | 1 + .../jumpstarter_cli_exporter/__init__.py | 1 + .../jumpstarter_cli_exporter/exporter.py | 1 + .../jumpstarter_driver_http/client.py | 7 +- .../jumpstarter_driver_http/driver.py | 12 ++- .../jumpstarter_driver_http/driver_test.py | 5 + .../jumpstarter_driver_pyserial/console.py | 6 +- .../driver_test.py | 6 +- .../jumpstarter_driver_raspberrypi/driver.py | 2 +- .../driver_test.py | 1 + .../examples/tftp_test.py | 3 +- .../jumpstarter_driver_tftp/driver.py | 17 ++-- .../jumpstarter_driver_tftp/driver_test.py | 6 +- .../jumpstarter_driver_tftp/server.py | 92 +++++++++---------- .../jumpstarter_driver_tftp/server_test.py | 43 ++++----- .../jumpstarter_kubernetes/__init__.py | 2 +- packages/jumpstarter_testing/conftest.py | 1 + .../jumpstarter_testing/pytest.py | 51 +++++----- 35 files changed, 172 insertions(+), 165 deletions(-) diff --git a/packages/jumpstarter/jumpstarter/client/lease.py b/packages/jumpstarter/jumpstarter/client/lease.py index 1ec426df0..d7f66d492 100644 --- a/packages/jumpstarter/jumpstarter/client/lease.py +++ b/packages/jumpstarter/jumpstarter/client/lease.py @@ -26,7 +26,7 @@ class Lease(AbstractContextManager, AbstractAsyncContextManager): name: str | None = field(default=None) allow: list[str] unsafe: bool - release: bool = True # release on contexts exit + release: bool = True # release on contexts exit controller: jumpstarter_pb2_grpc.ControllerServiceStub = field(init=False) tls_config: TLSConfigV1Alpha1 = field(default_factory=TLSConfigV1Alpha1) @@ -53,7 +53,7 @@ def request(self): return self.portal.call(self.request_async) async def request_async(self): - """ Request a lease, or verifies a lease which was already created. + """Request a lease, or verifies a lease which was already created. :return: lease :rtype: Lease @@ -68,7 +68,7 @@ async def request_async(self): return await self._acquire() async def _acquire(self): - """ Acquire a lease. + """Acquire a lease. Makes sure the lease is ready, and returns the lease object. """ diff --git a/packages/jumpstarter/jumpstarter/common/condition.py b/packages/jumpstarter/jumpstarter/common/condition.py index 486e6a367..1fdb7c0ad 100644 --- a/packages/jumpstarter/jumpstarter/common/condition.py +++ b/packages/jumpstarter/jumpstarter/common/condition.py @@ -3,8 +3,9 @@ from jumpstarter_protocol import kubernetes_pb2 -def condition_present_and_equal(conditions: list[kubernetes_pb2.Condition], - condition_type: str, status: str, reason: str | None=None) -> bool: +def condition_present_and_equal( + conditions: list[kubernetes_pb2.Condition], condition_type: str, status: str, reason: str | None = None +) -> bool: for condition in conditions: if condition.type == condition_type: if reason is None or condition.reason == reason: diff --git a/packages/jumpstarter/jumpstarter/common/utils.py b/packages/jumpstarter/jumpstarter/common/utils.py index cb41d4bc7..d9908e0a1 100644 --- a/packages/jumpstarter/jumpstarter/common/utils.py +++ b/packages/jumpstarter/jumpstarter/common/utils.py @@ -23,7 +23,6 @@ async def serve_async(root_device: Driver, portal: BlockingPortal): client.close() - @contextmanager def serve(root_device: Driver): with start_blocking_portal() as portal: @@ -35,7 +34,7 @@ def serve(root_device: Driver): @asynccontextmanager async def env_async(portal): - """ Provide a client for an existing JUMPSTARTER_HOST environment variable. + """Provide a client for an existing JUMPSTARTER_HOST environment variable. Async version of env() @@ -56,7 +55,7 @@ async def env_async(portal): @contextmanager def env(): - """ Provide a client for an existing JUMPSTARTER_HOST environment variable. + """Provide a client for an existing JUMPSTARTER_HOST environment variable. This is useful when interacting with an already established Jumpstarter shell, to either a local exporter or a remote one. diff --git a/packages/jumpstarter/jumpstarter/config/__init__.py b/packages/jumpstarter/jumpstarter/config/__init__.py index e0d00a6f7..c81ab2f02 100644 --- a/packages/jumpstarter/jumpstarter/config/__init__.py +++ b/packages/jumpstarter/jumpstarter/config/__init__.py @@ -20,5 +20,5 @@ "ClientConfigV1Alpha1", "ClientConfigV1Alpha1Drivers", "ExporterConfigV1Alpha1", - "ExporterConfigV1Alpha1DriverInstance" + "ExporterConfigV1Alpha1DriverInstance", ] diff --git a/packages/jumpstarter/jumpstarter/config/client.py b/packages/jumpstarter/jumpstarter/config/client.py index 82096fb3f..6e8594e15 100644 --- a/packages/jumpstarter/jumpstarter/config/client.py +++ b/packages/jumpstarter/jumpstarter/config/client.py @@ -27,6 +27,7 @@ def _allow_from_env(): case _: return allow.split(","), False + class ClientConfigV1Alpha1Drivers(BaseModel): allow: list[str] = Field(default_factory=[]) unsafe: bool = Field(default=False) @@ -58,8 +59,7 @@ async def channel(self): @contextmanager def lease(self, metadata_filter: MetadataFilter, lease_name: str | None = None): with start_blocking_portal() as portal: - with portal.wrap_async_context_manager( - self.lease_async(metadata_filter, lease_name, portal)) as lease: + with portal.wrap_async_context_manager(self.lease_async(metadata_filter, lease_name, portal)) as lease: yield lease def request_lease(self, metadata_filter: MetadataFilter): @@ -74,9 +74,10 @@ def release_lease(self, name): with start_blocking_portal() as portal: portal.call(self.release_lease_async, name) - async def request_lease_async(self, metadata_filter: MetadataFilter, portal:BlockingPortal): + async def request_lease_async(self, metadata_filter: MetadataFilter, portal: BlockingPortal): # dynamically import to avoid circular imports from jumpstarter.client import Lease + lease = Lease( channel=await self.channel(), name=None, diff --git a/packages/jumpstarter/jumpstarter/config/env.py b/packages/jumpstarter/jumpstarter/config/env.py index 62c46f2eb..1cde72093 100644 --- a/packages/jumpstarter/jumpstarter/config/env.py +++ b/packages/jumpstarter/jumpstarter/config/env.py @@ -4,4 +4,4 @@ JMP_TOKEN = "JMP_TOKEN" JMP_DRIVERS_ALLOW = "JMP_DRIVERS_ALLOW" JUMPSTARTER_HOST = "JUMPSTARTER_HOST" -JMP_LEASE ="JMP_LEASE" +JMP_LEASE = "JMP_LEASE" diff --git a/packages/jumpstarter/jumpstarter/config/exporter.py b/packages/jumpstarter/jumpstarter/config/exporter.py index 5cbf0987a..46a4a2411 100644 --- a/packages/jumpstarter/jumpstarter/config/exporter.py +++ b/packages/jumpstarter/jumpstarter/config/exporter.py @@ -28,6 +28,7 @@ def instantiate(self) -> Driver: return driver_class(children=children, **self.config) + class ExporterConfigV1Alpha1(BaseModel): BASE_PATH: ClassVar[Path] = Path("/etc/jumpstarter/exporters") @@ -96,6 +97,7 @@ def delete(cls, alias: str): async def serve_unix_async(self): # dynamic import to avoid circular imports from jumpstarter.exporter import Session + with Session( root_device=ExporterConfigV1Alpha1DriverInstance(children=self.export).instantiate(), ) as session: @@ -111,6 +113,7 @@ def serve_unix(self): async def serve(self): # dynamic import to avoid circular imports from jumpstarter.exporter import Exporter + def channel_factory(): credentials = grpc.composite_channel_credentials( ssl_channel_credentials(self.endpoint, self.tls), diff --git a/packages/jumpstarter/jumpstarter/config/exporter_test.py b/packages/jumpstarter/jumpstarter/config/exporter_test.py index 41028437d..df0577f7f 100644 --- a/packages/jumpstarter/jumpstarter/config/exporter_test.py +++ b/packages/jumpstarter/jumpstarter/config/exporter_test.py @@ -141,7 +141,7 @@ def test_exporter_config(monkeypatch: pytest.MonkeyPatch, tmp_path: Path): ), }, config={}, - path=path + path=path, ) path.unlink() diff --git a/packages/jumpstarter_cli/jumpstarter_cli/__init__.py b/packages/jumpstarter_cli/jumpstarter_cli/__init__.py index 2f5da97d2..a32f07830 100644 --- a/packages/jumpstarter_cli/jumpstarter_cli/__init__.py +++ b/packages/jumpstarter_cli/jumpstarter_cli/__init__.py @@ -9,6 +9,7 @@ def jmp(): """The Jumpstarter CLI""" + jmp.add_command(client) jmp.add_command(exporter) jmp.add_command(admin) diff --git a/packages/jumpstarter_cli/jumpstarter_cli/cli_test.py b/packages/jumpstarter_cli/jumpstarter_cli/cli_test.py index 1a585ce36..51c9d5084 100644 --- a/packages/jumpstarter_cli/jumpstarter_cli/cli_test.py +++ b/packages/jumpstarter_cli/jumpstarter_cli/cli_test.py @@ -13,6 +13,7 @@ async def test_cli(): assert "exporter" in result.output assert "version" in result.output + @pytest.fixture def anyio_backend(): return "asyncio" diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/__init__.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/__init__.py index 1878b5469..7badfbcc7 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/__init__.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/__init__.py @@ -12,6 +12,7 @@ def admin(): """Jumpstarter Kubernetes cluster admin CLI tool""" + admin.add_command(get) admin.add_command(create) admin.add_command(delete) diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get.py index 0de9211fb..70cbfa510 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get.py @@ -152,6 +152,7 @@ async def get_exporter( LEASE_COLUMNS = ["NAME", "CLIENT", "SELECTOR", "EXPORTER", "STATUS", "REASON", "BEGIN", "END", "DURATION", "AGE"] + def get_reason(lease: V1Alpha1Lease): condition = lease.status.conditions[-1] if len(lease.status.conditions) > 0 else None reason = condition.reason if condition is not None else "Unknown" @@ -167,6 +168,7 @@ def get_reason(lease: V1Alpha1Lease): else: return "Complete" + def make_lease_row(lease: V1Alpha1Lease): selectors = [] for label in lease.spec.selector: diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py index e94539bd1..c124b5d99 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py @@ -95,9 +95,7 @@ async def test_import_client(_load_kube_config_mock, get_client_config_mock: Asy @patch.object(ExporterConfigV1Alpha1, "save") @patch.object(ExportersV1Alpha1Api, "get_exporter_config", return_value=EXPORTER_CONFIG) @patch.object(ExportersV1Alpha1Api, "_load_kube_config") -async def test_import_exporter( - _load_kube_config_mock, _get_exporter_config_mock, save_exporter_config_mock: Mock -): +async def test_import_exporter(_load_kube_config_mock, _get_exporter_config_mock, save_exporter_config_mock: Mock): runner = CliRunner() # Save with prompts diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py index 7812d3d8e..4338d2c99 100644 --- a/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py @@ -12,6 +12,7 @@ def client(): """Jumpstarter client CLI tool""" + def j(): with env() as client: client.cli()(standalone_mode=False) diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/__init__.py b/packages/jumpstarter_cli_common/jumpstarter_cli_common/__init__.py index 5ab756911..445a88c04 100644 --- a/packages/jumpstarter_cli_common/jumpstarter_cli_common/__init__.py +++ b/packages/jumpstarter_cli_common/jumpstarter_cli_common/__init__.py @@ -13,5 +13,5 @@ "opt_namespace", "time_since", "version", - "get_client_version" + "get_client_version", ] diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/alias.py b/packages/jumpstarter_cli_common/jumpstarter_cli_common/alias.py index 88c68a6a7..2d5e4391d 100644 --- a/packages/jumpstarter_cli_common/jumpstarter_cli_common/alias.py +++ b/packages/jumpstarter_cli_common/jumpstarter_cli_common/alias.py @@ -23,7 +23,7 @@ class AliasedGroup(click.Group): "exporter": ["exporters", "e"], "client": ["clients", "c"], "lease": ["leases", "l"], - "version": ["ver", "v"] + "version": ["ver", "v"], } def get_command(self, ctx: click.Context, cmd_name: str): @@ -31,8 +31,9 @@ def get_command(self, ctx: click.Context, cmd_name: str): if rv is not None: return rv # Match if listed in the common aliases - matches = [x for x in self.list_commands(ctx) - if x in self.common_aliases and cmd_name in self.common_aliases[x]] + matches = [ + x for x in self.list_commands(ctx) if x in self.common_aliases and cmd_name in self.common_aliases[x] + ] if not matches: return None elif len(matches) == 1: diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/opt.py b/packages/jumpstarter_cli_common/jumpstarter_cli_common/opt.py index cc33610f3..e4136d8d7 100644 --- a/packages/jumpstarter_cli_common/jumpstarter_cli_common/opt.py +++ b/packages/jumpstarter_cli_common/jumpstarter_cli_common/opt.py @@ -1,30 +1,17 @@ import asyncclick as click opt_log_level = click.option( - "-l", "--log-level", "log_level", - type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]), - help="Set the log level" + "-l", + "--log-level", + "log_level", + type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]), + help="Set the log level", ) opt_kubeconfig = click.option( - "--kubeconfig", "kubeconfig", - type=click.File(), - default=None, - help="path to the kubeconfig file" + "--kubeconfig", "kubeconfig", type=click.File(), default=None, help="path to the kubeconfig file" ) -opt_context = click.option( - "--context", - "context", - type=str, - default=None, - help="Kubernetes context to use" -) +opt_context = click.option("--context", "context", type=str, default=None, help="Kubernetes context to use") -opt_namespace = click.option( - "-n", - "--namespace", - type=str, - help="Kubernetes namespace to use", - default="default" -) +opt_namespace = click.option("-n", "--namespace", type=str, help="Kubernetes namespace to use", default="default") diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/table_test.py b/packages/jumpstarter_cli_common/jumpstarter_cli_common/table_test.py index c4798eab7..41efd2d87 100644 --- a/packages/jumpstarter_cli_common/jumpstarter_cli_common/table_test.py +++ b/packages/jumpstarter_cli_common/jumpstarter_cli_common/table_test.py @@ -2,6 +2,7 @@ EXPECTED_TABLE = "TEST HELLO \n123456 There " + def test_make_table(): COLUMNS = ["TEST", "HELLO"] DATA = [{"TEST": "123456", "HELLO": "There"}] diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/__init__.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/__init__.py index e75d71678..8d2c06d3e 100644 --- a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/__init__.py +++ b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/__init__.py @@ -17,6 +17,7 @@ def exporter(log_level: Optional[str]): else: logging.basicConfig(level=logging.INFO) + exporter.add_command(create_exporter_config) exporter.add_command(delete_exporter_config) exporter.add_command(edit_exporter_config) diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py index 945587535..e35b8cdf6 100644 --- a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py +++ b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py @@ -41,6 +41,7 @@ async def run_exporter(alias, config_path): return await _serve_with_exc_handling(config) + @click.command("shell") @arg_alias @opt_config_path diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py index 6ee1f29ba..e541f3a90 100644 --- a/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py @@ -68,12 +68,7 @@ def put_local_file(self, filepath: str) -> str: >>> client.put_local_file("/path/to/local/file.txt") """ absolute = Path(filepath).resolve() - with OpendalAdapter( - client=self, - operator=Operator("fs", root="/"), - path=str(absolute), - mode="rb" - ) as handle: + with OpendalAdapter(client=self, operator=Operator("fs", root="/"), path=str(absolute), mode="rb") as handle: return self.call("put_file", absolute.name, handle) def delete_file(self, filename: str) -> str: diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py index 060e1a5a9..5b7774aa7 100644 --- a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py @@ -48,9 +48,11 @@ class HttpServer(Driver): def __post_init__(self): super().__post_init__() os.makedirs(self.root_dir, exist_ok=True) - self.app.router.add_routes([ - web.get('/{filename}', self.get_file), - ]) + self.app.router.add_routes( + [ + web.get("/{filename}", self.get_file), + ] + ) @classmethod def client(cls) -> str: @@ -129,7 +131,7 @@ async def get_file(self, request) -> web.FileResponse: Raises: web.HTTPNotFound: If the requested file does not exist. """ - filename = request.match_info['filename'] + filename = request.match_info["filename"] file_path = os.path.join(self.root_dir, filename) if not os.path.isfile(file_path): logger.warning(f"File not found: {file_path}") @@ -170,7 +172,7 @@ async def start(self): self.runner = web.AppRunner(self.app) if self.runner: - await self.runner.setup() + await self.runner.setup() site = web.TCPSite(self.runner, self.host, self.port) await site.start() diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py index 2a47da734..7a221544c 100644 --- a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py @@ -16,11 +16,13 @@ def anyio_backend(): return "asyncio" + @pytest.fixture def temp_dir(): with TemporaryDirectory() as tmpdir: yield tmpdir + @pytest.fixture async def server(temp_dir): server = HttpServer(root_dir=temp_dir) @@ -30,6 +32,7 @@ async def server(temp_dir): finally: await server.stop() + @pytest.mark.anyio async def test_http_server(server): filename = "test.txt" @@ -67,11 +70,13 @@ async def send_data(): files_after_deletion = server.list_files() assert filename not in files_after_deletion + def test_http_server_host_config(temp_dir): custom_host = "192.168.1.1" server = HttpServer(root_dir=temp_dir, host=custom_host) assert server.get_host() == custom_host + def test_http_server_root_directory_creation(temp_dir): new_dir = os.path.join(temp_dir, "new_http_root") _ = HttpServer(root_dir=new_dir) diff --git a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/console.py b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/console.py index 6934d440c..a022c0df7 100644 --- a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/console.py +++ b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/console.py @@ -1,4 +1,3 @@ - import os import sys import termios @@ -9,7 +8,7 @@ class Console: - def __init__(self, serial_client:DriverClient): + def __init__(self, serial_client: DriverClient): self.serial_client = serial_client def run(self): @@ -28,7 +27,7 @@ def _run(self, stream): data = sys.stdin.buffer.read(1) if not data: continue - if data == b"\x02": # Ctrl-B + if data == b"\x02": # Ctrl-B ctrl_b_count += 1 if ctrl_b_count == 3: return @@ -51,4 +50,3 @@ def _copy_serial_to_stdout(self): sys.stdout.flush() finally: self._reset_terminal() - diff --git a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver_test.py b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver_test.py index 141000a20..87bf09872 100644 --- a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver_test.py +++ b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver_test.py @@ -12,6 +12,7 @@ def test_bare_pyserial(): stream.send(b"hello") assert "hello".startswith(stream.receive().decode("utf-8")) + def test_bare_open_pyserial(): with serve(PySerial(url="loop://")) as client: client = cast(PySerialClient, client) @@ -20,13 +21,15 @@ def test_bare_open_pyserial(): assert "hello".startswith(stream.receive().decode("utf-8")) client.close() + def test_pexpect_open_pyserial_forget_close(): with serve(PySerial(url="loop://")) as client: - client = cast(PySerialClient, client) # this is only necessary for the editor to recognize the client methods + client = cast(PySerialClient, client) # this is only necessary for the editor to recognize the client methods pexpect = client.open() pexpect.sendline("hello") assert pexpect.expect("hello") == 0 + def test_pexpect_open_pyserial(): with serve(PySerial(url="loop://")) as client: client = cast(PySerialClient, client) @@ -35,6 +38,7 @@ def test_pexpect_open_pyserial(): assert pexpect.expect("hello") == 0 client.close() + def test_pexpect_context_pyserial(): with serve(PySerial(url="loop://")) as client: client = cast(PySerialClient, client) diff --git a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py index 4489f1ecb..20c4a0cbe 100644 --- a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py +++ b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py @@ -20,7 +20,7 @@ def __post_init__(self): self.device = InputDevice(pin=self.pin) def close(self): - if hasattr(self, 'device'): + if hasattr(self, "device"): self.device.close() super().close() diff --git a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py index 79575ef90..de71d989e 100644 --- a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py +++ b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py @@ -31,6 +31,7 @@ def test_drivers_gpio_digital_output(): mock_pin.assert_states([False, True, False]) + def test_drivers_gpio_digital_input(): instance = DigitalInput(pin=4) diff --git a/packages/jumpstarter_driver_tftp/examples/tftp_test.py b/packages/jumpstarter_driver_tftp/examples/tftp_test.py index 4cd33831e..ba7b7067b 100644 --- a/packages/jumpstarter_driver_tftp/examples/tftp_test.py +++ b/packages/jumpstarter_driver_tftp/examples/tftp_test.py @@ -7,8 +7,9 @@ log = logging.getLogger(__name__) + class TestResource(JumpstarterTest): - filter_labels = {"board":"rpi4"} + filter_labels = {"board": "rpi4"} @pytest.fixture() def test_tftp_upload(self, client): diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py index bd4fb7580..465d5d0e5 100644 --- a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py @@ -14,6 +14,7 @@ logger = logging.getLogger(__name__) + def get_default_ip(): """Get the IP address of the default route interface""" try: @@ -24,18 +25,25 @@ def get_default_ip(): logger.warning("Could not determine default IP address, falling back to 0.0.0.0") return "0.0.0.0" + class TftpError(Exception): """Base exception for TFTP server errors""" + pass + class ServerNotRunning(TftpError): """Server is not running""" + pass + class FileNotFound(TftpError): """File not found""" + pass + @dataclass(kw_only=True) class Tftp(Driver): """TFTP Server driver for Jumpstarter""" @@ -43,7 +51,7 @@ class Tftp(Driver): root_dir: str = "/var/lib/tftpboot" host: str = field(default_factory=get_default_ip) port: int = 69 - server: Optional['TftpServer'] = field(init=False, default=None) + server: Optional["TftpServer"] = field(init=False, default=None) server_thread: Optional[threading.Thread] = field(init=False, default=None) _shutdown_event: threading.Event = field(init=False, default_factory=threading.Event) _loop_ready: threading.Event = field(init=False, default_factory=threading.Event) @@ -82,10 +90,7 @@ def _start_server(self): async def _run_server(self): try: server_task = asyncio.create_task(self.server.start()) - await asyncio.gather( - server_task, - self._wait_for_shutdown() - ) + await asyncio.gather(server_task, self._wait_for_shutdown()) except asyncio.CancelledError: logger.info("Server task cancelled") raise @@ -95,7 +100,7 @@ async def _wait_for_shutdown(self): await asyncio.sleep(0.1) logger.info("Shutdown event detected") if self.server is not None: - await self.server.shutdown() + await self.server.shutdown() @export def start(self): diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py index 7cb9f2964..733130cc3 100644 --- a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py @@ -19,12 +19,14 @@ def temp_dir(): with tempfile.TemporaryDirectory() as tmpdir: yield tmpdir + @pytest.fixture def server(temp_dir): server = Tftp(root_dir=temp_dir, host="127.0.0.1") yield server server.close() + @pytest.mark.anyio async def test_tftp_file_operations(server): filename = "test.txt" @@ -64,12 +66,14 @@ def test_tftp_host_config(temp_dir): server = Tftp(root_dir=temp_dir, host=custom_host) assert server.get_host() == custom_host + def test_tftp_root_directory_creation(temp_dir): new_dir = os.path.join(temp_dir, "new_tftp_root") server = Tftp(root_dir=new_dir) assert os.path.exists(new_dir) server.close() + @pytest.fixture def anyio_backend(): - return 'asyncio' + return "asyncio" diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py index d602c0615..f10fb69db 100644 --- a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py @@ -32,18 +32,19 @@ class TftpServer: TFTP Server that handles read requests (RRQ). """ - def __init__(self, host: str, port: int, root_dir: str, - block_size: int = 512, timeout: float = 5.0, retries: int = 3): + def __init__( + self, host: str, port: int, root_dir: str, block_size: int = 512, timeout: float = 5.0, retries: int = 3 + ): self.host = host self.port = port self.root_dir = pathlib.Path(os.path.abspath(root_dir)) self.block_size = block_size self.timeout = timeout self.retries = retries - self.active_transfers: Set['TftpTransfer'] = set() + self.active_transfers: Set["TftpTransfer"] = set() self.shutdown_event = asyncio.Event() self.transport: Optional[asyncio.DatagramTransport] = None - self.protocol: Optional['TftpServerProtocol'] = None + self.protocol: Optional["TftpServerProtocol"] = None self.logger = logging.getLogger(self.__class__.__name__) async def start(self): @@ -51,8 +52,7 @@ async def start(self): loop = asyncio.get_running_loop() self.transport, self.protocol = await loop.create_datagram_endpoint( - lambda: TftpServerProtocol(self), - local_addr=(self.host, self.port) + lambda: TftpServerProtocol(self), local_addr=(self.host, self.port) ) try: @@ -82,11 +82,11 @@ async def shutdown(self): self.logger.info("Shutdown signal received for TFTP server") self.shutdown_event.set() - def register_transfer(self, transfer: 'TftpTransfer'): + def register_transfer(self, transfer: "TftpTransfer"): self.active_transfers.add(transfer) self.logger.debug(f"Registered transfer: {transfer}") - def unregister_transfer(self, transfer: 'TftpTransfer'): + def unregister_transfer(self, transfer: "TftpTransfer"): self.active_transfers.discard(transfer) self.logger.debug(f"Unregistered transfer: {transfer}") @@ -120,7 +120,7 @@ def datagram_received(self, data: bytes, addr: Tuple[str, int]): return try: - opcode = Opcode(int.from_bytes(data[0:2], 'big')) + opcode = Opcode(int.from_bytes(data[0:2], "big")) except ValueError: self.logger.error(f"Unknown opcode from {addr}") self._send_error(addr, TftpErrorCode.ILLEGAL_OPERATION, "Unknown opcode") @@ -137,17 +137,17 @@ def datagram_received(self, data: bytes, addr: Tuple[str, int]): async def _handle_read_request(self, data: bytes, addr: Tuple[str, int]): try: # Parse filename and mode from request - parts = data[2:].split(b'\x00') + parts = data[2:].split(b"\x00") if len(parts) < 2: self.logger.error(f"Invalid RRQ format from {addr}") raise ValueError("Invalid RRQ format") - filename = parts[0].decode('utf-8') - mode = parts[1].decode('utf-8').lower() + filename = parts[0].decode("utf-8") + mode = parts[1].decode("utf-8").lower() self.logger.info(f"RRQ from {addr}: '{filename}' in mode '{mode}'") - if mode not in ('netascii', 'octet'): + if mode not in ("netascii", "octet"): self.logger.warning(f"Unsupported transfer mode '{mode}' from {addr}") self._send_error(addr, TftpErrorCode.ILLEGAL_OPERATION, "Unsupported transfer mode") return @@ -172,7 +172,7 @@ async def _handle_read_request(self, data: bytes, addr: Tuple[str, int]): client_addr=addr, block_size=self.server.block_size, timeout=self.server.timeout, - retries=self.server.retries + retries=self.server.retries, ) self.server.register_transfer(transfer) asyncio.create_task(transfer.start()) @@ -183,9 +183,7 @@ async def _handle_read_request(self, data: bytes, addr: Tuple[str, int]): def _send_error(self, addr: Tuple[str, int], error_code: TftpErrorCode, message: str): error_packet = ( - Opcode.ERROR.to_bytes(2, 'big') + - error_code.to_bytes(2, 'big') + - message.encode('utf-8') + b'\x00' + Opcode.ERROR.to_bytes(2, "big") + error_code.to_bytes(2, "big") + message.encode("utf-8") + b"\x00" ) if self.transport: self.transport.sendto(error_packet, addr) @@ -205,8 +203,15 @@ class TftpTransfer: Base class for TFTP transfers. """ - def __init__(self, server: TftpServer, filepath: pathlib.Path, client_addr: Tuple[str, int], - block_size: int, timeout: float, retries: int): + def __init__( + self, + server: TftpServer, + filepath: pathlib.Path, + client_addr: Tuple[str, int], + block_size: int, + timeout: float, + retries: int, + ): self.server = server self.filepath = filepath self.client_addr = client_addr @@ -214,7 +219,7 @@ def __init__(self, server: TftpServer, filepath: pathlib.Path, client_addr: Tupl self.timeout = timeout self.retries = retries self.transport: Optional[asyncio.DatagramTransport] = None - self.protocol: Optional['TftpTransferProtocol'] = None + self.protocol: Optional["TftpTransferProtocol"] = None self.cleanup_task: Optional[asyncio.Task] = None self.logger = logging.getLogger(self.__class__.__name__) @@ -236,8 +241,15 @@ class TftpReadTransfer(TftpTransfer): Handles a TFTP Read (RRQ) transfer. """ - def __init__(self, server: TftpServer, filepath: pathlib.Path, client_addr: Tuple[str, int], - block_size: int, timeout: float, retries: int): + def __init__( + self, + server: TftpServer, + filepath: pathlib.Path, + client_addr: Tuple[str, int], + block_size: int, + timeout: float, + retries: int, + ): super().__init__(server, filepath, client_addr, block_size, timeout, retries) self.block_num = 1 self.ack_received = asyncio.Event() @@ -248,26 +260,20 @@ async def start(self): loop = asyncio.get_running_loop() self.transport, self.protocol = await loop.create_datagram_endpoint( - lambda: TftpTransferProtocol(self), - local_addr=('0.0.0.0', 0), - remote_addr=self.client_addr + lambda: TftpTransferProtocol(self), local_addr=("0.0.0.0", 0), remote_addr=self.client_addr ) - local_addr = self.transport.get_extra_info('sockname') + local_addr = self.transport.get_extra_info("sockname") self.logger.debug(f"Transfer bound to local {local_addr}") try: - async with aiofiles.open(self.filepath, 'rb') as f: + async with aiofiles.open(self.filepath, "rb") as f: while True: if self.server.shutdown_event.is_set(): self.logger.info(f"Server shutdown detected, stopping transfer to {self.client_addr}") break data = await f.read(self.block_size) if data: - packet = ( - Opcode.DATA.to_bytes(2, 'big') + - self.block_num.to_bytes(2, 'big') + - data - ) + packet = Opcode.DATA.to_bytes(2, "big") + self.block_num.to_bytes(2, "big") + data success = await self._send_with_retries(packet) if not success: self.logger.error(f"Failed to send block {self.block_num} to {self.client_addr}") @@ -282,16 +288,11 @@ async def start(self): else: # If no data is returned, it means the file size is an exact multiple of block_size # Send an extra empty DATA packet to signal end of transfer - packet = ( - Opcode.DATA.to_bytes(2, 'big') + - self.block_num.to_bytes(2, 'big') + - b'' - ) + packet = Opcode.DATA.to_bytes(2, "big") + self.block_num.to_bytes(2, "big") + b"" success = await self._send_with_retries(packet) if not success: self.logger.error( - f"Failed to send final empty block {self.block_num} " - f"to {self.client_addr}" + f"Failed to send final empty block {self.block_num} " f"to {self.client_addr}" ) break self.logger.info(f"Transfer complete to {self.client_addr}, final block {self.block_num}") @@ -327,7 +328,7 @@ def _send_packet(self, packet: bytes): Sends a DATA packet to the client. """ self.transport.sendto(packet) - block = int.from_bytes(packet[2:4], 'big') + block = int.from_bytes(packet[2:4], "big") data_length = len(packet) - 4 self.logger.debug(f"Sent DATA block {block} ({data_length} bytes) to {self.client_addr}") @@ -343,6 +344,7 @@ def handle_ack(self, block_num: int): else: self.logger.warning(f"Out of sequence ACK: expected {self.block_num}, got {block_num}") + class TftpTransferProtocol(asyncio.DatagramProtocol): """ Protocol for handling ACKs during a TFTP transfer. @@ -354,7 +356,7 @@ def __init__(self, transfer: TftpReadTransfer): def connection_made(self, transport: asyncio.DatagramTransport): self.transfer.transport = transport - local_addr = transport.get_extra_info('sockname') + local_addr = transport.get_extra_info("sockname") self.logger.debug(f"Transfer protocol connection established on {local_addr} for {self.transfer.client_addr}") def datagram_received(self, data: bytes, addr: Tuple[str, int]): @@ -368,7 +370,7 @@ def datagram_received(self, data: bytes, addr: Tuple[str, int]): return try: - opcode = Opcode(int.from_bytes(data[0:2], 'big')) + opcode = Opcode(int.from_bytes(data[0:2], "big")) except ValueError: self.logger.error(f"Unknown opcode in ACK from {addr}") self._send_error(addr, TftpErrorCode.ILLEGAL_OPERATION, "Unknown opcode in ACK") @@ -379,7 +381,7 @@ def datagram_received(self, data: bytes, addr: Tuple[str, int]): self._send_error(addr, TftpErrorCode.ILLEGAL_OPERATION, "Expected ACK") return - block_num = int.from_bytes(data[2:4], 'big') + block_num = int.from_bytes(data[2:4], "big") self.logger.debug(f"Received ACK for block {block_num} from {addr}") self.transfer.handle_ack(block_num) @@ -391,9 +393,7 @@ def connection_lost(self, exc): def _send_error(self, addr: Tuple[str, int], error_code: TftpErrorCode, message: str): error_packet = ( - Opcode.ERROR.to_bytes(2, 'big') + - error_code.to_bytes(2, 'big') + - message.encode('utf-8') + b'\x00' + Opcode.ERROR.to_bytes(2, "big") + error_code.to_bytes(2, "big") + message.encode("utf-8") + b"\x00" ) if self.transfer.transport: self.transfer.transport.sendto(error_packet) diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server_test.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server_test.py index 488fd9f98..6ffa44534 100644 --- a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server_test.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server_test.py @@ -14,25 +14,22 @@ async def tftp_server(): test_file_path = Path(temp_dir) / "test.txt" test_file_path.write_text("Hello, TFTP!") - server = TftpServer( - host="127.0.0.1", - port=0, - root_dir=temp_dir - ) + server = TftpServer(host="127.0.0.1", port=0, root_dir=temp_dir) yield server, temp_dir await server.shutdown() + async def create_test_client(server_port): """Helper function to create a test UDP client.""" loop = asyncio.get_running_loop() transport, protocol = await loop.create_datagram_endpoint( - asyncio.DatagramProtocol, - remote_addr=('127.0.0.1', server_port) + asyncio.DatagramProtocol, remote_addr=("127.0.0.1", server_port) ) return transport, protocol + @pytest.mark.anyio async def test_server_startup_and_shutdown(tftp_server): """Test that server starts up and shuts down cleanly.""" @@ -48,6 +45,7 @@ async def test_server_startup_and_shutdown(tftp_server): assert True + @pytest.mark.anyio async def test_read_request_for_existing_file(tftp_server): """Test reading an existing file from the server.""" @@ -60,9 +58,9 @@ async def test_read_request_for_existing_file(tftp_server): transport, _ = await create_test_client(server.port) rrq_packet = ( - Opcode.RRQ.to_bytes(2, 'big') + - b'test.txt\x00' + # Filename - b'octet\x00' # Mode + Opcode.RRQ.to_bytes(2, "big") + + b"test.txt\x00" # Filename + + b"octet\x00" # Mode ) transport.sendto(rrq_packet) @@ -75,6 +73,7 @@ async def test_read_request_for_existing_file(tftp_server): await server.shutdown() await server_task + @pytest.mark.anyio async def test_read_request_for_nonexistent_file(tftp_server): """Test reading a non-existent file returns appropriate error.""" @@ -86,11 +85,7 @@ async def test_read_request_for_nonexistent_file(tftp_server): try: transport, protocol = await create_test_client(server.port) - rrq_packet = ( - Opcode.RRQ.to_bytes(2, 'big') + - b'nonexistent.txt\x00' + - b'octet\x00' - ) + rrq_packet = Opcode.RRQ.to_bytes(2, "big") + b"nonexistent.txt\x00" + b"octet\x00" transport.sendto(rrq_packet) await asyncio.sleep(0.1) @@ -102,6 +97,7 @@ async def test_read_request_for_nonexistent_file(tftp_server): await server.shutdown() await server_task + @pytest.mark.anyio async def test_write_request_rejection(tftp_server): """Test that write requests are properly rejected (server is read-only).""" @@ -111,11 +107,7 @@ async def test_write_request_rejection(tftp_server): try: transport, _ = await create_test_client(server.port) - wrq_packet = ( - Opcode.WRQ.to_bytes(2, 'big') + - b'test.txt\x00' + - b'octet\x00' - ) + wrq_packet = Opcode.WRQ.to_bytes(2, "big") + b"test.txt\x00" + b"octet\x00" transport.sendto(wrq_packet) await asyncio.sleep(0.1) @@ -127,6 +119,7 @@ async def test_write_request_rejection(tftp_server): await server.shutdown() await server_task + @pytest.mark.anyio async def test_invalid_packet_handling(tftp_server): server, _ = tftp_server @@ -135,7 +128,7 @@ async def test_invalid_packet_handling(tftp_server): try: transport, _ = await create_test_client(server.port) - transport.sendto(b'\x00\x01') + transport.sendto(b"\x00\x01") await asyncio.sleep(0.1) assert server.transport is not None @@ -145,6 +138,7 @@ async def test_invalid_packet_handling(tftp_server): await server.shutdown() await server_task + @pytest.mark.anyio async def test_path_traversal_prevention(tftp_server): """Test that path traversal attempts are blocked.""" @@ -156,11 +150,7 @@ async def test_path_traversal_prevention(tftp_server): try: transport, _ = await create_test_client(server.port) - rrq_packet = ( - Opcode.RRQ.to_bytes(2, 'big') + - b'../../../etc/passwd\x00' + - b'octet\x00' - ) + rrq_packet = Opcode.RRQ.to_bytes(2, "big") + b"../../../etc/passwd\x00" + b"octet\x00" transport.sendto(rrq_packet) await asyncio.sleep(0.1) @@ -172,6 +162,7 @@ async def test_path_traversal_prevention(tftp_server): await server.shutdown() await server_task + @pytest.fixture def anyio_backend(): return "asyncio" diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/__init__.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/__init__.py index 9ec397ccb..f1612ea21 100644 --- a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/__init__.py +++ b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/__init__.py @@ -17,5 +17,5 @@ "V1Alpha1LeaseSpec", "get_ip_address", "helm_installed", - "install_helm_chart" + "install_helm_chart", ] diff --git a/packages/jumpstarter_testing/conftest.py b/packages/jumpstarter_testing/conftest.py index 9fd31378a..4d2c99857 100644 --- a/packages/jumpstarter_testing/conftest.py +++ b/packages/jumpstarter_testing/conftest.py @@ -2,6 +2,7 @@ pytest_plugins = ["pytester"] + @pytest.fixture def anyio_backend(): return "asyncio" diff --git a/packages/jumpstarter_testing/jumpstarter_testing/pytest.py b/packages/jumpstarter_testing/jumpstarter_testing/pytest.py index a841ba7bb..7d3908c8d 100644 --- a/packages/jumpstarter_testing/jumpstarter_testing/pytest.py +++ b/packages/jumpstarter_testing/jumpstarter_testing/pytest.py @@ -10,41 +10,42 @@ log = logging.getLogger(__name__) + class JumpstarterTest: - """ Base class for Jumpstarter test cases in pytest + """Base class for Jumpstarter test cases in pytest -This class provides a client fixture that can be used to interact with -Jumpstarter services in test cases. + This class provides a client fixture that can be used to interact with + Jumpstarter services in test cases. -Looks for the `JUMPSTARTER_HOST` environment variable to connect to an -established Jumpstarter shell, otherwise it will try to acquire a lease -for a single exporter using the filter_labels annotation. -i.e.: + Looks for the `JUMPSTARTER_HOST` environment variable to connect to an + established Jumpstarter shell, otherwise it will try to acquire a lease + for a single exporter using the filter_labels annotation. + i.e.: -.. code-block:: python + .. code-block:: python - import os - import pytest - import logging + import os + import pytest + import logging - from jumpstarter_testing.pytest import JumpstarterTest + from jumpstarter_testing.pytest import JumpstarterTest - log = logging.getLogger(__name__) + log = logging.getLogger(__name__) - class TestResource(JumpstarterTest): - filter_labels = {"board":"rpi4"} + class TestResource(JumpstarterTest): + filter_labels = {"board":"rpi4"} - @pytest.fixture() - def console(self, client): - with PexpectAdapter(client=client.dutlink.console) as console: - yield console + @pytest.fixture() + def console(self, client): + with PexpectAdapter(client=client.dutlink.console) as console: + yield console - def test_setup_device(self, client, console): - client.dutlink.power.off() - log.info("Setting up device") - client.dutlink.storage.write_local_file("2024-07-04-raspios-bookworm-arm64-lite.img") - client.dutlink.storage.dut() - client.dutlink.power.on() + def test_setup_device(self, client, console): + client.dutlink.power.off() + log.info("Setting up device") + client.dutlink.storage.write_local_file("2024-07-04-raspios-bookworm-arm64-lite.img") + client.dutlink.storage.dut() + client.dutlink.power.on() """ From 03d793211ee26e62a722fa7d8b43abb2fbeb7966 Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 13:35:26 -0500 Subject: [PATCH 08/16] Fix import ordering (per ruff) --- packages/jumpstarter/conftest.py | 3 +-- packages/jumpstarter/jumpstarter/client/base.py | 3 +-- packages/jumpstarter/jumpstarter/client/client.py | 3 +-- packages/jumpstarter/jumpstarter/client/core.py | 3 +-- packages/jumpstarter/jumpstarter/client/lease.py | 3 +-- .../jumpstarter/jumpstarter/common/streams.py | 5 ++--- packages/jumpstarter/jumpstarter/common/utils.py | 1 - packages/jumpstarter/jumpstarter/config/client.py | 5 ++--- .../jumpstarter/config/client_config_test.py | 3 +-- .../jumpstarter/jumpstarter/config/exporter.py | 3 +-- .../jumpstarter/config/exporter_test.py | 1 - .../jumpstarter/config/user_config_test.py | 1 - packages/jumpstarter/jumpstarter/driver/base.py | 7 +++---- .../jumpstarter/jumpstarter/exporter/exporter.py | 9 ++++----- .../jumpstarter/jumpstarter/exporter/session.py | 9 ++++----- packages/jumpstarter/jumpstarter/listener_test.py | 3 +-- .../jumpstarter_cli_admin/create.py | 3 +-- .../jumpstarter_cli_admin/create_test.py | 11 +++++------ .../jumpstarter_cli_admin/delete.py | 3 +-- .../jumpstarter_cli_admin/delete_test.py | 15 +++++++-------- .../jumpstarter_cli_admin/import_res.py | 11 +++++------ .../jumpstarter_cli_admin/import_res_test.py | 9 ++++----- .../jumpstarter_cli_client/__init__.py | 3 +-- .../jumpstarter_cli_client/client_config.py | 3 +-- .../jumpstarter_cli_client/client_shell.py | 1 - .../jumpstarter_cli_client/client_test.py | 1 - .../jumpstarter_cli_client/lease.py | 3 +-- .../jumpstarter_cli_exporter/exporter.py | 1 - .../jumpstarter_cli_exporter/exporter_config.py | 3 +-- .../jumpstarter_cli_exporter/exporter_test.py | 1 - .../jumpstarter_driver_can/client.py | 3 +-- .../jumpstarter_driver_can/client_test.py | 2 +- .../jumpstarter_driver_can/driver.py | 3 +-- .../jumpstarter_driver_composite/client.py | 1 - .../jumpstarter_driver_composite/driver.py | 3 +-- .../jumpstarter_driver_composite/driver_test.py | 3 +-- .../examples/dutlink.py | 3 +-- .../jumpstarter_driver_dutlink/driver.py | 3 +-- .../jumpstarter_driver_dutlink/driver_test.py | 2 +- .../jumpstarter_driver_http/client.py | 3 +-- .../jumpstarter_driver_http/driver.py | 1 - .../jumpstarter_driver_http/driver_test.py | 1 - .../adapters/fabric_test.py | 3 +-- .../adapters/novnc_test.py | 3 +-- .../jumpstarter_driver_network/driver.py | 1 - .../jumpstarter_driver_network/driver_test.py | 1 - .../jumpstarter_driver_opendal/adapter.py | 5 ++--- .../jumpstarter_driver_opendal/client.py | 3 +-- .../jumpstarter_driver_opendal/driver.py | 1 - .../jumpstarter_driver_opendal/driver_test.py | 3 +-- .../jumpstarter_driver_power/client.py | 1 - .../jumpstarter_driver_pyserial/client.py | 3 +-- .../jumpstarter_driver_pyserial/driver.py | 3 +-- .../jumpstarter_driver_raspberrypi/driver.py | 1 - .../jumpstarter_driver_raspberrypi/driver_test.py | 2 +- .../jumpstarter_driver_sdwire/driver.py | 3 +-- .../jumpstarter_driver_sdwire/driver_test.py | 2 +- .../jumpstarter_driver_tftp/client.py | 3 +-- .../jumpstarter_driver_tftp/driver.py | 2 +- .../jumpstarter_driver_tftp/driver_test.py | 2 +- .../jumpstarter_driver_ustreamer/client.py | 3 +-- .../jumpstarter_driver_ustreamer/driver.py | 1 - .../jumpstarter_driver_ustreamer/driver_test.py | 2 +- .../jumpstarter_imagehash/imagehash.py | 3 +-- .../jumpstarter_kubernetes/clients.py | 3 +-- .../jumpstarter_kubernetes/exporters.py | 3 +-- .../jumpstarter_testing/pytest.py | 1 - .../jumpstarter_testing/pytest_test.py | 5 ++--- 68 files changed, 80 insertions(+), 141 deletions(-) diff --git a/packages/jumpstarter/conftest.py b/packages/jumpstarter/conftest.py index 91a57bc36..159b28ab1 100644 --- a/packages/jumpstarter/conftest.py +++ b/packages/jumpstarter/conftest.py @@ -14,6 +14,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import rsa +from jumpstarter.streams import RouterStream, forward_stream from jumpstarter_protocol import ( jumpstarter_pb2, jumpstarter_pb2_grpc, @@ -21,8 +22,6 @@ router_pb2_grpc, ) -from jumpstarter.streams import RouterStream, forward_stream - @dataclass(kw_only=True) class MockRouter(router_pb2_grpc.RouterServiceServicer): diff --git a/packages/jumpstarter/jumpstarter/client/base.py b/packages/jumpstarter/jumpstarter/client/base.py index 5b4e7cfd1..22f236447 100644 --- a/packages/jumpstarter/jumpstarter/client/base.py +++ b/packages/jumpstarter/jumpstarter/client/base.py @@ -8,11 +8,10 @@ from dataclasses import field from anyio.from_thread import BlockingPortal +from jumpstarter.streams import BlockingStream from pydantic import ConfigDict from pydantic.dataclasses import dataclass -from jumpstarter.streams import BlockingStream - from .core import AsyncDriverClient diff --git a/packages/jumpstarter/jumpstarter/client/client.py b/packages/jumpstarter/jumpstarter/client/client.py index 3eec9033b..257dd6b71 100644 --- a/packages/jumpstarter/jumpstarter/client/client.py +++ b/packages/jumpstarter/jumpstarter/client/client.py @@ -6,10 +6,9 @@ from anyio.from_thread import BlockingPortal from google.protobuf import empty_pb2 from graphlib import TopologicalSorter -from jumpstarter_protocol import jumpstarter_pb2_grpc - from jumpstarter.client import DriverClient from jumpstarter.common.importlib import import_class +from jumpstarter_protocol import jumpstarter_pb2_grpc @asynccontextmanager diff --git a/packages/jumpstarter/jumpstarter/client/core.py b/packages/jumpstarter/jumpstarter/client/core.py index 193d1e492..f7deaae52 100644 --- a/packages/jumpstarter/jumpstarter/client/core.py +++ b/packages/jumpstarter/jumpstarter/client/core.py @@ -7,8 +7,6 @@ from grpc import StatusCode from grpc.aio import AioRpcError, Channel -from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc - from jumpstarter.common import Metadata from jumpstarter.common.resources import ResourceMetadata from jumpstarter.common.serde import decode_value, encode_value @@ -24,6 +22,7 @@ RouterStream, forward_stream, ) +from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc @dataclass(kw_only=True) diff --git a/packages/jumpstarter/jumpstarter/client/lease.py b/packages/jumpstarter/jumpstarter/client/lease.py index d7f66d492..3a3f96e4e 100644 --- a/packages/jumpstarter/jumpstarter/client/lease.py +++ b/packages/jumpstarter/jumpstarter/client/lease.py @@ -6,13 +6,12 @@ from anyio.from_thread import BlockingPortal from google.protobuf import duration_pb2 from grpc.aio import Channel -from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, kubernetes_pb2 - from jumpstarter.client import client_from_path from jumpstarter.common import MetadataFilter, TemporaryUnixListener from jumpstarter.common.condition import condition_false, condition_present_and_equal, condition_true from jumpstarter.common.streams import connect_router_stream from jumpstarter.config.tls import TLSConfigV1Alpha1 +from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, kubernetes_pb2 logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter/jumpstarter/common/streams.py b/packages/jumpstarter/jumpstarter/common/streams.py index d1fa265d2..e2a9db6ad 100644 --- a/packages/jumpstarter/jumpstarter/common/streams.py +++ b/packages/jumpstarter/jumpstarter/common/streams.py @@ -3,11 +3,10 @@ from uuid import UUID import grpc -from jumpstarter_protocol.jumpstarter.v1 import router_pb2_grpc -from pydantic import BaseModel, Field, Json - from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials from jumpstarter.streams import RouterStream, forward_stream +from jumpstarter_protocol.jumpstarter.v1 import router_pb2_grpc +from pydantic import BaseModel, Field, Json class ResourceStreamRequest(BaseModel): diff --git a/packages/jumpstarter/jumpstarter/common/utils.py b/packages/jumpstarter/jumpstarter/common/utils.py index d9908e0a1..20e91c46c 100644 --- a/packages/jumpstarter/jumpstarter/common/utils.py +++ b/packages/jumpstarter/jumpstarter/common/utils.py @@ -4,7 +4,6 @@ from subprocess import Popen from anyio.from_thread import BlockingPortal, start_blocking_portal - from jumpstarter.client import client_from_path from jumpstarter.config.client import _allow_from_env from jumpstarter.config.env import JMP_DRIVERS_ALLOW, JUMPSTARTER_HOST diff --git a/packages/jumpstarter/jumpstarter/config/client.py b/packages/jumpstarter/jumpstarter/config/client.py index 6e8594e15..633d36ad1 100644 --- a/packages/jumpstarter/jumpstarter/config/client.py +++ b/packages/jumpstarter/jumpstarter/config/client.py @@ -6,11 +6,10 @@ import grpc import yaml from anyio.from_thread import BlockingPortal, start_blocking_portal -from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc -from pydantic import BaseModel, Field, ValidationError - from jumpstarter.common import MetadataFilter from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials +from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc +from pydantic import BaseModel, Field, ValidationError from .common import CONFIG_PATH from .env import JMP_DRIVERS_ALLOW, JMP_ENDPOINT, JMP_LEASE, JMP_TOKEN diff --git a/packages/jumpstarter/jumpstarter/config/client_config_test.py b/packages/jumpstarter/jumpstarter/config/client_config_test.py index fbdc1e9ae..325873477 100644 --- a/packages/jumpstarter/jumpstarter/config/client_config_test.py +++ b/packages/jumpstarter/jumpstarter/config/client_config_test.py @@ -5,13 +5,12 @@ import pytest import yaml -from pydantic import ValidationError - from jumpstarter.config import ( ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, ) from jumpstarter.config.env import JMP_DRIVERS_ALLOW, JMP_ENDPOINT, JMP_TOKEN +from pydantic import ValidationError def test_client_ensure_exists_makes_dir(monkeypatch: pytest.MonkeyPatch): diff --git a/packages/jumpstarter/jumpstarter/config/exporter.py b/packages/jumpstarter/jumpstarter/config/exporter.py index 46a4a2411..a241d81da 100644 --- a/packages/jumpstarter/jumpstarter/config/exporter.py +++ b/packages/jumpstarter/jumpstarter/config/exporter.py @@ -7,11 +7,10 @@ import grpc import yaml from anyio.from_thread import start_blocking_portal -from pydantic import BaseModel, Field - from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials from jumpstarter.common.importlib import import_class from jumpstarter.driver import Driver +from pydantic import BaseModel, Field from .tls import TLSConfigV1Alpha1 diff --git a/packages/jumpstarter/jumpstarter/config/exporter_test.py b/packages/jumpstarter/jumpstarter/config/exporter_test.py index df0577f7f..92e00319a 100644 --- a/packages/jumpstarter/jumpstarter/config/exporter_test.py +++ b/packages/jumpstarter/jumpstarter/config/exporter_test.py @@ -3,7 +3,6 @@ import pytest from anyio import create_task_group from anyio.from_thread import start_blocking_portal - from jumpstarter.common import MetadataFilter from .client import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers diff --git a/packages/jumpstarter/jumpstarter/config/user_config_test.py b/packages/jumpstarter/jumpstarter/config/user_config_test.py index d7daa9d06..2504ab94b 100644 --- a/packages/jumpstarter/jumpstarter/config/user_config_test.py +++ b/packages/jumpstarter/jumpstarter/config/user_config_test.py @@ -3,7 +3,6 @@ from unittest.mock import patch import pytest - from jumpstarter.config import ( ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, diff --git a/packages/jumpstarter/jumpstarter/driver/base.py b/packages/jumpstarter/jumpstarter/driver/base.py index b425b624f..712b21a12 100644 --- a/packages/jumpstarter/jumpstarter/driver/base.py +++ b/packages/jumpstarter/jumpstarter/driver/base.py @@ -15,10 +15,6 @@ import aiohttp from anyio import to_thread from grpc import StatusCode -from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc -from pydantic import TypeAdapter -from pydantic.dataclasses import dataclass - from jumpstarter.common import Metadata from jumpstarter.common.resources import ClientStreamResource, PresignedRequestResource, Resource, ResourceMetadata from jumpstarter.common.serde import decode_value, encode_value @@ -27,6 +23,9 @@ ResourceStreamRequest, ) from jumpstarter.streams import AiohttpStreamReaderStream, MetadataStream, create_memory_stream +from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc +from pydantic import TypeAdapter +from pydantic.dataclasses import dataclass from .decorators import ( MARKER_DRIVERCALL, diff --git a/packages/jumpstarter/jumpstarter/exporter/exporter.py b/packages/jumpstarter/jumpstarter/exporter/exporter.py index ff3963d32..1420215cb 100644 --- a/packages/jumpstarter/jumpstarter/exporter/exporter.py +++ b/packages/jumpstarter/jumpstarter/exporter/exporter.py @@ -6,16 +6,15 @@ import grpc from anyio import connect_unix, create_task_group from google.protobuf import empty_pb2 -from jumpstarter_protocol import ( - jumpstarter_pb2, - jumpstarter_pb2_grpc, -) - from jumpstarter.common import Metadata from jumpstarter.common.streams import connect_router_stream from jumpstarter.config.tls import TLSConfigV1Alpha1 from jumpstarter.driver import Driver from jumpstarter.exporter.session import Session +from jumpstarter_protocol import ( + jumpstarter_pb2, + jumpstarter_pb2_grpc, +) logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter/jumpstarter/exporter/session.py b/packages/jumpstarter/jumpstarter/exporter/session.py index 3e8e82b93..892e9585b 100644 --- a/packages/jumpstarter/jumpstarter/exporter/session.py +++ b/packages/jumpstarter/jumpstarter/exporter/session.py @@ -6,17 +6,16 @@ import grpc from anyio import Event, TypedAttributeLookupError from anyio.from_thread import start_blocking_portal +from jumpstarter.common import Metadata, TemporarySocket +from jumpstarter.common.streams import StreamRequestMetadata +from jumpstarter.driver import Driver +from jumpstarter.streams import MetadataStreamAttributes, RouterStream, forward_stream from jumpstarter_protocol import ( jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc, ) -from jumpstarter.common import Metadata, TemporarySocket -from jumpstarter.common.streams import StreamRequestMetadata -from jumpstarter.driver import Driver -from jumpstarter.streams import MetadataStreamAttributes, RouterStream, forward_stream - logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter/jumpstarter/listener_test.py b/packages/jumpstarter/jumpstarter/listener_test.py index d2025489f..73c3e8b5b 100644 --- a/packages/jumpstarter/jumpstarter/listener_test.py +++ b/packages/jumpstarter/jumpstarter/listener_test.py @@ -7,14 +7,13 @@ import pytest from anyio import create_task_group from anyio.from_thread import start_blocking_portal -from jumpstarter_driver_power.driver import MockPower - from jumpstarter.client import Lease from jumpstarter.common import MetadataFilter from jumpstarter.common.grpc import aio_secure_channel, ssl_channel_credentials from jumpstarter.common.streams import connect_router_stream from jumpstarter.config.tls import TLSConfigV1Alpha1 from jumpstarter.exporter import Exporter, Session +from jumpstarter_driver_power.driver import MockPower pytestmark = pytest.mark.anyio diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py index d2fc864a9..d5ebcf7aa 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py @@ -2,6 +2,7 @@ from typing import Optional import asyncclick as click +from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 from jumpstarter_cli_common import ( AliasedGroup, opt_context, @@ -13,8 +14,6 @@ from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.config.config_exception import ConfigException -from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 - from .k8s import ( handle_k8s_api_exception, handle_k8s_config_exception, diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py index 1ccd58621..f7fd3ecff 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py @@ -3,6 +3,11 @@ import pytest from asyncclick.testing import CliRunner +from jumpstarter.config import ( + ClientConfigV1Alpha1, + ClientConfigV1Alpha1Drivers, + ExporterConfigV1Alpha1, +) from jumpstarter_kubernetes import ( ClientsV1Alpha1Api, ExportersV1Alpha1Api, @@ -13,12 +18,6 @@ ) from kubernetes_asyncio.client.models import V1ObjectMeta -from jumpstarter.config import ( - ClientConfigV1Alpha1, - ClientConfigV1Alpha1Drivers, - ExporterConfigV1Alpha1, -) - from .create import create # Generate a random client name diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py index dc0d55b45..3df7151f9 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py @@ -2,6 +2,7 @@ from typing import Optional import asyncclick as click +from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 from jumpstarter_cli_common import ( AliasedGroup, opt_context, @@ -13,8 +14,6 @@ from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.config.config_exception import ConfigException -from jumpstarter.config import ClientConfigV1Alpha1, ExporterConfigV1Alpha1, UserConfigV1Alpha1 - from .k8s import ( handle_k8s_api_exception, handle_k8s_config_exception, diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py index bba248db3..521966906 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py @@ -2,14 +2,6 @@ import pytest from asyncclick.testing import CliRunner -from jumpstarter_kubernetes import ( - ClientsV1Alpha1Api, - ExportersV1Alpha1Api, - V1Alpha1Exporter, - V1Alpha1ExporterStatus, -) -from kubernetes_asyncio.client.models import V1ObjectMeta - from jumpstarter.config import ( ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, @@ -17,6 +9,13 @@ UserConfigV1Alpha1, UserConfigV1Alpha1Config, ) +from jumpstarter_kubernetes import ( + ClientsV1Alpha1Api, + ExportersV1Alpha1Api, + V1Alpha1Exporter, + V1Alpha1ExporterStatus, +) +from kubernetes_asyncio.client.models import V1ObjectMeta from .delete import delete diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py index 0ab62c33e..10dd4aa8b 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py @@ -1,6 +1,11 @@ from typing import Optional import asyncclick as click +from jumpstarter.config import ( + ClientConfigV1Alpha1, + UserConfigV1Alpha1, +) +from jumpstarter.config.exporter import ExporterConfigV1Alpha1 from jumpstarter_cli_common import ( opt_context, opt_kubeconfig, @@ -10,12 +15,6 @@ from kubernetes_asyncio.client.exceptions import ApiException from kubernetes_asyncio.config.config_exception import ConfigException -from jumpstarter.config import ( - ClientConfigV1Alpha1, - UserConfigV1Alpha1, -) -from jumpstarter.config.exporter import ExporterConfigV1Alpha1 - from .k8s import ( handle_k8s_api_exception, handle_k8s_config_exception, diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py index c124b5d99..da977d81a 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py @@ -3,16 +3,15 @@ import pytest from asyncclick.testing import CliRunner -from jumpstarter_kubernetes import ( - ClientsV1Alpha1Api, - ExportersV1Alpha1Api, -) - from jumpstarter.config import ( ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, ExporterConfigV1Alpha1, ) +from jumpstarter_kubernetes import ( + ClientsV1Alpha1Api, + ExportersV1Alpha1Api, +) from .import_res import import_res diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py index 4338d2c99..73a28d086 100644 --- a/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py @@ -1,7 +1,6 @@ import asyncclick as click -from jumpstarter_cli_common import AliasedGroup, version - from jumpstarter.common.utils import env +from jumpstarter_cli_common import AliasedGroup, version from .client_config import create_client_config, delete_client_config, list_client_configs, use_client_config from .client_shell import client_shell diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py index 5a08aa25f..bed794ea0 100644 --- a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py @@ -1,9 +1,8 @@ from typing import Optional import asyncclick as click -from jumpstarter_cli_common import make_table - from jumpstarter.config import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers, UserConfigV1Alpha1 +from jumpstarter_cli_common import make_table @click.command("create-config", short_help="Create a client config.") diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py index ec5c11857..fc1eb856c 100644 --- a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py @@ -1,5 +1,4 @@ import asyncclick as click - from jumpstarter.common import MetadataFilter from jumpstarter.common.utils import launch_shell from jumpstarter.config import ( diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py index e717a84bb..1440e5adf 100644 --- a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py @@ -1,6 +1,5 @@ import pytest from asyncclick.testing import CliRunner - from jumpstarter.config import ClientConfigV1Alpha1, UserConfigV1Alpha1 from . import client diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py b/packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py index 24b20ed1f..0ec567229 100644 --- a/packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py +++ b/packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py @@ -1,10 +1,9 @@ import asyncclick as click -from jumpstarter_cli_common import AliasedGroup - from jumpstarter.config import ( ClientConfigV1Alpha1, UserConfigV1Alpha1, ) +from jumpstarter_cli_common import AliasedGroup @click.group(cls=AliasedGroup, short_help="") diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py index e35b8cdf6..870ac78b2 100644 --- a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py +++ b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py @@ -3,7 +3,6 @@ from pathlib import Path import asyncclick as click - from jumpstarter.common.utils import launch_shell from jumpstarter.config.exporter import ExporterConfigV1Alpha1 diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py index 6283f6098..074ec2662 100644 --- a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py +++ b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py @@ -1,7 +1,6 @@ import asyncclick as click -from jumpstarter_cli_common import make_table - from jumpstarter.config.exporter import ExporterConfigV1Alpha1 +from jumpstarter_cli_common import make_table arg_alias = click.argument("alias", default="default") diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py index 473337db7..f3824fd21 100644 --- a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py +++ b/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py @@ -1,6 +1,5 @@ import pytest from asyncclick.testing import CliRunner - from jumpstarter.config.exporter import ExporterConfigV1Alpha1 from . import exporter diff --git a/packages/jumpstarter_driver_can/jumpstarter_driver_can/client.py b/packages/jumpstarter_driver_can/jumpstarter_driver_can/client.py index 3555ec0ce..bf86a2b3b 100644 --- a/packages/jumpstarter_driver_can/jumpstarter_driver_can/client.py +++ b/packages/jumpstarter_driver_can/jumpstarter_driver_can/client.py @@ -8,9 +8,8 @@ import can import isotp from can.bus import _SelfRemovingCyclicTask -from pydantic import ConfigDict, validate_call - from jumpstarter.client import DriverClient +from pydantic import ConfigDict, validate_call from .common import CanMessage, IsoTpAddress, IsoTpAsymmetricAddress, IsoTpMessage diff --git a/packages/jumpstarter_driver_can/jumpstarter_driver_can/client_test.py b/packages/jumpstarter_driver_can/jumpstarter_driver_can/client_test.py index fe73e8d0a..88c130af6 100644 --- a/packages/jumpstarter_driver_can/jumpstarter_driver_can/client_test.py +++ b/packages/jumpstarter_driver_can/jumpstarter_driver_can/client_test.py @@ -6,8 +6,8 @@ import can import isotp import pytest - from jumpstarter.common.utils import serve + from jumpstarter_driver_can.common import IsoTpParams from jumpstarter_driver_can.driver import Can, IsoTpPython, IsoTpSocket diff --git a/packages/jumpstarter_driver_can/jumpstarter_driver_can/driver.py b/packages/jumpstarter_driver_can/jumpstarter_driver_can/driver.py index 177d341ee..96f2c06eb 100644 --- a/packages/jumpstarter_driver_can/jumpstarter_driver_can/driver.py +++ b/packages/jumpstarter_driver_can/jumpstarter_driver_can/driver.py @@ -4,11 +4,10 @@ import can import isotp +from jumpstarter.driver import Driver, export from pydantic import ConfigDict, validate_call from pydantic.dataclasses import dataclass -from jumpstarter.driver import Driver, export - from .common import CanMessage, IsoTpAddress, IsoTpAsymmetricAddress, IsoTpMessage, IsoTpParams diff --git a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py index fed7d169e..273e0434f 100644 --- a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py +++ b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py @@ -1,7 +1,6 @@ from dataclasses import dataclass import asyncclick as click - from jumpstarter.client import DriverClient diff --git a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py index 5a8f66990..438ce317b 100644 --- a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py +++ b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py @@ -1,6 +1,5 @@ -from pydantic.dataclasses import dataclass - from jumpstarter.driver import Driver +from pydantic.dataclasses import dataclass class CompositeInterface: diff --git a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py index 03f4fb580..b2adf6d02 100644 --- a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py +++ b/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py @@ -1,6 +1,5 @@ -from jumpstarter_driver_power.driver import MockPower - from jumpstarter.common.utils import serve +from jumpstarter_driver_power.driver import MockPower from .driver import Composite diff --git a/packages/jumpstarter_driver_dutlink/examples/dutlink.py b/packages/jumpstarter_driver_dutlink/examples/dutlink.py index dc2fea042..b04840f40 100755 --- a/packages/jumpstarter_driver_dutlink/examples/dutlink.py +++ b/packages/jumpstarter_driver_dutlink/examples/dutlink.py @@ -3,9 +3,8 @@ import time import asyncclick as click -from jumpstarter_driver_network.adapters import PexpectAdapter - from jumpstarter.common.utils import env +from jumpstarter_driver_network.adapters import PexpectAdapter # initialize client from exporter config # from jumpstarter.common import MetadataFilter diff --git a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py index 40e287e55..dc583ee1c 100644 --- a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py +++ b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py @@ -11,14 +11,13 @@ import usb.util from anyio import fail_after, sleep from anyio.streams.file import FileReadStream, FileWriteStream +from jumpstarter.driver import Driver, export from jumpstarter_driver_composite.driver import CompositeInterface from jumpstarter_driver_opendal.driver import StorageMuxInterface from jumpstarter_driver_power.driver import PowerInterface, PowerReading from jumpstarter_driver_pyserial.driver import PySerial from serial.serialutil import SerialException -from jumpstarter.driver import Driver, export - log = logging.getLogger(__name__) diff --git a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py index 18c82ae0b..efab289d4 100644 --- a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py +++ b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py @@ -1,8 +1,8 @@ import pytest import usb +from jumpstarter.common.utils import serve from jumpstarter_driver_network.adapters import PexpectAdapter -from jumpstarter.common.utils import serve from jumpstarter_driver_dutlink.driver import Dutlink diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py index e541f3a90..cf68516e0 100644 --- a/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py @@ -1,11 +1,10 @@ from dataclasses import dataclass from pathlib import Path +from jumpstarter.client import DriverClient from jumpstarter_driver_opendal.adapter import OpendalAdapter from opendal import Operator -from jumpstarter.client import DriverClient - @dataclass(kw_only=True) class HttpServerClient(DriverClient): diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py index 5b7774aa7..08ba20308 100644 --- a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py @@ -7,7 +7,6 @@ import anyio from aiohttp import web from anyio.streams.file import FileWriteStream - from jumpstarter.driver import Driver, export logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py index 7a221544c..519fce79a 100644 --- a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py +++ b/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py @@ -6,7 +6,6 @@ import anyio import pytest from anyio import create_memory_object_stream - from jumpstarter.common.resources import ClientStreamResource from .driver import HttpServer diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py index 12d478752..6845e257b 100644 --- a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py @@ -2,11 +2,10 @@ from threading import Thread from time import sleep +from jumpstarter.common.utils import serve from paramiko import AUTH_SUCCESSFUL, OPEN_SUCCEEDED, ServerInterface, Transport from paramiko.rsakey import RSAKey -from jumpstarter.common.utils import serve - from ..driver import TcpNetwork from .fabric import FabricAdapter diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py index 7f84c9d0e..f3b5deaab 100644 --- a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py @@ -2,10 +2,9 @@ from urllib.parse import parse_qsl, urlparse from anyio.from_thread import start_blocking_portal -from websocket import create_connection - from jumpstarter.common import TemporaryTcpListener from jumpstarter.common.utils import serve +from websocket import create_connection from ..driver import TcpNetwork from .novnc import NovncAdapter diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py index 8b7e64ce5..8b2293ef7 100644 --- a/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py @@ -10,7 +10,6 @@ create_memory_object_stream, ) from anyio.streams.stapled import StapledObjectStream - from jumpstarter.driver import Driver, exportstream logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py index 7dbe04ec9..647e229be 100644 --- a/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py +++ b/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py @@ -5,7 +5,6 @@ import pytest from anyio.from_thread import start_blocking_portal - from jumpstarter.common import TemporaryTcpListener, TemporaryUnixListener from jumpstarter.common.utils import serve diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py index 1dde10343..a94be7948 100644 --- a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py @@ -4,11 +4,10 @@ from anyio import BrokenResourceError, EndOfStream from anyio.abc import ObjectStream -from opendal import AsyncFile, Operator -from opendal.exceptions import Error - from jumpstarter.client.adapters import ClientAdapter from jumpstarter.common.resources import PresignedRequestResource +from opendal import AsyncFile, Operator +from opendal.exceptions import Error @dataclass(frozen=True, kw_only=True, slots=True) diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py index 5905b4538..261a86069 100644 --- a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py @@ -1,9 +1,8 @@ from pathlib import Path import asyncclick as click -from opendal import Operator - from jumpstarter.client import DriverClient +from opendal import Operator from .adapter import OpendalAdapter diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py index 0b2f17934..47d36f19b 100644 --- a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py @@ -3,7 +3,6 @@ from tempfile import NamedTemporaryFile from anyio.streams.file import FileReadStream, FileWriteStream - from jumpstarter.driver import Driver, export diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py index 1b0536316..90221b443 100644 --- a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py +++ b/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py @@ -5,9 +5,8 @@ from threading import Thread import pytest -from opendal import Operator - from jumpstarter.common.utils import serve +from opendal import Operator from .driver import MockStorageMux diff --git a/packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py b/packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py index f9aa897d7..be2003773 100644 --- a/packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py +++ b/packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py @@ -1,7 +1,6 @@ from collections.abc import Generator import asyncclick as click - from jumpstarter.client import DriverClient from .common import PowerReading diff --git a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py index c0080db77..f6640cc49 100644 --- a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py +++ b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py @@ -1,11 +1,10 @@ from contextlib import contextmanager import asyncclick as click +from jumpstarter.client import DriverClient from jumpstarter_driver_network.adapters import PexpectAdapter from pexpect.fdpexpect import fdspawn -from jumpstarter.client import DriverClient - from .console import Console diff --git a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py index 67505d142..69d4d0f88 100644 --- a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py +++ b/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py @@ -4,9 +4,8 @@ from anyio.abc import ObjectStream from anyio.to_thread import run_sync -from serial import Serial, serial_for_url - from jumpstarter.driver import Driver, exportstream +from serial import Serial, serial_for_url log = logging.getLogger(__name__) diff --git a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py index 20c4a0cbe..1e86d5253 100644 --- a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py +++ b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py @@ -1,7 +1,6 @@ from dataclasses import dataclass, field from gpiozero import DigitalInputDevice, DigitalOutputDevice, InputDevice - from jumpstarter.driver import Driver, export diff --git a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py index de71d989e..a933ac17a 100644 --- a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py +++ b/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py @@ -2,8 +2,8 @@ from gpiozero import Device from gpiozero.pins.mock import MockFactory - from jumpstarter.common.utils import serve + from jumpstarter_driver_raspberrypi.driver import DigitalInput, DigitalOutput Device.pin_factory = MockFactory() diff --git a/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py index f7c6d8269..ad5d94419 100644 --- a/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py +++ b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py @@ -8,9 +8,8 @@ import usb.util from anyio import fail_after, sleep from anyio.streams.file import FileReadStream, FileWriteStream -from jumpstarter_driver_opendal.driver import StorageMuxInterface - from jumpstarter.driver import Driver, export +from jumpstarter_driver_opendal.driver import StorageMuxInterface @dataclass(kw_only=True) diff --git a/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py index d6d9c9aed..8f4434d0d 100644 --- a/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py +++ b/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py @@ -1,7 +1,7 @@ import pytest import usb - from jumpstarter.common.utils import serve + from jumpstarter_driver_sdwire.driver import SDWire diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py index cc22910cd..06c009c6f 100644 --- a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py @@ -1,11 +1,10 @@ from dataclasses import dataclass from pathlib import Path +from jumpstarter.client import DriverClient from jumpstarter_driver_opendal.adapter import OpendalAdapter from opendal import Operator -from jumpstarter.client import DriverClient - @dataclass(kw_only=True) class TftpServerClient(DriverClient): diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py index 465d5d0e5..2c917d596 100644 --- a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py @@ -8,8 +8,8 @@ from typing import Optional from anyio.streams.file import FileWriteStream - from jumpstarter.driver import Driver, export + from jumpstarter_driver_tftp.server import TftpServer logger = logging.getLogger(__name__) diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py index 733130cc3..196cdb4b1 100644 --- a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py @@ -6,8 +6,8 @@ import anyio import pytest from anyio import create_memory_object_stream - from jumpstarter.common.resources import ClientStreamResource + from jumpstarter_driver_tftp.driver import ( FileNotFound, Tftp, diff --git a/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/client.py b/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/client.py index 7f40da8ea..e2e8f5101 100644 --- a/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/client.py +++ b/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/client.py @@ -2,9 +2,8 @@ import logging from base64 import b64decode -from PIL import Image - from jumpstarter.client import DriverClient +from PIL import Image from .common import UStreamerState diff --git a/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver.py b/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver.py index e0a620989..24f21d724 100644 --- a/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver.py +++ b/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver.py @@ -10,7 +10,6 @@ from aiohttp import ClientSession, UnixConnector from anyio import connect_unix - from jumpstarter.driver import Driver, export, exportstream from .common import UStreamerState diff --git a/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver_test.py b/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver_test.py index 7cbda2858..de52cd3bd 100644 --- a/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver_test.py +++ b/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver_test.py @@ -1,6 +1,6 @@ import pytest - from jumpstarter.common.utils import serve + from jumpstarter_driver_ustreamer.driver import UStreamer diff --git a/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py b/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py index 8208b20c9..047f7117c 100644 --- a/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py +++ b/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py @@ -5,9 +5,8 @@ from typing import Any import imagehash -from PIL import Image - from jumpstarter.client import DriverClient +from PIL import Image log = logging.getLogger("imagehash") diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py index cd3d69e37..34d80f356 100644 --- a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py +++ b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py @@ -4,9 +4,8 @@ from dataclasses import dataclass from typing import Literal, Optional -from kubernetes_asyncio.client.models import V1ObjectMeta, V1ObjectReference - from jumpstarter.config import ClientConfigV1Alpha1, ClientConfigV1Alpha1Drivers +from kubernetes_asyncio.client.models import V1ObjectMeta, V1ObjectReference from .util import AbstractAsyncCustomObjectApi diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py index 27b115e2c..ff23bb216 100644 --- a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py +++ b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py @@ -3,9 +3,8 @@ from dataclasses import dataclass from typing import Literal -from kubernetes_asyncio.client.models import V1ObjectMeta, V1ObjectReference - from jumpstarter.config import ExporterConfigV1Alpha1 +from kubernetes_asyncio.client.models import V1ObjectMeta, V1ObjectReference from .util import AbstractAsyncCustomObjectApi diff --git a/packages/jumpstarter_testing/jumpstarter_testing/pytest.py b/packages/jumpstarter_testing/jumpstarter_testing/pytest.py index 7d3908c8d..512abcd1c 100644 --- a/packages/jumpstarter_testing/jumpstarter_testing/pytest.py +++ b/packages/jumpstarter_testing/jumpstarter_testing/pytest.py @@ -3,7 +3,6 @@ from typing import ClassVar import pytest - from jumpstarter.common import MetadataFilter from jumpstarter.common.utils import env from jumpstarter.config.client import ClientConfigV1Alpha1 diff --git a/packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py b/packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py index b026ec5d3..60be99a0d 100644 --- a/packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py +++ b/packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py @@ -1,8 +1,7 @@ -from jumpstarter_driver_power.driver import MockPower -from pytest import Pytester - from jumpstarter.config.env import JMP_DRIVERS_ALLOW, JUMPSTARTER_HOST from jumpstarter.exporter import Session +from jumpstarter_driver_power.driver import MockPower +from pytest import Pytester def test_env(pytester: Pytester, monkeypatch): From c4ec102d5e1e0b5e63c518e21a711183dd0e0fdf Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 13:45:20 -0500 Subject: [PATCH 09/16] Update pre-commit hooks and update lockfile --- .pre-commit-config.yaml | 2 +- uv.lock | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9758601e5..a8cf4f29b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,4 +1,4 @@ -default_stages: [commit] +default_stages: [pre-commit] repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.3.5 diff --git a/uv.lock b/uv.lock index 44a5dd795..9c3a06828 100644 --- a/uv.lock +++ b/uv.lock @@ -1332,26 +1332,22 @@ source = { virtual = "examples/soc-pytest" } dependencies = [ { name = "jumpstarter" }, { name = "jumpstarter-driver-dutlink" }, + { name = "jumpstarter-driver-network" }, { name = "jumpstarter-imagehash" }, - { name = "pytest" }, -] - -[package.dev-dependencies] -dev = [ { name = "jumpstarter-testing" }, + { name = "pytest" }, ] [package.metadata] requires-dist = [ { name = "jumpstarter", editable = "packages/jumpstarter" }, { name = "jumpstarter-driver-dutlink", editable = "packages/jumpstarter_driver_dutlink" }, + { name = "jumpstarter-driver-network", editable = "packages/jumpstarter_driver_network" }, { name = "jumpstarter-imagehash", editable = "packages/jumpstarter_imagehash" }, + { name = "jumpstarter-testing", editable = "packages/jumpstarter_testing" }, { name = "pytest", specifier = ">=8.3.2" }, ] -[package.metadata.requires-dev] -dev = [{ name = "jumpstarter-testing", editable = "packages/jumpstarter_testing" }] - [[package]] name = "jumpstarter-imagehash" version = "0.5.1.dev113+g07bed5a.d20250123" From 83a27a29468e49cee3a14caed63e5f6422a16338 Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 13:56:51 -0500 Subject: [PATCH 10/16] Switch ruff version and pin to pyproject.toml for GitHub Action --- .github/workflows/ruff.yaml | 4 +++- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ruff.yaml b/.github/workflows/ruff.yaml index 889f6f06c..1972189d2 100644 --- a/.github/workflows/ruff.yaml +++ b/.github/workflows/ruff.yaml @@ -17,4 +17,6 @@ jobs: - uses: actions/checkout@v4 - name: Run ruff - uses: chartboost/ruff-action@v1 + uses: astral-sh/ruff-action@v3 + with: + version-file: "pyproject.toml" diff --git a/pyproject.toml b/pyproject.toml index 7fd893c84..c1c79ecb6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ docs = [ "sphinx-substitution-extensions>=2024.10.17", ] dev = [ - "ruff>=0.6.1", + "ruff>=0.7.3", "typos>=1.23.6", "pre-commit>=3.8.0", "esbonio>=0.16.5", From 5087c1569bf2f03c9c13ce6bd12f9f6d33b64e93 Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 14:00:33 -0500 Subject: [PATCH 11/16] Upgrade to Ruff 0.9.2 --- pyproject.toml | 2 +- uv.lock | 44 ++++++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c1c79ecb6..b0de3ccf7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ docs = [ "sphinx-substitution-extensions>=2024.10.17", ] dev = [ - "ruff>=0.7.3", + "ruff>=0.9.2", "typos>=1.23.6", "pre-commit>=3.8.0", "esbonio>=0.16.5", diff --git a/uv.lock b/uv.lock index 9c3a06828..4de3a0558 100644 --- a/uv.lock +++ b/uv.lock @@ -37,7 +37,7 @@ members = [ dev = [ { name = "esbonio", specifier = ">=0.16.5" }, { name = "pre-commit", specifier = ">=3.8.0" }, - { name = "ruff", specifier = ">=0.6.1" }, + { name = "ruff", specifier = ">=0.9.2" }, { name = "typos", specifier = ">=1.23.6" }, ] docs = [ @@ -2265,27 +2265,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.7.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4b/06/09d1276df977eece383d0ed66052fc24ec4550a61f8fbc0a11200e690496/ruff-0.7.3.tar.gz", hash = "sha256:e1d1ba2e40b6e71a61b063354d04be669ab0d39c352461f3d789cac68b54a313", size = 3243664 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/56/933d433c2489e4642487b835f53dd9ff015fb3d8fa459b09bb2ce42d7c4b/ruff-0.7.3-py3-none-linux_armv6l.whl", hash = "sha256:34f2339dc22687ec7e7002792d1f50712bf84a13d5152e75712ac08be565d344", size = 10372090 }, - { url = "https://files.pythonhosted.org/packages/20/ea/1f0a22a6bcdd3fc26c73f63a025d05bd565901b729d56bcb093c722a6c4c/ruff-0.7.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fb397332a1879b9764a3455a0bb1087bda876c2db8aca3a3cbb67b3dbce8cda0", size = 10190037 }, - { url = "https://files.pythonhosted.org/packages/16/74/aca75666e0d481fe394e76a8647c44ea919087748024924baa1a17371e3e/ruff-0.7.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:37d0b619546103274e7f62643d14e1adcbccb242efda4e4bdb9544d7764782e9", size = 9811998 }, - { url = "https://files.pythonhosted.org/packages/20/a1/cf446a0d7f78ea1f0bd2b9171c11dfe746585c0c4a734b25966121eb4f5d/ruff-0.7.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d59f0c3ee4d1a6787614e7135b72e21024875266101142a09a61439cb6e38a5", size = 10620626 }, - { url = "https://files.pythonhosted.org/packages/cd/c1/82b27d09286ae855f5d03b1ad37cf243f21eb0081732d4d7b0d658d439cb/ruff-0.7.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:44eb93c2499a169d49fafd07bc62ac89b1bc800b197e50ff4633aed212569299", size = 10177598 }, - { url = "https://files.pythonhosted.org/packages/b9/42/c0acac22753bf74013d035a5ef6c5c4c40ad4d6686bfb3fda7c6f37d9b37/ruff-0.7.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d0242ce53f3a576c35ee32d907475a8d569944c0407f91d207c8af5be5dae4e", size = 11171963 }, - { url = "https://files.pythonhosted.org/packages/43/18/bb0befb7fb9121dd9009e6a72eb98e24f1bacb07c6f3ecb55f032ba98aed/ruff-0.7.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6b6224af8b5e09772c2ecb8dc9f3f344c1aa48201c7f07e7315367f6dd90ac29", size = 11856157 }, - { url = "https://files.pythonhosted.org/packages/5e/91/04e98d7d6e32eca9d1372be595f9abc7b7f048795e32eb2edbd8794d50bd/ruff-0.7.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c50f95a82b94421c964fae4c27c0242890a20fe67d203d127e84fbb8013855f5", size = 11440331 }, - { url = "https://files.pythonhosted.org/packages/f5/dc/3fe99f2ce10b76d389041a1b9f99e7066332e479435d4bebcceea16caff5/ruff-0.7.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7f3eff9961b5d2644bcf1616c606e93baa2d6b349e8aa8b035f654df252c8c67", size = 12725354 }, - { url = "https://files.pythonhosted.org/packages/43/7b/1daa712de1c5bc6cbbf9fa60e9c41cc48cda962dc6d2c4f2a224d2c3007e/ruff-0.7.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8963cab06d130c4df2fd52c84e9f10d297826d2e8169ae0c798b6221be1d1d2", size = 11010091 }, - { url = "https://files.pythonhosted.org/packages/b6/db/1227a903587432eb569e57a95b15a4f191a71fe315cde4c0312df7bc85da/ruff-0.7.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:61b46049d6edc0e4317fb14b33bd693245281a3007288b68a3f5b74a22a0746d", size = 10610687 }, - { url = "https://files.pythonhosted.org/packages/db/e2/dc41ee90c3085aadad4da614d310d834f641aaafddf3dfbba08210c616ce/ruff-0.7.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:10ebce7696afe4644e8c1a23b3cf8c0f2193a310c18387c06e583ae9ef284de2", size = 10254843 }, - { url = "https://files.pythonhosted.org/packages/6f/09/5f6cac1c91542bc5bd33d40b4c13b637bf64d7bb29e091dadb01b62527fe/ruff-0.7.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3f36d56326b3aef8eeee150b700e519880d1aab92f471eefdef656fd57492aa2", size = 10730962 }, - { url = "https://files.pythonhosted.org/packages/d3/42/89a4b9a24ef7d00269e24086c417a006f9a3ffeac2c80f2629eb5ce140ee/ruff-0.7.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5d024301109a0007b78d57ab0ba190087b43dce852e552734ebf0b0b85e4fb16", size = 11101907 }, - { url = "https://files.pythonhosted.org/packages/b0/5c/efdb4777686683a8edce94ffd812783bddcd3d2454d38c5ac193fef7c500/ruff-0.7.3-py3-none-win32.whl", hash = "sha256:4ba81a5f0c5478aa61674c5a2194de8b02652f17addf8dfc40c8937e6e7d79fc", size = 8611095 }, - { url = "https://files.pythonhosted.org/packages/bb/b8/28fbc6a4efa50178f973972d1c84b2d0a33cdc731588522ab751ac3da2f5/ruff-0.7.3-py3-none-win_amd64.whl", hash = "sha256:588a9ff2fecf01025ed065fe28809cd5a53b43505f48b69a1ac7707b1b7e4088", size = 9418283 }, - { url = "https://files.pythonhosted.org/packages/3f/77/b587cba6febd5e2003374f37eb89633f79f161e71084f94057c8653b7fb3/ruff-0.7.3-py3-none-win_arm64.whl", hash = "sha256:1713e2c5545863cdbfe2cbce21f69ffaf37b813bfd1fb3b90dc9a6f1963f5a8c", size = 8725228 }, +version = "0.9.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/80/63/77ecca9d21177600f551d1c58ab0e5a0b260940ea7312195bd2a4798f8a8/ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0", size = 3553799 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/b9/0e168e4e7fb3af851f739e8f07889b91d1a33a30fca8c29fa3149d6b03ec/ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347", size = 11652408 }, + { url = "https://files.pythonhosted.org/packages/2c/22/08ede5db17cf701372a461d1cb8fdde037da1d4fa622b69ac21960e6237e/ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00", size = 11587553 }, + { url = "https://files.pythonhosted.org/packages/42/05/dedfc70f0bf010230229e33dec6e7b2235b2a1b8cbb2a991c710743e343f/ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4", size = 11020755 }, + { url = "https://files.pythonhosted.org/packages/df/9b/65d87ad9b2e3def67342830bd1af98803af731243da1255537ddb8f22209/ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d", size = 11826502 }, + { url = "https://files.pythonhosted.org/packages/93/02/f2239f56786479e1a89c3da9bc9391120057fc6f4a8266a5b091314e72ce/ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c", size = 11390562 }, + { url = "https://files.pythonhosted.org/packages/c9/37/d3a854dba9931f8cb1b2a19509bfe59e00875f48ade632e95aefcb7a0aee/ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f", size = 12548968 }, + { url = "https://files.pythonhosted.org/packages/fa/c3/c7b812bb256c7a1d5553433e95980934ffa85396d332401f6b391d3c4569/ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684", size = 13187155 }, + { url = "https://files.pythonhosted.org/packages/bd/5a/3c7f9696a7875522b66aa9bba9e326e4e5894b4366bd1dc32aa6791cb1ff/ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d", size = 12704674 }, + { url = "https://files.pythonhosted.org/packages/be/d6/d908762257a96ce5912187ae9ae86792e677ca4f3dc973b71e7508ff6282/ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df", size = 14529328 }, + { url = "https://files.pythonhosted.org/packages/2d/c2/049f1e6755d12d9cd8823242fa105968f34ee4c669d04cac8cea51a50407/ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247", size = 12385955 }, + { url = "https://files.pythonhosted.org/packages/91/5a/a9bdb50e39810bd9627074e42743b00e6dc4009d42ae9f9351bc3dbc28e7/ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e", size = 11810149 }, + { url = "https://files.pythonhosted.org/packages/e5/fd/57df1a0543182f79a1236e82a79c68ce210efb00e97c30657d5bdb12b478/ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe", size = 11479141 }, + { url = "https://files.pythonhosted.org/packages/dc/16/bc3fd1d38974f6775fc152a0554f8c210ff80f2764b43777163c3c45d61b/ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb", size = 12014073 }, + { url = "https://files.pythonhosted.org/packages/47/6b/e4ca048a8f2047eb652e1e8c755f384d1b7944f69ed69066a37acd4118b0/ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a", size = 12435758 }, + { url = "https://files.pythonhosted.org/packages/c2/40/4d3d6c979c67ba24cf183d29f706051a53c36d78358036a9cd21421582ab/ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145", size = 9796916 }, + { url = "https://files.pythonhosted.org/packages/c3/ef/7f548752bdb6867e6939489c87fe4da489ab36191525fadc5cede2a6e8e2/ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5", size = 10773080 }, + { url = "https://files.pythonhosted.org/packages/0e/4e/33df635528292bd2d18404e4daabcd74ca8a9853b2e1df85ed3d32d24362/ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6", size = 10001738 }, ] [[package]] From cfb9113c47c3c80aec40ead24941bda373cdbe1e Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 15:29:31 -0500 Subject: [PATCH 12/16] Fix new Ruff lint error --- packages/jumpstarter/jumpstarter/client/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jumpstarter/jumpstarter/client/client.py b/packages/jumpstarter/jumpstarter/client/client.py index 257dd6b71..64730330b 100644 --- a/packages/jumpstarter/jumpstarter/client/client.py +++ b/packages/jumpstarter/jumpstarter/client/client.py @@ -1,11 +1,11 @@ from collections import OrderedDict, defaultdict from contextlib import asynccontextmanager +from graphlib import TopologicalSorter from uuid import UUID import grpc from anyio.from_thread import BlockingPortal from google.protobuf import empty_pb2 -from graphlib import TopologicalSorter from jumpstarter.client import DriverClient from jumpstarter.common.importlib import import_class from jumpstarter_protocol import jumpstarter_pb2_grpc From 180ed74f3e86133a424f7391424930e3e09baad6 Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 15:33:19 -0500 Subject: [PATCH 13/16] Run ruff format --- .../jumpstarter_example_soc_pytest/test_on_rpi4.py | 2 +- .../jumpstarter_cli_admin/jumpstarter_cli_admin/install.py | 2 +- packages/jumpstarter_cli_admin/jumpstarter_cli_admin/k8s.py | 2 +- .../jumpstarter_driver_dutlink/driver.py | 5 ++--- .../jumpstarter_driver_tftp/server.py | 2 +- .../jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py | 2 +- .../jumpstarter_kubernetes/jumpstarter_kubernetes/install.py | 2 +- 7 files changed, 8 insertions(+), 9 deletions(-) diff --git a/examples/soc-pytest/jumpstarter_example_soc_pytest/test_on_rpi4.py b/examples/soc-pytest/jumpstarter_example_soc_pytest/test_on_rpi4.py index a152883f3..9b40f1c02 100644 --- a/examples/soc-pytest/jumpstarter_example_soc_pytest/test_on_rpi4.py +++ b/examples/soc-pytest/jumpstarter_example_soc_pytest/test_on_rpi4.py @@ -42,7 +42,7 @@ def test_setup_device(self, client, console): client.dutlink.storage.write_local_file("image/images/latest.raw") except opendal.exceptions.NotFound: pytest.exit( - "No image found, please enter the image directory and run `make`, " "more details in the README.md" + "No image found, please enter the image directory and run `make`, more details in the README.md" ) return client.dutlink.storage.dut() diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/install.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/install.py index c94804ecd..f52a98579 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/install.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/install.py @@ -8,7 +8,7 @@ def get_chart_version() -> str: client_version = get_client_version() parts = client_version.split(".") - return f"{parts[0].replace("v", "")}.{parts[1]}.{parts[2]}" + return f"{parts[0].replace('v', '')}.{parts[1]}.{parts[2]}" @click.command diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/k8s.py b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/k8s.py index 9cb21b4e2..8e3f622cd 100644 --- a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/k8s.py +++ b/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/k8s.py @@ -10,7 +10,7 @@ def handle_k8s_api_exception(e: ApiException): # Try to parse the JSON response try: json_body = json.loads(e.body) - raise click.ClickException(f"Error from server ({json_body["reason"]}): {json_body["message"]}") from e + raise click.ClickException(f"Error from server ({json_body['reason']}): {json_body['message']}") from e except json.decoder.JSONDecodeError: raise click.ClickException(f"Server error: {e.body}") from e diff --git a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py index dc583ee1c..410440f19 100644 --- a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py +++ b/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py @@ -198,7 +198,7 @@ async def write(self, src: str): async for chunk in res: await stream.send(chunk) if total_bytes > next_print: - log.debug(f"{self.storage_device} written {total_bytes/(1024*1024)} MB") + log.debug(f"{self.storage_device} written {total_bytes / (1024 * 1024)} MB") next_print += 50 * 1024 * 1024 total_bytes += len(chunk) @@ -251,8 +251,7 @@ def __post_init__(self): self.children["console"] = PySerial(url=self.alternate_console, baudrate=self.baudrate) except SerialException: log.info( - f"failed to open alternate console {self.alternate_console} " - "but trying to power on the target once" + f"failed to open alternate console {self.alternate_console} but trying to power on the target once" ) self.children["power"].on() time.sleep(5) diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py index f10fb69db..bf476f1fa 100644 --- a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py +++ b/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py @@ -292,7 +292,7 @@ async def start(self): success = await self._send_with_retries(packet) if not success: self.logger.error( - f"Failed to send final empty block {self.block_num} " f"to {self.client_addr}" + f"Failed to send final empty block {self.block_num} to {self.client_addr}" ) break self.logger.info(f"Transfer complete to {self.client_addr}, final block {self.block_num}") diff --git a/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py b/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py index 047f7117c..e7b747111 100644 --- a/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py +++ b/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py @@ -67,7 +67,7 @@ def assert_snapshot(self, reference_img_file, tolerance=1): log.error(f"Image hashes are different, saving the actual image as {save_filename}") snapshot_img.save(save_filename) raise AssertionError( - f"{self.client.name}.assert_snapshot {reference_img_file}:" f" diff {diff} > tolerance {tolerance}" + f"{self.client.name}.assert_snapshot {reference_img_file}: diff {diff} > tolerance {tolerance}" ) def _snapshot_diff(self, reference_img_file, hash_func=imagehash.average_hash, hash_size=8): diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/install.py b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/install.py index 090e03488..42a538bad 100644 --- a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/install.py +++ b/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/install.py @@ -54,7 +54,7 @@ async def install_helm_chart( "--set", "global.metrics.enabled=false", "--set", - f"jumpstarter-controller.grpc.nodeport.enabled={"true" if mode == "nodeport" else "false"}", + f"jumpstarter-controller.grpc.nodeport.enabled={'true' if mode == 'nodeport' else 'false'}", "--set", f"jumpstarter-controller.grpc.nodeport.port={grpc_port}", "--set", From a178b632e1b6ace81a8c16ef4826037d6997c5a4 Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 15:51:58 -0500 Subject: [PATCH 14/16] Upgrade python-can dependency and update package naming --- .../README.md | 0 .../jumpstarter_cli_admin/__init__.py | 0 .../jumpstarter_cli_admin/create.py | 0 .../jumpstarter_cli_admin/create_test.py | 0 .../jumpstarter_cli_admin/delete.py | 0 .../jumpstarter_cli_admin/delete_test.py | 0 .../jumpstarter_cli_admin/get.py | 0 .../jumpstarter_cli_admin/get_test.py | 0 .../jumpstarter_cli_admin/import_res.py | 0 .../jumpstarter_cli_admin/import_res_test.py | 0 .../jumpstarter_cli_admin/install.py | 0 .../jumpstarter_cli_admin/k8s.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_cli_client/__init__.py | 0 .../jumpstarter_cli_client/client_config.py | 0 .../jumpstarter_cli_client/client_shell.py | 0 .../jumpstarter_cli_client/client_test.py | 0 .../jumpstarter_cli_client/j.py | 0 .../jumpstarter_cli_client/lease.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_cli_common/__init__.py | 0 .../jumpstarter_cli_common/alias.py | 0 .../jumpstarter_cli_common/opt.py | 0 .../jumpstarter_cli_common/table.py | 0 .../jumpstarter_cli_common/table_test.py | 0 .../jumpstarter_cli_common/time.py | 0 .../jumpstarter_cli_common/version.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_cli_exporter/__init__.py | 0 .../jumpstarter_cli_exporter/exporter.py | 0 .../exporter_config.py | 0 .../jumpstarter_cli_exporter/exporter_test.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_cli/__init__.py | 0 .../jumpstarter_cli/__main__.py | 0 .../jumpstarter_cli/cli_test.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_driver_can/__init__.py | 0 .../jumpstarter_driver_can/client.py | 0 .../jumpstarter_driver_can/client_test.py | 0 .../jumpstarter_driver_can/common.py | 0 .../jumpstarter_driver_can/driver.py | 0 .../pyproject.toml | 2 +- .../README.md | 0 .../jumpstarter_driver_composite/__init__.py | 0 .../jumpstarter_driver_composite/client.py | 0 .../jumpstarter_driver_composite/driver.py | 0 .../driver_test.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../examples/dutlink.py | 0 .../examples/exporter.yaml | 0 .../jumpstarter_driver_dutlink/__init__.py | 0 .../jumpstarter_driver_dutlink/driver.py | 0 .../jumpstarter_driver_dutlink/driver_test.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_driver_http/__init__.py | 0 .../jumpstarter_driver_http/client.py | 0 .../jumpstarter_driver_http/driver.py | 0 .../jumpstarter_driver_http/driver_test.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_driver_network/__init__.py | 0 .../adapters/__init__.py | 0 .../adapters/fabric.py | 0 .../adapters/fabric_test.py | 0 .../adapters/novnc.py | 0 .../adapters/novnc_test.py | 0 .../adapters/pexpect.py | 0 .../adapters/portforward.py | 0 .../jumpstarter_driver_network/client.py | 0 .../jumpstarter_driver_network/driver.py | 0 .../jumpstarter_driver_network/driver_test.py | 0 .../streams/__init__.py | 0 .../streams/websocket.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_driver_opendal/__init__.py | 0 .../jumpstarter_driver_opendal/adapter.py | 0 .../jumpstarter_driver_opendal/client.py | 0 .../jumpstarter_driver_opendal/driver.py | 0 .../jumpstarter_driver_opendal/driver_test.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_driver_power/__init__.py | 0 .../jumpstarter_driver_power/client.py | 0 .../jumpstarter_driver_power/client_test.py | 0 .../jumpstarter_driver_power/common.py | 0 .../jumpstarter_driver_power/driver.py | 0 .../jumpstarter_driver_power/driver_test.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_driver_pyserial/__init__.py | 0 .../jumpstarter_driver_pyserial/client.py | 0 .../jumpstarter_driver_pyserial/console.py | 0 .../jumpstarter_driver_pyserial/driver.py | 0 .../driver_test.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../__init__.py | 0 .../jumpstarter_driver_raspberrypi/client.py | 0 .../jumpstarter_driver_raspberrypi/driver.py | 0 .../driver_test.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_driver_sdwire/__init__.py | 0 .../jumpstarter_driver_sdwire/driver.py | 0 .../jumpstarter_driver_sdwire/driver_test.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../examples/exporter.yaml | 0 .../examples/tftp_test.py | 0 .../jumpstarter_driver_tftp/__init__.py | 0 .../jumpstarter_driver_tftp/client.py | 0 .../jumpstarter_driver_tftp/driver.py | 0 .../jumpstarter_driver_tftp/driver_test.py | 0 .../jumpstarter_driver_tftp/server.py | 0 .../jumpstarter_driver_tftp/server_test.py | 0 .../pyproject.toml | 0 .../test.txt | 0 .../README.md | 0 .../jumpstarter_driver_ustreamer/__init__.py | 0 .../jumpstarter_driver_ustreamer/client.py | 0 .../jumpstarter_driver_ustreamer/common.py | 0 .../jumpstarter_driver_ustreamer/driver.py | 0 .../driver_test.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_imagehash/__init__.py | 0 .../jumpstarter_imagehash/imagehash.py | 0 .../jumpstarter_imagehash/imagehash_test.py | 0 .../jumpstarter_imagehash/test_image_a.jpeg | Bin .../jumpstarter_imagehash/test_image_b.jpeg | Bin .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_kubernetes/__init__.py | 0 .../jumpstarter_kubernetes/clients.py | 0 .../jumpstarter_kubernetes/exporters.py | 0 .../jumpstarter_kubernetes/install.py | 0 .../jumpstarter_kubernetes/leases.py | 0 .../jumpstarter_kubernetes/util/__init__.py | 0 .../util/async_custom_object_api.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../jumpstarter_protocol/__init__.py | 0 .../jumpstarter/v1/jumpstarter_pb2.py | 0 .../jumpstarter/v1/jumpstarter_pb2_grpc.py | 0 .../jumpstarter/v1/kubernetes_pb2.py | 0 .../jumpstarter/v1/kubernetes_pb2_grpc.py | 0 .../jumpstarter/v1/router_pb2.py | 0 .../jumpstarter/v1/router_pb2_grpc.py | 0 .../pyproject.toml | 0 .../README.md | 0 .../conftest.py | 0 .../jumpstarter_testing/__init__.py | 0 .../jumpstarter_testing/pytest.py | 0 .../jumpstarter_testing/pytest_test.py | 0 .../pyproject.toml | 0 uv.lock | 172 ++++++++---------- 165 files changed, 75 insertions(+), 99 deletions(-) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/README.md (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/jumpstarter_cli_admin/__init__.py (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/jumpstarter_cli_admin/create.py (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/jumpstarter_cli_admin/create_test.py (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/jumpstarter_cli_admin/delete.py (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/jumpstarter_cli_admin/delete_test.py (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/jumpstarter_cli_admin/get.py (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/jumpstarter_cli_admin/get_test.py (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/jumpstarter_cli_admin/import_res.py (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/jumpstarter_cli_admin/import_res_test.py (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/jumpstarter_cli_admin/install.py (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/jumpstarter_cli_admin/k8s.py (100%) rename packages/{jumpstarter_cli_admin => jumpstarter-cli-admin}/pyproject.toml (100%) rename packages/{jumpstarter_cli_client => jumpstarter-cli-client}/README.md (100%) rename packages/{jumpstarter_cli_client => jumpstarter-cli-client}/jumpstarter_cli_client/__init__.py (100%) rename packages/{jumpstarter_cli_client => jumpstarter-cli-client}/jumpstarter_cli_client/client_config.py (100%) rename packages/{jumpstarter_cli_client => jumpstarter-cli-client}/jumpstarter_cli_client/client_shell.py (100%) rename packages/{jumpstarter_cli_client => jumpstarter-cli-client}/jumpstarter_cli_client/client_test.py (100%) rename packages/{jumpstarter_cli_client => jumpstarter-cli-client}/jumpstarter_cli_client/j.py (100%) rename packages/{jumpstarter_cli_client => jumpstarter-cli-client}/jumpstarter_cli_client/lease.py (100%) rename packages/{jumpstarter_cli_client => jumpstarter-cli-client}/pyproject.toml (100%) rename packages/{jumpstarter_cli_common => jumpstarter-cli-common}/README.md (100%) rename packages/{jumpstarter_cli_common => jumpstarter-cli-common}/jumpstarter_cli_common/__init__.py (100%) rename packages/{jumpstarter_cli_common => jumpstarter-cli-common}/jumpstarter_cli_common/alias.py (100%) rename packages/{jumpstarter_cli_common => jumpstarter-cli-common}/jumpstarter_cli_common/opt.py (100%) rename packages/{jumpstarter_cli_common => jumpstarter-cli-common}/jumpstarter_cli_common/table.py (100%) rename packages/{jumpstarter_cli_common => jumpstarter-cli-common}/jumpstarter_cli_common/table_test.py (100%) rename packages/{jumpstarter_cli_common => jumpstarter-cli-common}/jumpstarter_cli_common/time.py (100%) rename packages/{jumpstarter_cli_common => jumpstarter-cli-common}/jumpstarter_cli_common/version.py (100%) rename packages/{jumpstarter_cli_common => jumpstarter-cli-common}/pyproject.toml (100%) rename packages/{jumpstarter_cli_exporter => jumpstarter-cli-exporter}/README.md (100%) rename packages/{jumpstarter_cli_exporter => jumpstarter-cli-exporter}/jumpstarter_cli_exporter/__init__.py (100%) rename packages/{jumpstarter_cli_exporter => jumpstarter-cli-exporter}/jumpstarter_cli_exporter/exporter.py (100%) rename packages/{jumpstarter_cli_exporter => jumpstarter-cli-exporter}/jumpstarter_cli_exporter/exporter_config.py (100%) rename packages/{jumpstarter_cli_exporter => jumpstarter-cli-exporter}/jumpstarter_cli_exporter/exporter_test.py (100%) rename packages/{jumpstarter_cli_exporter => jumpstarter-cli-exporter}/pyproject.toml (100%) rename packages/{jumpstarter_cli => jumpstarter-cli}/README.md (100%) rename packages/{jumpstarter_cli => jumpstarter-cli}/jumpstarter_cli/__init__.py (100%) rename packages/{jumpstarter_cli => jumpstarter-cli}/jumpstarter_cli/__main__.py (100%) rename packages/{jumpstarter_cli => jumpstarter-cli}/jumpstarter_cli/cli_test.py (100%) rename packages/{jumpstarter_cli => jumpstarter-cli}/pyproject.toml (100%) rename packages/{jumpstarter_driver_can => jumpstarter-driver-can}/README.md (100%) rename packages/{jumpstarter_driver_can => jumpstarter-driver-can}/jumpstarter_driver_can/__init__.py (100%) rename packages/{jumpstarter_driver_can => jumpstarter-driver-can}/jumpstarter_driver_can/client.py (100%) rename packages/{jumpstarter_driver_can => jumpstarter-driver-can}/jumpstarter_driver_can/client_test.py (100%) rename packages/{jumpstarter_driver_can => jumpstarter-driver-can}/jumpstarter_driver_can/common.py (100%) rename packages/{jumpstarter_driver_can => jumpstarter-driver-can}/jumpstarter_driver_can/driver.py (100%) rename packages/{jumpstarter_driver_can => jumpstarter-driver-can}/pyproject.toml (97%) rename packages/{jumpstarter_driver_composite => jumpstarter-driver-composite}/README.md (100%) rename packages/{jumpstarter_driver_composite => jumpstarter-driver-composite}/jumpstarter_driver_composite/__init__.py (100%) rename packages/{jumpstarter_driver_composite => jumpstarter-driver-composite}/jumpstarter_driver_composite/client.py (100%) rename packages/{jumpstarter_driver_composite => jumpstarter-driver-composite}/jumpstarter_driver_composite/driver.py (100%) rename packages/{jumpstarter_driver_composite => jumpstarter-driver-composite}/jumpstarter_driver_composite/driver_test.py (100%) rename packages/{jumpstarter_driver_composite => jumpstarter-driver-composite}/pyproject.toml (100%) rename packages/{jumpstarter_driver_dutlink => jumpstarter-driver-dutlink}/README.md (100%) rename packages/{jumpstarter_driver_dutlink => jumpstarter-driver-dutlink}/examples/dutlink.py (100%) rename packages/{jumpstarter_driver_dutlink => jumpstarter-driver-dutlink}/examples/exporter.yaml (100%) rename packages/{jumpstarter_driver_dutlink => jumpstarter-driver-dutlink}/jumpstarter_driver_dutlink/__init__.py (100%) rename packages/{jumpstarter_driver_dutlink => jumpstarter-driver-dutlink}/jumpstarter_driver_dutlink/driver.py (100%) rename packages/{jumpstarter_driver_dutlink => jumpstarter-driver-dutlink}/jumpstarter_driver_dutlink/driver_test.py (100%) rename packages/{jumpstarter_driver_dutlink => jumpstarter-driver-dutlink}/pyproject.toml (100%) rename packages/{jumpstarter_driver_http => jumpstarter-driver-http}/README.md (100%) rename packages/{jumpstarter_driver_http => jumpstarter-driver-http}/jumpstarter_driver_http/__init__.py (100%) rename packages/{jumpstarter_driver_http => jumpstarter-driver-http}/jumpstarter_driver_http/client.py (100%) rename packages/{jumpstarter_driver_http => jumpstarter-driver-http}/jumpstarter_driver_http/driver.py (100%) rename packages/{jumpstarter_driver_http => jumpstarter-driver-http}/jumpstarter_driver_http/driver_test.py (100%) rename packages/{jumpstarter_driver_http => jumpstarter-driver-http}/pyproject.toml (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/README.md (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/__init__.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/adapters/__init__.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/adapters/fabric.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/adapters/fabric_test.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/adapters/novnc.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/adapters/novnc_test.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/adapters/pexpect.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/adapters/portforward.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/client.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/driver.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/driver_test.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/streams/__init__.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/jumpstarter_driver_network/streams/websocket.py (100%) rename packages/{jumpstarter_driver_network => jumpstarter-driver-network}/pyproject.toml (100%) rename packages/{jumpstarter_driver_opendal => jumpstarter-driver-opendal}/README.md (100%) rename packages/{jumpstarter_driver_opendal => jumpstarter-driver-opendal}/jumpstarter_driver_opendal/__init__.py (100%) rename packages/{jumpstarter_driver_opendal => jumpstarter-driver-opendal}/jumpstarter_driver_opendal/adapter.py (100%) rename packages/{jumpstarter_driver_opendal => jumpstarter-driver-opendal}/jumpstarter_driver_opendal/client.py (100%) rename packages/{jumpstarter_driver_opendal => jumpstarter-driver-opendal}/jumpstarter_driver_opendal/driver.py (100%) rename packages/{jumpstarter_driver_opendal => jumpstarter-driver-opendal}/jumpstarter_driver_opendal/driver_test.py (100%) rename packages/{jumpstarter_driver_opendal => jumpstarter-driver-opendal}/pyproject.toml (100%) rename packages/{jumpstarter_driver_power => jumpstarter-driver-power}/README.md (100%) rename packages/{jumpstarter_driver_power => jumpstarter-driver-power}/jumpstarter_driver_power/__init__.py (100%) rename packages/{jumpstarter_driver_power => jumpstarter-driver-power}/jumpstarter_driver_power/client.py (100%) rename packages/{jumpstarter_driver_power => jumpstarter-driver-power}/jumpstarter_driver_power/client_test.py (100%) rename packages/{jumpstarter_driver_power => jumpstarter-driver-power}/jumpstarter_driver_power/common.py (100%) rename packages/{jumpstarter_driver_power => jumpstarter-driver-power}/jumpstarter_driver_power/driver.py (100%) rename packages/{jumpstarter_driver_power => jumpstarter-driver-power}/jumpstarter_driver_power/driver_test.py (100%) rename packages/{jumpstarter_driver_power => jumpstarter-driver-power}/pyproject.toml (100%) rename packages/{jumpstarter_driver_pyserial => jumpstarter-driver-pyserial}/README.md (100%) rename packages/{jumpstarter_driver_pyserial => jumpstarter-driver-pyserial}/jumpstarter_driver_pyserial/__init__.py (100%) rename packages/{jumpstarter_driver_pyserial => jumpstarter-driver-pyserial}/jumpstarter_driver_pyserial/client.py (100%) rename packages/{jumpstarter_driver_pyserial => jumpstarter-driver-pyserial}/jumpstarter_driver_pyserial/console.py (100%) rename packages/{jumpstarter_driver_pyserial => jumpstarter-driver-pyserial}/jumpstarter_driver_pyserial/driver.py (100%) rename packages/{jumpstarter_driver_pyserial => jumpstarter-driver-pyserial}/jumpstarter_driver_pyserial/driver_test.py (100%) rename packages/{jumpstarter_driver_pyserial => jumpstarter-driver-pyserial}/pyproject.toml (100%) rename packages/{jumpstarter_driver_raspberrypi => jumpstarter-driver-raspberrypi}/README.md (100%) rename packages/{jumpstarter_driver_raspberrypi => jumpstarter-driver-raspberrypi}/jumpstarter_driver_raspberrypi/__init__.py (100%) rename packages/{jumpstarter_driver_raspberrypi => jumpstarter-driver-raspberrypi}/jumpstarter_driver_raspberrypi/client.py (100%) rename packages/{jumpstarter_driver_raspberrypi => jumpstarter-driver-raspberrypi}/jumpstarter_driver_raspberrypi/driver.py (100%) rename packages/{jumpstarter_driver_raspberrypi => jumpstarter-driver-raspberrypi}/jumpstarter_driver_raspberrypi/driver_test.py (100%) rename packages/{jumpstarter_driver_raspberrypi => jumpstarter-driver-raspberrypi}/pyproject.toml (100%) rename packages/{jumpstarter_driver_sdwire => jumpstarter-driver-sdwire}/README.md (100%) rename packages/{jumpstarter_driver_sdwire => jumpstarter-driver-sdwire}/jumpstarter_driver_sdwire/__init__.py (100%) rename packages/{jumpstarter_driver_sdwire => jumpstarter-driver-sdwire}/jumpstarter_driver_sdwire/driver.py (100%) rename packages/{jumpstarter_driver_sdwire => jumpstarter-driver-sdwire}/jumpstarter_driver_sdwire/driver_test.py (100%) rename packages/{jumpstarter_driver_sdwire => jumpstarter-driver-sdwire}/pyproject.toml (100%) rename packages/{jumpstarter_driver_tftp => jumpstarter-driver-tftp}/README.md (100%) rename packages/{jumpstarter_driver_tftp => jumpstarter-driver-tftp}/examples/exporter.yaml (100%) rename packages/{jumpstarter_driver_tftp => jumpstarter-driver-tftp}/examples/tftp_test.py (100%) rename packages/{jumpstarter_driver_tftp => jumpstarter-driver-tftp}/jumpstarter_driver_tftp/__init__.py (100%) rename packages/{jumpstarter_driver_tftp => jumpstarter-driver-tftp}/jumpstarter_driver_tftp/client.py (100%) rename packages/{jumpstarter_driver_tftp => jumpstarter-driver-tftp}/jumpstarter_driver_tftp/driver.py (100%) rename packages/{jumpstarter_driver_tftp => jumpstarter-driver-tftp}/jumpstarter_driver_tftp/driver_test.py (100%) rename packages/{jumpstarter_driver_tftp => jumpstarter-driver-tftp}/jumpstarter_driver_tftp/server.py (100%) rename packages/{jumpstarter_driver_tftp => jumpstarter-driver-tftp}/jumpstarter_driver_tftp/server_test.py (100%) rename packages/{jumpstarter_driver_tftp => jumpstarter-driver-tftp}/pyproject.toml (100%) rename packages/{jumpstarter_driver_tftp => jumpstarter-driver-tftp}/test.txt (100%) rename packages/{jumpstarter_driver_ustreamer => jumpstarter-driver-ustreamer}/README.md (100%) rename packages/{jumpstarter_driver_ustreamer => jumpstarter-driver-ustreamer}/jumpstarter_driver_ustreamer/__init__.py (100%) rename packages/{jumpstarter_driver_ustreamer => jumpstarter-driver-ustreamer}/jumpstarter_driver_ustreamer/client.py (100%) rename packages/{jumpstarter_driver_ustreamer => jumpstarter-driver-ustreamer}/jumpstarter_driver_ustreamer/common.py (100%) rename packages/{jumpstarter_driver_ustreamer => jumpstarter-driver-ustreamer}/jumpstarter_driver_ustreamer/driver.py (100%) rename packages/{jumpstarter_driver_ustreamer => jumpstarter-driver-ustreamer}/jumpstarter_driver_ustreamer/driver_test.py (100%) rename packages/{jumpstarter_driver_ustreamer => jumpstarter-driver-ustreamer}/pyproject.toml (100%) rename packages/{jumpstarter_imagehash => jumpstarter-imagehash}/README.md (100%) rename packages/{jumpstarter_imagehash => jumpstarter-imagehash}/jumpstarter_imagehash/__init__.py (100%) rename packages/{jumpstarter_imagehash => jumpstarter-imagehash}/jumpstarter_imagehash/imagehash.py (100%) rename packages/{jumpstarter_imagehash => jumpstarter-imagehash}/jumpstarter_imagehash/imagehash_test.py (100%) rename packages/{jumpstarter_imagehash => jumpstarter-imagehash}/jumpstarter_imagehash/test_image_a.jpeg (100%) rename packages/{jumpstarter_imagehash => jumpstarter-imagehash}/jumpstarter_imagehash/test_image_b.jpeg (100%) rename packages/{jumpstarter_imagehash => jumpstarter-imagehash}/pyproject.toml (100%) rename packages/{jumpstarter_kubernetes => jumpstarter-kubernetes}/README.md (100%) rename packages/{jumpstarter_kubernetes => jumpstarter-kubernetes}/jumpstarter_kubernetes/__init__.py (100%) rename packages/{jumpstarter_kubernetes => jumpstarter-kubernetes}/jumpstarter_kubernetes/clients.py (100%) rename packages/{jumpstarter_kubernetes => jumpstarter-kubernetes}/jumpstarter_kubernetes/exporters.py (100%) rename packages/{jumpstarter_kubernetes => jumpstarter-kubernetes}/jumpstarter_kubernetes/install.py (100%) rename packages/{jumpstarter_kubernetes => jumpstarter-kubernetes}/jumpstarter_kubernetes/leases.py (100%) rename packages/{jumpstarter_kubernetes => jumpstarter-kubernetes}/jumpstarter_kubernetes/util/__init__.py (100%) rename packages/{jumpstarter_kubernetes => jumpstarter-kubernetes}/jumpstarter_kubernetes/util/async_custom_object_api.py (100%) rename packages/{jumpstarter_kubernetes => jumpstarter-kubernetes}/pyproject.toml (100%) rename packages/{jumpstarter_protocol => jumpstarter-protocol}/README.md (100%) rename packages/{jumpstarter_protocol => jumpstarter-protocol}/jumpstarter_protocol/__init__.py (100%) rename packages/{jumpstarter_protocol => jumpstarter-protocol}/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py (100%) rename packages/{jumpstarter_protocol => jumpstarter-protocol}/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py (100%) rename packages/{jumpstarter_protocol => jumpstarter-protocol}/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.py (100%) rename packages/{jumpstarter_protocol => jumpstarter-protocol}/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2_grpc.py (100%) rename packages/{jumpstarter_protocol => jumpstarter-protocol}/jumpstarter_protocol/jumpstarter/v1/router_pb2.py (100%) rename packages/{jumpstarter_protocol => jumpstarter-protocol}/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py (100%) rename packages/{jumpstarter_protocol => jumpstarter-protocol}/pyproject.toml (100%) rename packages/{jumpstarter_testing => jumpstarter-testing}/README.md (100%) rename packages/{jumpstarter_testing => jumpstarter-testing}/conftest.py (100%) rename packages/{jumpstarter_testing => jumpstarter-testing}/jumpstarter_testing/__init__.py (100%) rename packages/{jumpstarter_testing => jumpstarter-testing}/jumpstarter_testing/pytest.py (100%) rename packages/{jumpstarter_testing => jumpstarter-testing}/jumpstarter_testing/pytest_test.py (100%) rename packages/{jumpstarter_testing => jumpstarter-testing}/pyproject.toml (100%) diff --git a/packages/jumpstarter_cli_admin/README.md b/packages/jumpstarter-cli-admin/README.md similarity index 100% rename from packages/jumpstarter_cli_admin/README.md rename to packages/jumpstarter-cli-admin/README.md diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/__init__.py b/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__init__.py similarity index 100% rename from packages/jumpstarter_cli_admin/jumpstarter_cli_admin/__init__.py rename to packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__init__.py diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py b/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py similarity index 100% rename from packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create.py rename to packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py b/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.py similarity index 100% rename from packages/jumpstarter_cli_admin/jumpstarter_cli_admin/create_test.py rename to packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.py diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py b/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/delete.py similarity index 100% rename from packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete.py rename to packages/jumpstarter-cli-admin/jumpstarter_cli_admin/delete.py diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py b/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/delete_test.py similarity index 100% rename from packages/jumpstarter_cli_admin/jumpstarter_cli_admin/delete_test.py rename to packages/jumpstarter-cli-admin/jumpstarter_cli_admin/delete_test.py diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get.py b/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py similarity index 100% rename from packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get.py rename to packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get_test.py b/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get_test.py similarity index 100% rename from packages/jumpstarter_cli_admin/jumpstarter_cli_admin/get_test.py rename to packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get_test.py diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py b/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res.py similarity index 100% rename from packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res.py rename to packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res.py diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py b/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res_test.py similarity index 100% rename from packages/jumpstarter_cli_admin/jumpstarter_cli_admin/import_res_test.py rename to packages/jumpstarter-cli-admin/jumpstarter_cli_admin/import_res_test.py diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/install.py b/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py similarity index 100% rename from packages/jumpstarter_cli_admin/jumpstarter_cli_admin/install.py rename to packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py diff --git a/packages/jumpstarter_cli_admin/jumpstarter_cli_admin/k8s.py b/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/k8s.py similarity index 100% rename from packages/jumpstarter_cli_admin/jumpstarter_cli_admin/k8s.py rename to packages/jumpstarter-cli-admin/jumpstarter_cli_admin/k8s.py diff --git a/packages/jumpstarter_cli_admin/pyproject.toml b/packages/jumpstarter-cli-admin/pyproject.toml similarity index 100% rename from packages/jumpstarter_cli_admin/pyproject.toml rename to packages/jumpstarter-cli-admin/pyproject.toml diff --git a/packages/jumpstarter_cli_client/README.md b/packages/jumpstarter-cli-client/README.md similarity index 100% rename from packages/jumpstarter_cli_client/README.md rename to packages/jumpstarter-cli-client/README.md diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py b/packages/jumpstarter-cli-client/jumpstarter_cli_client/__init__.py similarity index 100% rename from packages/jumpstarter_cli_client/jumpstarter_cli_client/__init__.py rename to packages/jumpstarter-cli-client/jumpstarter_cli_client/__init__.py diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py b/packages/jumpstarter-cli-client/jumpstarter_cli_client/client_config.py similarity index 100% rename from packages/jumpstarter_cli_client/jumpstarter_cli_client/client_config.py rename to packages/jumpstarter-cli-client/jumpstarter_cli_client/client_config.py diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py b/packages/jumpstarter-cli-client/jumpstarter_cli_client/client_shell.py similarity index 100% rename from packages/jumpstarter_cli_client/jumpstarter_cli_client/client_shell.py rename to packages/jumpstarter-cli-client/jumpstarter_cli_client/client_shell.py diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py b/packages/jumpstarter-cli-client/jumpstarter_cli_client/client_test.py similarity index 100% rename from packages/jumpstarter_cli_client/jumpstarter_cli_client/client_test.py rename to packages/jumpstarter-cli-client/jumpstarter_cli_client/client_test.py diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/j.py b/packages/jumpstarter-cli-client/jumpstarter_cli_client/j.py similarity index 100% rename from packages/jumpstarter_cli_client/jumpstarter_cli_client/j.py rename to packages/jumpstarter-cli-client/jumpstarter_cli_client/j.py diff --git a/packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py b/packages/jumpstarter-cli-client/jumpstarter_cli_client/lease.py similarity index 100% rename from packages/jumpstarter_cli_client/jumpstarter_cli_client/lease.py rename to packages/jumpstarter-cli-client/jumpstarter_cli_client/lease.py diff --git a/packages/jumpstarter_cli_client/pyproject.toml b/packages/jumpstarter-cli-client/pyproject.toml similarity index 100% rename from packages/jumpstarter_cli_client/pyproject.toml rename to packages/jumpstarter-cli-client/pyproject.toml diff --git a/packages/jumpstarter_cli_common/README.md b/packages/jumpstarter-cli-common/README.md similarity index 100% rename from packages/jumpstarter_cli_common/README.md rename to packages/jumpstarter-cli-common/README.md diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/__init__.py b/packages/jumpstarter-cli-common/jumpstarter_cli_common/__init__.py similarity index 100% rename from packages/jumpstarter_cli_common/jumpstarter_cli_common/__init__.py rename to packages/jumpstarter-cli-common/jumpstarter_cli_common/__init__.py diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/alias.py b/packages/jumpstarter-cli-common/jumpstarter_cli_common/alias.py similarity index 100% rename from packages/jumpstarter_cli_common/jumpstarter_cli_common/alias.py rename to packages/jumpstarter-cli-common/jumpstarter_cli_common/alias.py diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/opt.py b/packages/jumpstarter-cli-common/jumpstarter_cli_common/opt.py similarity index 100% rename from packages/jumpstarter_cli_common/jumpstarter_cli_common/opt.py rename to packages/jumpstarter-cli-common/jumpstarter_cli_common/opt.py diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/table.py b/packages/jumpstarter-cli-common/jumpstarter_cli_common/table.py similarity index 100% rename from packages/jumpstarter_cli_common/jumpstarter_cli_common/table.py rename to packages/jumpstarter-cli-common/jumpstarter_cli_common/table.py diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/table_test.py b/packages/jumpstarter-cli-common/jumpstarter_cli_common/table_test.py similarity index 100% rename from packages/jumpstarter_cli_common/jumpstarter_cli_common/table_test.py rename to packages/jumpstarter-cli-common/jumpstarter_cli_common/table_test.py diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/time.py b/packages/jumpstarter-cli-common/jumpstarter_cli_common/time.py similarity index 100% rename from packages/jumpstarter_cli_common/jumpstarter_cli_common/time.py rename to packages/jumpstarter-cli-common/jumpstarter_cli_common/time.py diff --git a/packages/jumpstarter_cli_common/jumpstarter_cli_common/version.py b/packages/jumpstarter-cli-common/jumpstarter_cli_common/version.py similarity index 100% rename from packages/jumpstarter_cli_common/jumpstarter_cli_common/version.py rename to packages/jumpstarter-cli-common/jumpstarter_cli_common/version.py diff --git a/packages/jumpstarter_cli_common/pyproject.toml b/packages/jumpstarter-cli-common/pyproject.toml similarity index 100% rename from packages/jumpstarter_cli_common/pyproject.toml rename to packages/jumpstarter-cli-common/pyproject.toml diff --git a/packages/jumpstarter_cli_exporter/README.md b/packages/jumpstarter-cli-exporter/README.md similarity index 100% rename from packages/jumpstarter_cli_exporter/README.md rename to packages/jumpstarter-cli-exporter/README.md diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/__init__.py b/packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/__init__.py similarity index 100% rename from packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/__init__.py rename to packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/__init__.py diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py b/packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter.py similarity index 100% rename from packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter.py rename to packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter.py diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py b/packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter_config.py similarity index 100% rename from packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_config.py rename to packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter_config.py diff --git a/packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py b/packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter_test.py similarity index 100% rename from packages/jumpstarter_cli_exporter/jumpstarter_cli_exporter/exporter_test.py rename to packages/jumpstarter-cli-exporter/jumpstarter_cli_exporter/exporter_test.py diff --git a/packages/jumpstarter_cli_exporter/pyproject.toml b/packages/jumpstarter-cli-exporter/pyproject.toml similarity index 100% rename from packages/jumpstarter_cli_exporter/pyproject.toml rename to packages/jumpstarter-cli-exporter/pyproject.toml diff --git a/packages/jumpstarter_cli/README.md b/packages/jumpstarter-cli/README.md similarity index 100% rename from packages/jumpstarter_cli/README.md rename to packages/jumpstarter-cli/README.md diff --git a/packages/jumpstarter_cli/jumpstarter_cli/__init__.py b/packages/jumpstarter-cli/jumpstarter_cli/__init__.py similarity index 100% rename from packages/jumpstarter_cli/jumpstarter_cli/__init__.py rename to packages/jumpstarter-cli/jumpstarter_cli/__init__.py diff --git a/packages/jumpstarter_cli/jumpstarter_cli/__main__.py b/packages/jumpstarter-cli/jumpstarter_cli/__main__.py similarity index 100% rename from packages/jumpstarter_cli/jumpstarter_cli/__main__.py rename to packages/jumpstarter-cli/jumpstarter_cli/__main__.py diff --git a/packages/jumpstarter_cli/jumpstarter_cli/cli_test.py b/packages/jumpstarter-cli/jumpstarter_cli/cli_test.py similarity index 100% rename from packages/jumpstarter_cli/jumpstarter_cli/cli_test.py rename to packages/jumpstarter-cli/jumpstarter_cli/cli_test.py diff --git a/packages/jumpstarter_cli/pyproject.toml b/packages/jumpstarter-cli/pyproject.toml similarity index 100% rename from packages/jumpstarter_cli/pyproject.toml rename to packages/jumpstarter-cli/pyproject.toml diff --git a/packages/jumpstarter_driver_can/README.md b/packages/jumpstarter-driver-can/README.md similarity index 100% rename from packages/jumpstarter_driver_can/README.md rename to packages/jumpstarter-driver-can/README.md diff --git a/packages/jumpstarter_driver_can/jumpstarter_driver_can/__init__.py b/packages/jumpstarter-driver-can/jumpstarter_driver_can/__init__.py similarity index 100% rename from packages/jumpstarter_driver_can/jumpstarter_driver_can/__init__.py rename to packages/jumpstarter-driver-can/jumpstarter_driver_can/__init__.py diff --git a/packages/jumpstarter_driver_can/jumpstarter_driver_can/client.py b/packages/jumpstarter-driver-can/jumpstarter_driver_can/client.py similarity index 100% rename from packages/jumpstarter_driver_can/jumpstarter_driver_can/client.py rename to packages/jumpstarter-driver-can/jumpstarter_driver_can/client.py diff --git a/packages/jumpstarter_driver_can/jumpstarter_driver_can/client_test.py b/packages/jumpstarter-driver-can/jumpstarter_driver_can/client_test.py similarity index 100% rename from packages/jumpstarter_driver_can/jumpstarter_driver_can/client_test.py rename to packages/jumpstarter-driver-can/jumpstarter_driver_can/client_test.py diff --git a/packages/jumpstarter_driver_can/jumpstarter_driver_can/common.py b/packages/jumpstarter-driver-can/jumpstarter_driver_can/common.py similarity index 100% rename from packages/jumpstarter_driver_can/jumpstarter_driver_can/common.py rename to packages/jumpstarter-driver-can/jumpstarter_driver_can/common.py diff --git a/packages/jumpstarter_driver_can/jumpstarter_driver_can/driver.py b/packages/jumpstarter-driver-can/jumpstarter_driver_can/driver.py similarity index 100% rename from packages/jumpstarter_driver_can/jumpstarter_driver_can/driver.py rename to packages/jumpstarter-driver-can/jumpstarter_driver_can/driver.py diff --git a/packages/jumpstarter_driver_can/pyproject.toml b/packages/jumpstarter-driver-can/pyproject.toml similarity index 97% rename from packages/jumpstarter_driver_can/pyproject.toml rename to packages/jumpstarter-driver-can/pyproject.toml index 4162bae1f..a429a2aa9 100644 --- a/packages/jumpstarter_driver_can/pyproject.toml +++ b/packages/jumpstarter-driver-can/pyproject.toml @@ -12,7 +12,7 @@ license = { text = "Apache-2.0" } requires-python = ">=3.11" dependencies = [ "jumpstarter", - "python-can>=4.4.2", + "python-can>=4.5.0", "can-isotp>=2.0.6", ] diff --git a/packages/jumpstarter_driver_composite/README.md b/packages/jumpstarter-driver-composite/README.md similarity index 100% rename from packages/jumpstarter_driver_composite/README.md rename to packages/jumpstarter-driver-composite/README.md diff --git a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/__init__.py b/packages/jumpstarter-driver-composite/jumpstarter_driver_composite/__init__.py similarity index 100% rename from packages/jumpstarter_driver_composite/jumpstarter_driver_composite/__init__.py rename to packages/jumpstarter-driver-composite/jumpstarter_driver_composite/__init__.py diff --git a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py b/packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py similarity index 100% rename from packages/jumpstarter_driver_composite/jumpstarter_driver_composite/client.py rename to packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py diff --git a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py b/packages/jumpstarter-driver-composite/jumpstarter_driver_composite/driver.py similarity index 100% rename from packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver.py rename to packages/jumpstarter-driver-composite/jumpstarter_driver_composite/driver.py diff --git a/packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py b/packages/jumpstarter-driver-composite/jumpstarter_driver_composite/driver_test.py similarity index 100% rename from packages/jumpstarter_driver_composite/jumpstarter_driver_composite/driver_test.py rename to packages/jumpstarter-driver-composite/jumpstarter_driver_composite/driver_test.py diff --git a/packages/jumpstarter_driver_composite/pyproject.toml b/packages/jumpstarter-driver-composite/pyproject.toml similarity index 100% rename from packages/jumpstarter_driver_composite/pyproject.toml rename to packages/jumpstarter-driver-composite/pyproject.toml diff --git a/packages/jumpstarter_driver_dutlink/README.md b/packages/jumpstarter-driver-dutlink/README.md similarity index 100% rename from packages/jumpstarter_driver_dutlink/README.md rename to packages/jumpstarter-driver-dutlink/README.md diff --git a/packages/jumpstarter_driver_dutlink/examples/dutlink.py b/packages/jumpstarter-driver-dutlink/examples/dutlink.py similarity index 100% rename from packages/jumpstarter_driver_dutlink/examples/dutlink.py rename to packages/jumpstarter-driver-dutlink/examples/dutlink.py diff --git a/packages/jumpstarter_driver_dutlink/examples/exporter.yaml b/packages/jumpstarter-driver-dutlink/examples/exporter.yaml similarity index 100% rename from packages/jumpstarter_driver_dutlink/examples/exporter.yaml rename to packages/jumpstarter-driver-dutlink/examples/exporter.yaml diff --git a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/__init__.py b/packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/__init__.py similarity index 100% rename from packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/__init__.py rename to packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/__init__.py diff --git a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py b/packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver.py similarity index 100% rename from packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver.py rename to packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver.py diff --git a/packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py b/packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver_test.py similarity index 100% rename from packages/jumpstarter_driver_dutlink/jumpstarter_driver_dutlink/driver_test.py rename to packages/jumpstarter-driver-dutlink/jumpstarter_driver_dutlink/driver_test.py diff --git a/packages/jumpstarter_driver_dutlink/pyproject.toml b/packages/jumpstarter-driver-dutlink/pyproject.toml similarity index 100% rename from packages/jumpstarter_driver_dutlink/pyproject.toml rename to packages/jumpstarter-driver-dutlink/pyproject.toml diff --git a/packages/jumpstarter_driver_http/README.md b/packages/jumpstarter-driver-http/README.md similarity index 100% rename from packages/jumpstarter_driver_http/README.md rename to packages/jumpstarter-driver-http/README.md diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/__init__.py b/packages/jumpstarter-driver-http/jumpstarter_driver_http/__init__.py similarity index 100% rename from packages/jumpstarter_driver_http/jumpstarter_driver_http/__init__.py rename to packages/jumpstarter-driver-http/jumpstarter_driver_http/__init__.py diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py b/packages/jumpstarter-driver-http/jumpstarter_driver_http/client.py similarity index 100% rename from packages/jumpstarter_driver_http/jumpstarter_driver_http/client.py rename to packages/jumpstarter-driver-http/jumpstarter_driver_http/client.py diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py b/packages/jumpstarter-driver-http/jumpstarter_driver_http/driver.py similarity index 100% rename from packages/jumpstarter_driver_http/jumpstarter_driver_http/driver.py rename to packages/jumpstarter-driver-http/jumpstarter_driver_http/driver.py diff --git a/packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py b/packages/jumpstarter-driver-http/jumpstarter_driver_http/driver_test.py similarity index 100% rename from packages/jumpstarter_driver_http/jumpstarter_driver_http/driver_test.py rename to packages/jumpstarter-driver-http/jumpstarter_driver_http/driver_test.py diff --git a/packages/jumpstarter_driver_http/pyproject.toml b/packages/jumpstarter-driver-http/pyproject.toml similarity index 100% rename from packages/jumpstarter_driver_http/pyproject.toml rename to packages/jumpstarter-driver-http/pyproject.toml diff --git a/packages/jumpstarter_driver_network/README.md b/packages/jumpstarter-driver-network/README.md similarity index 100% rename from packages/jumpstarter_driver_network/README.md rename to packages/jumpstarter-driver-network/README.md diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/__init__.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/__init__.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/__init__.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/__init__.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/__init__.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/__init__.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/__init__.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/__init__.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/fabric.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/fabric.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/fabric_test.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/fabric_test.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/fabric_test.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/novnc.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/novnc.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/novnc_test.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/novnc_test.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/novnc_test.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/pexpect.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/pexpect.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/pexpect.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/pexpect.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/portforward.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/portforward.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/adapters/portforward.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/portforward.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/client.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/client.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/client.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/client.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/driver.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/driver.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/driver_test.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/driver_test.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/streams/__init__.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/__init__.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/streams/__init__.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/__init__.py diff --git a/packages/jumpstarter_driver_network/jumpstarter_driver_network/streams/websocket.py b/packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py similarity index 100% rename from packages/jumpstarter_driver_network/jumpstarter_driver_network/streams/websocket.py rename to packages/jumpstarter-driver-network/jumpstarter_driver_network/streams/websocket.py diff --git a/packages/jumpstarter_driver_network/pyproject.toml b/packages/jumpstarter-driver-network/pyproject.toml similarity index 100% rename from packages/jumpstarter_driver_network/pyproject.toml rename to packages/jumpstarter-driver-network/pyproject.toml diff --git a/packages/jumpstarter_driver_opendal/README.md b/packages/jumpstarter-driver-opendal/README.md similarity index 100% rename from packages/jumpstarter_driver_opendal/README.md rename to packages/jumpstarter-driver-opendal/README.md diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/__init__.py b/packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/__init__.py similarity index 100% rename from packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/__init__.py rename to packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/__init__.py diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py b/packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/adapter.py similarity index 100% rename from packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/adapter.py rename to packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/adapter.py diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py b/packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/client.py similarity index 100% rename from packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/client.py rename to packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/client.py diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py b/packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/driver.py similarity index 100% rename from packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver.py rename to packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/driver.py diff --git a/packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py b/packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/driver_test.py similarity index 100% rename from packages/jumpstarter_driver_opendal/jumpstarter_driver_opendal/driver_test.py rename to packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/driver_test.py diff --git a/packages/jumpstarter_driver_opendal/pyproject.toml b/packages/jumpstarter-driver-opendal/pyproject.toml similarity index 100% rename from packages/jumpstarter_driver_opendal/pyproject.toml rename to packages/jumpstarter-driver-opendal/pyproject.toml diff --git a/packages/jumpstarter_driver_power/README.md b/packages/jumpstarter-driver-power/README.md similarity index 100% rename from packages/jumpstarter_driver_power/README.md rename to packages/jumpstarter-driver-power/README.md diff --git a/packages/jumpstarter_driver_power/jumpstarter_driver_power/__init__.py b/packages/jumpstarter-driver-power/jumpstarter_driver_power/__init__.py similarity index 100% rename from packages/jumpstarter_driver_power/jumpstarter_driver_power/__init__.py rename to packages/jumpstarter-driver-power/jumpstarter_driver_power/__init__.py diff --git a/packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py b/packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py similarity index 100% rename from packages/jumpstarter_driver_power/jumpstarter_driver_power/client.py rename to packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py diff --git a/packages/jumpstarter_driver_power/jumpstarter_driver_power/client_test.py b/packages/jumpstarter-driver-power/jumpstarter_driver_power/client_test.py similarity index 100% rename from packages/jumpstarter_driver_power/jumpstarter_driver_power/client_test.py rename to packages/jumpstarter-driver-power/jumpstarter_driver_power/client_test.py diff --git a/packages/jumpstarter_driver_power/jumpstarter_driver_power/common.py b/packages/jumpstarter-driver-power/jumpstarter_driver_power/common.py similarity index 100% rename from packages/jumpstarter_driver_power/jumpstarter_driver_power/common.py rename to packages/jumpstarter-driver-power/jumpstarter_driver_power/common.py diff --git a/packages/jumpstarter_driver_power/jumpstarter_driver_power/driver.py b/packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py similarity index 100% rename from packages/jumpstarter_driver_power/jumpstarter_driver_power/driver.py rename to packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py diff --git a/packages/jumpstarter_driver_power/jumpstarter_driver_power/driver_test.py b/packages/jumpstarter-driver-power/jumpstarter_driver_power/driver_test.py similarity index 100% rename from packages/jumpstarter_driver_power/jumpstarter_driver_power/driver_test.py rename to packages/jumpstarter-driver-power/jumpstarter_driver_power/driver_test.py diff --git a/packages/jumpstarter_driver_power/pyproject.toml b/packages/jumpstarter-driver-power/pyproject.toml similarity index 100% rename from packages/jumpstarter_driver_power/pyproject.toml rename to packages/jumpstarter-driver-power/pyproject.toml diff --git a/packages/jumpstarter_driver_pyserial/README.md b/packages/jumpstarter-driver-pyserial/README.md similarity index 100% rename from packages/jumpstarter_driver_pyserial/README.md rename to packages/jumpstarter-driver-pyserial/README.md diff --git a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/__init__.py b/packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/__init__.py similarity index 100% rename from packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/__init__.py rename to packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/__init__.py diff --git a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py b/packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/client.py similarity index 100% rename from packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/client.py rename to packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/client.py diff --git a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/console.py b/packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/console.py similarity index 100% rename from packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/console.py rename to packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/console.py diff --git a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py b/packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py similarity index 100% rename from packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver.py rename to packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver.py diff --git a/packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver_test.py b/packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver_test.py similarity index 100% rename from packages/jumpstarter_driver_pyserial/jumpstarter_driver_pyserial/driver_test.py rename to packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/driver_test.py diff --git a/packages/jumpstarter_driver_pyserial/pyproject.toml b/packages/jumpstarter-driver-pyserial/pyproject.toml similarity index 100% rename from packages/jumpstarter_driver_pyserial/pyproject.toml rename to packages/jumpstarter-driver-pyserial/pyproject.toml diff --git a/packages/jumpstarter_driver_raspberrypi/README.md b/packages/jumpstarter-driver-raspberrypi/README.md similarity index 100% rename from packages/jumpstarter_driver_raspberrypi/README.md rename to packages/jumpstarter-driver-raspberrypi/README.md diff --git a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/__init__.py b/packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/__init__.py similarity index 100% rename from packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/__init__.py rename to packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/__init__.py diff --git a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/client.py b/packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/client.py similarity index 100% rename from packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/client.py rename to packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/client.py diff --git a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py b/packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/driver.py similarity index 100% rename from packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver.py rename to packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/driver.py diff --git a/packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py b/packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py similarity index 100% rename from packages/jumpstarter_driver_raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py rename to packages/jumpstarter-driver-raspberrypi/jumpstarter_driver_raspberrypi/driver_test.py diff --git a/packages/jumpstarter_driver_raspberrypi/pyproject.toml b/packages/jumpstarter-driver-raspberrypi/pyproject.toml similarity index 100% rename from packages/jumpstarter_driver_raspberrypi/pyproject.toml rename to packages/jumpstarter-driver-raspberrypi/pyproject.toml diff --git a/packages/jumpstarter_driver_sdwire/README.md b/packages/jumpstarter-driver-sdwire/README.md similarity index 100% rename from packages/jumpstarter_driver_sdwire/README.md rename to packages/jumpstarter-driver-sdwire/README.md diff --git a/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/__init__.py b/packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/__init__.py similarity index 100% rename from packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/__init__.py rename to packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/__init__.py diff --git a/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py b/packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/driver.py similarity index 100% rename from packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver.py rename to packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/driver.py diff --git a/packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py b/packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/driver_test.py similarity index 100% rename from packages/jumpstarter_driver_sdwire/jumpstarter_driver_sdwire/driver_test.py rename to packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/driver_test.py diff --git a/packages/jumpstarter_driver_sdwire/pyproject.toml b/packages/jumpstarter-driver-sdwire/pyproject.toml similarity index 100% rename from packages/jumpstarter_driver_sdwire/pyproject.toml rename to packages/jumpstarter-driver-sdwire/pyproject.toml diff --git a/packages/jumpstarter_driver_tftp/README.md b/packages/jumpstarter-driver-tftp/README.md similarity index 100% rename from packages/jumpstarter_driver_tftp/README.md rename to packages/jumpstarter-driver-tftp/README.md diff --git a/packages/jumpstarter_driver_tftp/examples/exporter.yaml b/packages/jumpstarter-driver-tftp/examples/exporter.yaml similarity index 100% rename from packages/jumpstarter_driver_tftp/examples/exporter.yaml rename to packages/jumpstarter-driver-tftp/examples/exporter.yaml diff --git a/packages/jumpstarter_driver_tftp/examples/tftp_test.py b/packages/jumpstarter-driver-tftp/examples/tftp_test.py similarity index 100% rename from packages/jumpstarter_driver_tftp/examples/tftp_test.py rename to packages/jumpstarter-driver-tftp/examples/tftp_test.py diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/__init__.py b/packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/__init__.py similarity index 100% rename from packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/__init__.py rename to packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/__init__.py diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py b/packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/client.py similarity index 100% rename from packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/client.py rename to packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/client.py diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py b/packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/driver.py similarity index 100% rename from packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver.py rename to packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/driver.py diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py b/packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/driver_test.py similarity index 100% rename from packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/driver_test.py rename to packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/driver_test.py diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py b/packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/server.py similarity index 100% rename from packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server.py rename to packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/server.py diff --git a/packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server_test.py b/packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/server_test.py similarity index 100% rename from packages/jumpstarter_driver_tftp/jumpstarter_driver_tftp/server_test.py rename to packages/jumpstarter-driver-tftp/jumpstarter_driver_tftp/server_test.py diff --git a/packages/jumpstarter_driver_tftp/pyproject.toml b/packages/jumpstarter-driver-tftp/pyproject.toml similarity index 100% rename from packages/jumpstarter_driver_tftp/pyproject.toml rename to packages/jumpstarter-driver-tftp/pyproject.toml diff --git a/packages/jumpstarter_driver_tftp/test.txt b/packages/jumpstarter-driver-tftp/test.txt similarity index 100% rename from packages/jumpstarter_driver_tftp/test.txt rename to packages/jumpstarter-driver-tftp/test.txt diff --git a/packages/jumpstarter_driver_ustreamer/README.md b/packages/jumpstarter-driver-ustreamer/README.md similarity index 100% rename from packages/jumpstarter_driver_ustreamer/README.md rename to packages/jumpstarter-driver-ustreamer/README.md diff --git a/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/__init__.py b/packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/__init__.py similarity index 100% rename from packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/__init__.py rename to packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/__init__.py diff --git a/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/client.py b/packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/client.py similarity index 100% rename from packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/client.py rename to packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/client.py diff --git a/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/common.py b/packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/common.py similarity index 100% rename from packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/common.py rename to packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/common.py diff --git a/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver.py b/packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/driver.py similarity index 100% rename from packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver.py rename to packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/driver.py diff --git a/packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver_test.py b/packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/driver_test.py similarity index 100% rename from packages/jumpstarter_driver_ustreamer/jumpstarter_driver_ustreamer/driver_test.py rename to packages/jumpstarter-driver-ustreamer/jumpstarter_driver_ustreamer/driver_test.py diff --git a/packages/jumpstarter_driver_ustreamer/pyproject.toml b/packages/jumpstarter-driver-ustreamer/pyproject.toml similarity index 100% rename from packages/jumpstarter_driver_ustreamer/pyproject.toml rename to packages/jumpstarter-driver-ustreamer/pyproject.toml diff --git a/packages/jumpstarter_imagehash/README.md b/packages/jumpstarter-imagehash/README.md similarity index 100% rename from packages/jumpstarter_imagehash/README.md rename to packages/jumpstarter-imagehash/README.md diff --git a/packages/jumpstarter_imagehash/jumpstarter_imagehash/__init__.py b/packages/jumpstarter-imagehash/jumpstarter_imagehash/__init__.py similarity index 100% rename from packages/jumpstarter_imagehash/jumpstarter_imagehash/__init__.py rename to packages/jumpstarter-imagehash/jumpstarter_imagehash/__init__.py diff --git a/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py b/packages/jumpstarter-imagehash/jumpstarter_imagehash/imagehash.py similarity index 100% rename from packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash.py rename to packages/jumpstarter-imagehash/jumpstarter_imagehash/imagehash.py diff --git a/packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash_test.py b/packages/jumpstarter-imagehash/jumpstarter_imagehash/imagehash_test.py similarity index 100% rename from packages/jumpstarter_imagehash/jumpstarter_imagehash/imagehash_test.py rename to packages/jumpstarter-imagehash/jumpstarter_imagehash/imagehash_test.py diff --git a/packages/jumpstarter_imagehash/jumpstarter_imagehash/test_image_a.jpeg b/packages/jumpstarter-imagehash/jumpstarter_imagehash/test_image_a.jpeg similarity index 100% rename from packages/jumpstarter_imagehash/jumpstarter_imagehash/test_image_a.jpeg rename to packages/jumpstarter-imagehash/jumpstarter_imagehash/test_image_a.jpeg diff --git a/packages/jumpstarter_imagehash/jumpstarter_imagehash/test_image_b.jpeg b/packages/jumpstarter-imagehash/jumpstarter_imagehash/test_image_b.jpeg similarity index 100% rename from packages/jumpstarter_imagehash/jumpstarter_imagehash/test_image_b.jpeg rename to packages/jumpstarter-imagehash/jumpstarter_imagehash/test_image_b.jpeg diff --git a/packages/jumpstarter_imagehash/pyproject.toml b/packages/jumpstarter-imagehash/pyproject.toml similarity index 100% rename from packages/jumpstarter_imagehash/pyproject.toml rename to packages/jumpstarter-imagehash/pyproject.toml diff --git a/packages/jumpstarter_kubernetes/README.md b/packages/jumpstarter-kubernetes/README.md similarity index 100% rename from packages/jumpstarter_kubernetes/README.md rename to packages/jumpstarter-kubernetes/README.md diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/__init__.py b/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/__init__.py similarity index 100% rename from packages/jumpstarter_kubernetes/jumpstarter_kubernetes/__init__.py rename to packages/jumpstarter-kubernetes/jumpstarter_kubernetes/__init__.py diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py b/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py similarity index 100% rename from packages/jumpstarter_kubernetes/jumpstarter_kubernetes/clients.py rename to packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients.py diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py b/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py similarity index 100% rename from packages/jumpstarter_kubernetes/jumpstarter_kubernetes/exporters.py rename to packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exporters.py diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/install.py b/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.py similarity index 100% rename from packages/jumpstarter_kubernetes/jumpstarter_kubernetes/install.py rename to packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.py diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/leases.py b/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py similarity index 100% rename from packages/jumpstarter_kubernetes/jumpstarter_kubernetes/leases.py rename to packages/jumpstarter-kubernetes/jumpstarter_kubernetes/leases.py diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/util/__init__.py b/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/util/__init__.py similarity index 100% rename from packages/jumpstarter_kubernetes/jumpstarter_kubernetes/util/__init__.py rename to packages/jumpstarter-kubernetes/jumpstarter_kubernetes/util/__init__.py diff --git a/packages/jumpstarter_kubernetes/jumpstarter_kubernetes/util/async_custom_object_api.py b/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/util/async_custom_object_api.py similarity index 100% rename from packages/jumpstarter_kubernetes/jumpstarter_kubernetes/util/async_custom_object_api.py rename to packages/jumpstarter-kubernetes/jumpstarter_kubernetes/util/async_custom_object_api.py diff --git a/packages/jumpstarter_kubernetes/pyproject.toml b/packages/jumpstarter-kubernetes/pyproject.toml similarity index 100% rename from packages/jumpstarter_kubernetes/pyproject.toml rename to packages/jumpstarter-kubernetes/pyproject.toml diff --git a/packages/jumpstarter_protocol/README.md b/packages/jumpstarter-protocol/README.md similarity index 100% rename from packages/jumpstarter_protocol/README.md rename to packages/jumpstarter-protocol/README.md diff --git a/packages/jumpstarter_protocol/jumpstarter_protocol/__init__.py b/packages/jumpstarter-protocol/jumpstarter_protocol/__init__.py similarity index 100% rename from packages/jumpstarter_protocol/jumpstarter_protocol/__init__.py rename to packages/jumpstarter-protocol/jumpstarter_protocol/__init__.py diff --git a/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py b/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py similarity index 100% rename from packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py rename to packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py diff --git a/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py b/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py similarity index 100% rename from packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py rename to packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py diff --git a/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.py b/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.py similarity index 100% rename from packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.py rename to packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.py diff --git a/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2_grpc.py b/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2_grpc.py similarity index 100% rename from packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2_grpc.py rename to packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2_grpc.py diff --git a/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.py b/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.py similarity index 100% rename from packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.py rename to packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.py diff --git a/packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py b/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py similarity index 100% rename from packages/jumpstarter_protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py rename to packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py diff --git a/packages/jumpstarter_protocol/pyproject.toml b/packages/jumpstarter-protocol/pyproject.toml similarity index 100% rename from packages/jumpstarter_protocol/pyproject.toml rename to packages/jumpstarter-protocol/pyproject.toml diff --git a/packages/jumpstarter_testing/README.md b/packages/jumpstarter-testing/README.md similarity index 100% rename from packages/jumpstarter_testing/README.md rename to packages/jumpstarter-testing/README.md diff --git a/packages/jumpstarter_testing/conftest.py b/packages/jumpstarter-testing/conftest.py similarity index 100% rename from packages/jumpstarter_testing/conftest.py rename to packages/jumpstarter-testing/conftest.py diff --git a/packages/jumpstarter_testing/jumpstarter_testing/__init__.py b/packages/jumpstarter-testing/jumpstarter_testing/__init__.py similarity index 100% rename from packages/jumpstarter_testing/jumpstarter_testing/__init__.py rename to packages/jumpstarter-testing/jumpstarter_testing/__init__.py diff --git a/packages/jumpstarter_testing/jumpstarter_testing/pytest.py b/packages/jumpstarter-testing/jumpstarter_testing/pytest.py similarity index 100% rename from packages/jumpstarter_testing/jumpstarter_testing/pytest.py rename to packages/jumpstarter-testing/jumpstarter_testing/pytest.py diff --git a/packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py b/packages/jumpstarter-testing/jumpstarter_testing/pytest_test.py similarity index 100% rename from packages/jumpstarter_testing/jumpstarter_testing/pytest_test.py rename to packages/jumpstarter-testing/jumpstarter_testing/pytest_test.py diff --git a/packages/jumpstarter_testing/pyproject.toml b/packages/jumpstarter-testing/pyproject.toml similarity index 100% rename from packages/jumpstarter_testing/pyproject.toml rename to packages/jumpstarter-testing/pyproject.toml diff --git a/uv.lock b/uv.lock index 4de3a0558..6390d1123 100644 --- a/uv.lock +++ b/uv.lock @@ -764,7 +764,7 @@ dev = [ requires-dist = [ { name = "aiohttp", specifier = ">=3.10.5" }, { name = "anyio", specifier = ">=4.4.0,!=4.6.2" }, - { name = "jumpstarter-protocol", editable = "packages/jumpstarter_protocol" }, + { name = "jumpstarter-protocol", editable = "packages/jumpstarter-protocol" }, { name = "pydantic", specifier = ">=2.8.2" }, { name = "pyyaml", specifier = ">=6.0.2" }, { name = "tqdm", specifier = ">=4.66.5" }, @@ -773,9 +773,9 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ { name = "cryptography", specifier = ">=43.0.3" }, - { name = "jumpstarter-driver-composite", editable = "packages/jumpstarter_driver_composite" }, - { name = "jumpstarter-driver-network", editable = "packages/jumpstarter_driver_network" }, - { name = "jumpstarter-driver-power", editable = "packages/jumpstarter_driver_power" }, + { name = "jumpstarter-driver-composite", editable = "packages/jumpstarter-driver-composite" }, + { name = "jumpstarter-driver-network", editable = "packages/jumpstarter-driver-network" }, + { name = "jumpstarter-driver-power", editable = "packages/jumpstarter-driver-power" }, { name = "pytest", specifier = ">=8.3.2" }, { name = "pytest-anyio", specifier = ">=0.0.0" }, { name = "pytest-asyncio", specifier = ">=0.0.0" }, @@ -784,8 +784,7 @@ dev = [ [[package]] name = "jumpstarter-cli" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_cli" } +source = { editable = "packages/jumpstarter-cli" } dependencies = [ { name = "jumpstarter-cli-admin" }, { name = "jumpstarter-cli-client" }, @@ -802,9 +801,9 @@ dev = [ [package.metadata] requires-dist = [ - { name = "jumpstarter-cli-admin", editable = "packages/jumpstarter_cli_admin" }, - { name = "jumpstarter-cli-client", editable = "packages/jumpstarter_cli_client" }, - { name = "jumpstarter-cli-exporter", editable = "packages/jumpstarter_cli_exporter" }, + { name = "jumpstarter-cli-admin", editable = "packages/jumpstarter-cli-admin" }, + { name = "jumpstarter-cli-client", editable = "packages/jumpstarter-cli-client" }, + { name = "jumpstarter-cli-exporter", editable = "packages/jumpstarter-cli-exporter" }, ] [package.metadata.requires-dev] @@ -817,8 +816,7 @@ dev = [ [[package]] name = "jumpstarter-cli-admin" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_cli_admin" } +source = { editable = "packages/jumpstarter-cli-admin" } dependencies = [ { name = "jumpstarter-cli-common" }, { name = "jumpstarter-kubernetes" }, @@ -834,8 +832,8 @@ dev = [ [package.metadata] requires-dist = [ - { name = "jumpstarter-cli-common", editable = "packages/jumpstarter_cli_common" }, - { name = "jumpstarter-kubernetes", editable = "packages/jumpstarter_kubernetes" }, + { name = "jumpstarter-cli-common", editable = "packages/jumpstarter-cli-common" }, + { name = "jumpstarter-kubernetes", editable = "packages/jumpstarter-kubernetes" }, ] [package.metadata.requires-dev] @@ -848,8 +846,7 @@ dev = [ [[package]] name = "jumpstarter-cli-client" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_cli_client" } +source = { editable = "packages/jumpstarter-cli-client" } dependencies = [ { name = "jumpstarter-cli-common" }, ] @@ -863,7 +860,7 @@ dev = [ ] [package.metadata] -requires-dist = [{ name = "jumpstarter-cli-common", editable = "packages/jumpstarter_cli_common" }] +requires-dist = [{ name = "jumpstarter-cli-common", editable = "packages/jumpstarter-cli-common" }] [package.metadata.requires-dev] dev = [ @@ -875,8 +872,7 @@ dev = [ [[package]] name = "jumpstarter-cli-common" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_cli_common" } +source = { editable = "packages/jumpstarter-cli-common" } dependencies = [ { name = "asyncclick" }, { name = "jumpstarter" }, @@ -906,8 +902,7 @@ dev = [ [[package]] name = "jumpstarter-cli-exporter" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_cli_exporter" } +source = { editable = "packages/jumpstarter-cli-exporter" } dependencies = [ { name = "asyncclick" }, { name = "jumpstarter-cli-common" }, @@ -924,7 +919,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "asyncclick", specifier = ">=8.1.7.2" }, - { name = "jumpstarter-cli-common", editable = "packages/jumpstarter_cli_common" }, + { name = "jumpstarter-cli-common", editable = "packages/jumpstarter-cli-common" }, ] [package.metadata.requires-dev] @@ -937,8 +932,7 @@ dev = [ [[package]] name = "jumpstarter-driver-can" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_driver_can" } +source = { editable = "packages/jumpstarter-driver-can" } dependencies = [ { name = "can-isotp" }, { name = "jumpstarter" }, @@ -955,7 +949,7 @@ dev = [ requires-dist = [ { name = "can-isotp", specifier = ">=2.0.6" }, { name = "jumpstarter", editable = "packages/jumpstarter" }, - { name = "python-can", specifier = ">=4.4.2" }, + { name = "python-can", specifier = ">=4.5.0" }, ] [package.metadata.requires-dev] @@ -966,8 +960,7 @@ dev = [ [[package]] name = "jumpstarter-driver-composite" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_driver_composite" } +source = { editable = "packages/jumpstarter-driver-composite" } dependencies = [ { name = "asyncclick" }, { name = "jumpstarter" }, @@ -988,15 +981,14 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ - { name = "jumpstarter-driver-power", editable = "packages/jumpstarter_driver_power" }, + { name = "jumpstarter-driver-power", editable = "packages/jumpstarter-driver-power" }, { name = "pytest", specifier = ">=8.3.2" }, { name = "pytest-cov", specifier = ">=5.0.0" }, ] [[package]] name = "jumpstarter-driver-dutlink" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_driver_dutlink" } +source = { editable = "packages/jumpstarter-driver-dutlink" } dependencies = [ { name = "asyncclick" }, { name = "jumpstarter" }, @@ -1019,11 +1011,11 @@ dev = [ requires-dist = [ { name = "asyncclick", specifier = ">=8.1.7.2" }, { name = "jumpstarter", editable = "packages/jumpstarter" }, - { name = "jumpstarter-driver-composite", editable = "packages/jumpstarter_driver_composite" }, - { name = "jumpstarter-driver-network", editable = "packages/jumpstarter_driver_network" }, - { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter_driver_opendal" }, - { name = "jumpstarter-driver-power", editable = "packages/jumpstarter_driver_power" }, - { name = "jumpstarter-driver-pyserial", editable = "packages/jumpstarter_driver_pyserial" }, + { name = "jumpstarter-driver-composite", editable = "packages/jumpstarter-driver-composite" }, + { name = "jumpstarter-driver-network", editable = "packages/jumpstarter-driver-network" }, + { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter-driver-opendal" }, + { name = "jumpstarter-driver-power", editable = "packages/jumpstarter-driver-power" }, + { name = "jumpstarter-driver-pyserial", editable = "packages/jumpstarter-driver-pyserial" }, { name = "pyudev", specifier = ">=0.24.3" }, { name = "pyusb", specifier = ">=1.2.1" }, ] @@ -1037,7 +1029,7 @@ dev = [ [[package]] name = "jumpstarter-driver-http" version = "0.1.0" -source = { editable = "packages/jumpstarter_driver_http" } +source = { editable = "packages/jumpstarter-driver-http" } dependencies = [ { name = "anyio" }, { name = "jumpstarter" }, @@ -1056,7 +1048,7 @@ dev = [ requires-dist = [ { name = "anyio", specifier = ">=4.6.2.post1" }, { name = "jumpstarter", editable = "packages/jumpstarter" }, - { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter_driver_opendal" }, + { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter-driver-opendal" }, ] [package.metadata.requires-dev] @@ -1070,8 +1062,7 @@ dev = [ [[package]] name = "jumpstarter-driver-network" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_driver_network" } +source = { editable = "packages/jumpstarter-driver-network" } dependencies = [ { name = "fabric" }, { name = "jumpstarter" }, @@ -1103,8 +1094,7 @@ dev = [ [[package]] name = "jumpstarter-driver-opendal" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_driver_opendal" } +source = { editable = "packages/jumpstarter-driver-opendal" } dependencies = [ { name = "asyncclick" }, { name = "jumpstarter" }, @@ -1132,8 +1122,7 @@ dev = [ [[package]] name = "jumpstarter-driver-power" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_driver_power" } +source = { editable = "packages/jumpstarter-driver-power" } dependencies = [ { name = "asyncclick" }, { name = "jumpstarter" }, @@ -1163,8 +1152,7 @@ dev = [ [[package]] name = "jumpstarter-driver-pyserial" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_driver_pyserial" } +source = { editable = "packages/jumpstarter-driver-pyserial" } dependencies = [ { name = "asyncclick" }, { name = "jumpstarter" }, @@ -1182,7 +1170,7 @@ dev = [ requires-dist = [ { name = "asyncclick", specifier = ">=8.1.7.2" }, { name = "jumpstarter", editable = "packages/jumpstarter" }, - { name = "jumpstarter-driver-network", editable = "packages/jumpstarter_driver_network" }, + { name = "jumpstarter-driver-network", editable = "packages/jumpstarter-driver-network" }, { name = "pyserial", specifier = ">=3.5" }, ] @@ -1194,8 +1182,7 @@ dev = [ [[package]] name = "jumpstarter-driver-raspberrypi" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_driver_raspberrypi" } +source = { editable = "packages/jumpstarter-driver-raspberrypi" } dependencies = [ { name = "gpiozero" }, { name = "jumpstarter" }, @@ -1221,8 +1208,7 @@ dev = [ [[package]] name = "jumpstarter-driver-sdwire" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_driver_sdwire" } +source = { editable = "packages/jumpstarter-driver-sdwire" } dependencies = [ { name = "jumpstarter" }, { name = "jumpstarter-driver-opendal" }, @@ -1239,7 +1225,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "jumpstarter", editable = "packages/jumpstarter" }, - { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter_driver_opendal" }, + { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter-driver-opendal" }, { name = "pyudev", specifier = ">=0.24.3" }, { name = "pyusb", specifier = ">=1.2.1" }, ] @@ -1253,7 +1239,7 @@ dev = [ [[package]] name = "jumpstarter-driver-tftp" version = "0.1.0" -source = { editable = "packages/jumpstarter_driver_tftp" } +source = { editable = "packages/jumpstarter-driver-tftp" } dependencies = [ { name = "aiofiles" }, { name = "anyio" }, @@ -1275,12 +1261,12 @@ requires-dist = [ { name = "aiofiles", specifier = ">=24.1.0" }, { name = "anyio", specifier = ">=4.6.2.post1" }, { name = "jumpstarter", editable = "packages/jumpstarter" }, - { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter_driver_opendal" }, + { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter-driver-opendal" }, ] [package.metadata.requires-dev] dev = [ - { name = "jumpstarter-testing", editable = "packages/jumpstarter_testing" }, + { name = "jumpstarter-testing", editable = "packages/jumpstarter-testing" }, { name = "pytest", specifier = ">=8.3.2" }, { name = "pytest-anyio", specifier = ">=0.0.0" }, { name = "pytest-asyncio", specifier = ">=0.0.0" }, @@ -1289,8 +1275,7 @@ dev = [ [[package]] name = "jumpstarter-driver-ustreamer" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_driver_ustreamer" } +source = { editable = "packages/jumpstarter-driver-ustreamer" } dependencies = [ { name = "jumpstarter" }, { name = "pillow" }, @@ -1341,17 +1326,16 @@ dependencies = [ [package.metadata] requires-dist = [ { name = "jumpstarter", editable = "packages/jumpstarter" }, - { name = "jumpstarter-driver-dutlink", editable = "packages/jumpstarter_driver_dutlink" }, - { name = "jumpstarter-driver-network", editable = "packages/jumpstarter_driver_network" }, - { name = "jumpstarter-imagehash", editable = "packages/jumpstarter_imagehash" }, - { name = "jumpstarter-testing", editable = "packages/jumpstarter_testing" }, + { name = "jumpstarter-driver-dutlink", editable = "packages/jumpstarter-driver-dutlink" }, + { name = "jumpstarter-driver-network", editable = "packages/jumpstarter-driver-network" }, + { name = "jumpstarter-imagehash", editable = "packages/jumpstarter-imagehash" }, + { name = "jumpstarter-testing", editable = "packages/jumpstarter-testing" }, { name = "pytest", specifier = ">=8.3.2" }, ] [[package]] name = "jumpstarter-imagehash" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_imagehash" } +source = { editable = "packages/jumpstarter-imagehash" } dependencies = [ { name = "imagehash" }, { name = "jumpstarter" }, @@ -1377,8 +1361,7 @@ dev = [ [[package]] name = "jumpstarter-kubernetes" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_kubernetes" } +source = { editable = "packages/jumpstarter-kubernetes" } dependencies = [ { name = "jumpstarter" }, { name = "kubernetes" }, @@ -1410,8 +1393,7 @@ dev = [ [[package]] name = "jumpstarter-protocol" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_protocol" } +source = { editable = "packages/jumpstarter-protocol" } dependencies = [ { name = "grpcio" }, { name = "protobuf" }, @@ -1441,8 +1423,7 @@ dev = [ [[package]] name = "jumpstarter-testing" -version = "0.5.1.dev113+g07bed5a.d20250123" -source = { editable = "packages/jumpstarter_testing" } +source = { editable = "packages/jumpstarter-testing" } dependencies = [ { name = "jumpstarter" }, { name = "pytest" }, @@ -1466,7 +1447,7 @@ requires-dist = [ ] [package.metadata.requires-dev] -dev = [{ name = "jumpstarter-driver-power", editable = "packages/jumpstarter_driver_power" }] +dev = [{ name = "jumpstarter-driver-power", editable = "packages/jumpstarter-driver-power" }] [[package]] name = "kubernetes" @@ -1593,19 +1574,28 @@ wheels = [ [[package]] name = "msgpack" -version = "1.0.8" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/08/4c/17adf86a8fbb02c144c7569dc4919483c01a2ac270307e2d59e1ce394087/msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3", size = 167014 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/97/73/757eeca26527ebac31d86d35bf4ba20155ee14d35c8619dd96bc80a037f3/msgpack-1.0.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:114be227f5213ef8b215c22dde19532f5da9652e56e8ce969bf0a26d7c419fee", size = 158948 }, - { url = "https://files.pythonhosted.org/packages/11/df/558899a5f90d450e988484be25be0b49c6930858d6fe44ea6f1f66502fe5/msgpack-1.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d661dc4785affa9d0edfdd1e59ec056a58b3dbb9f196fa43587f3ddac654ac7b", size = 88696 }, - { url = "https://files.pythonhosted.org/packages/99/3e/49d430df1e9abf06bb91e9824422cd6ceead2114662417286da3ddcdd295/msgpack-1.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d56fd9f1f1cdc8227d7b7918f55091349741904d9520c65f0139a9755952c9e8", size = 85428 }, - { url = "https://files.pythonhosted.org/packages/54/f7/84828d0c6be6b7f0770777f1a7b1f76f3a78e8b6afb5e4e9c1c9350242be/msgpack-1.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0726c282d188e204281ebd8de31724b7d749adebc086873a59efb8cf7ae27df3", size = 396116 }, - { url = "https://files.pythonhosted.org/packages/04/2a/c833a8503be9030083f0469e7a3c74d3622a3b4eae676c3934d3ccc01036/msgpack-1.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8db8e423192303ed77cff4dce3a4b88dbfaf43979d280181558af5e2c3c71afc", size = 408331 }, - { url = "https://files.pythonhosted.org/packages/04/50/b988d0a8e8835f705e4bbcb6433845ff11dd50083c0aa43e607bb7b2ff96/msgpack-1.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99881222f4a8c2f641f25703963a5cefb076adffd959e0558dc9f803a52d6a58", size = 394182 }, - { url = "https://files.pythonhosted.org/packages/98/e1/0d18496cbeef771db605b6a14794f9b4235d371f36b43f7223c1613969ec/msgpack-1.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b5505774ea2a73a86ea176e8a9a4a7c8bf5d521050f0f6f8426afe798689243f", size = 401226 }, - { url = "https://files.pythonhosted.org/packages/03/79/ae000bde2aee4b9f0d50c1ca1ab301ade873b59dd6968c28f918d1cf8be4/msgpack-1.0.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ef254a06bcea461e65ff0373d8a0dd1ed3aa004af48839f002a0c994a6f72d04", size = 432994 }, - { url = "https://files.pythonhosted.org/packages/cb/46/f97bedf3ab16d38eeea0aafa3ad93cc7b9adf898218961faaea9c3c639f1/msgpack-1.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1dd7839443592d00e96db831eddb4111a2a81a46b028f0facd60a09ebbdd543", size = 410432 }, +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cb/d0/7555686ae7ff5731205df1012ede15dd9d927f6227ea151e901c7406af4f/msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e", size = 167260 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/d6/716b7ca1dbde63290d2973d22bbef1b5032ca634c3ff4384a958ec3f093a/msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d", size = 152421 }, + { url = "https://files.pythonhosted.org/packages/70/da/5312b067f6773429cec2f8f08b021c06af416bba340c912c2ec778539ed6/msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2", size = 85277 }, + { url = "https://files.pythonhosted.org/packages/28/51/da7f3ae4462e8bb98af0d5bdf2707f1b8c65a0d4f496e46b6afb06cbc286/msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420", size = 82222 }, + { url = "https://files.pythonhosted.org/packages/33/af/dc95c4b2a49cff17ce47611ca9ba218198806cad7796c0b01d1e332c86bb/msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2", size = 392971 }, + { url = "https://files.pythonhosted.org/packages/f1/54/65af8de681fa8255402c80eda2a501ba467921d5a7a028c9c22a2c2eedb5/msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39", size = 401403 }, + { url = "https://files.pythonhosted.org/packages/97/8c/e333690777bd33919ab7024269dc3c41c76ef5137b211d776fbb404bfead/msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f", size = 385356 }, + { url = "https://files.pythonhosted.org/packages/57/52/406795ba478dc1c890559dd4e89280fa86506608a28ccf3a72fbf45df9f5/msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247", size = 383028 }, + { url = "https://files.pythonhosted.org/packages/e7/69/053b6549bf90a3acadcd8232eae03e2fefc87f066a5b9fbb37e2e608859f/msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c", size = 391100 }, + { url = "https://files.pythonhosted.org/packages/23/f0/d4101d4da054f04274995ddc4086c2715d9b93111eb9ed49686c0f7ccc8a/msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b", size = 394254 }, + { url = "https://files.pythonhosted.org/packages/c8/b0/380f5f639543a4ac413e969109978feb1f3c66e931068f91ab6ab0f8be00/msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf", size = 151142 }, + { url = "https://files.pythonhosted.org/packages/c8/ee/be57e9702400a6cb2606883d55b05784fada898dfc7fd12608ab1fdb054e/msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330", size = 84523 }, + { url = "https://files.pythonhosted.org/packages/7e/3a/2919f63acca3c119565449681ad08a2f84b2171ddfcff1dba6959db2cceb/msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734", size = 81556 }, + { url = "https://files.pythonhosted.org/packages/7c/43/a11113d9e5c1498c145a8925768ea2d5fce7cbab15c99cda655aa09947ed/msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e", size = 392105 }, + { url = "https://files.pythonhosted.org/packages/2d/7b/2c1d74ca6c94f70a1add74a8393a0138172207dc5de6fc6269483519d048/msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca", size = 399979 }, + { url = "https://files.pythonhosted.org/packages/82/8c/cf64ae518c7b8efc763ca1f1348a96f0e37150061e777a8ea5430b413a74/msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915", size = 383816 }, + { url = "https://files.pythonhosted.org/packages/69/86/a847ef7a0f5ef3fa94ae20f52a4cacf596a4e4a010197fbcc27744eb9a83/msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d", size = 380973 }, + { url = "https://files.pythonhosted.org/packages/aa/90/c74cf6e1126faa93185d3b830ee97246ecc4fe12cf9d2d31318ee4246994/msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434", size = 387435 }, + { url = "https://files.pythonhosted.org/packages/7a/40/631c238f1f338eb09f4acb0f34ab5862c4e9d7eda11c1b685471a4c5ea37/msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c", size = 399082 }, ] [[package]] @@ -2110,18 +2100,17 @@ wheels = [ [[package]] name = "python-can" -version = "4.4.2" +version = "4.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "msgpack", marker = "sys_platform != 'win32'" }, { name = "packaging" }, - { name = "pywin32", marker = "platform_python_implementation == 'CPython' and sys_platform == 'win32'" }, { name = "typing-extensions" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a3/17/57c38abbf00993ac5ec306de0c00271685d1372ef3d907b107eb63ab13a8/python_can-4.4.2.tar.gz", hash = "sha256:1c46c0935f39f7a9c3e76b03249af0580689ebf7a1844195e92f87257f009df5", size = 345568 } +sdist = { url = "https://files.pythonhosted.org/packages/6a/4b/b6fd103c3f2eb0ae942e0704642d396ebbaf87f4d82d0102560cc738fdf1/python_can-4.5.0.tar.gz", hash = "sha256:d3684cebe5b028a148c1742b3a45cec4fcaf83a7f7c52d0680b2eaeaf52f8eb7", size = 1190119 } wheels = [ - { url = "https://files.pythonhosted.org/packages/42/c5/9eb41131696edbe56c7b97e167e3c19b15bfa4f964e21c0a6c9f28bde298/python_can-4.4.2-py3-none-any.whl", hash = "sha256:e956d781b45563c244c1f3c8fe001e292d1857519cff663d7c184673a68879f9", size = 265202 }, + { url = "https://files.pythonhosted.org/packages/6f/38/3faaa0460705f09f5fbae8e44ad4e12c6a90b12535797b9fba67f5271fed/python_can-4.5.0-py3-none-any.whl", hash = "sha256:1eec66833c1ac76a7e3d636ee0f8b4ba2752e892bab1c56ce74308b2216b5445", size = 268989 }, ] [[package]] @@ -2184,19 +2173,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d7/76/a5ff1f1afe1e84c961c7e4b541684c2515ba4c529359f0ee2d9305cb9cd9/pywavelets-1.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e0611ffb6ceeee1b677bd224e657895193eec03ad39538f5263ce61db465f836", size = 4466593 }, ] -[[package]] -name = "pywin32" -version = "308" -source = { registry = "https://pypi.org/simple" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/00/7c/d00d6bdd96de4344e06c4afbf218bc86b54436a94c01c71a8701f613aa56/pywin32-308-cp312-cp312-win32.whl", hash = "sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897", size = 5939729 }, - { url = "https://files.pythonhosted.org/packages/21/27/0c8811fbc3ca188f93b5354e7c286eb91f80a53afa4e11007ef661afa746/pywin32-308-cp312-cp312-win_amd64.whl", hash = "sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47", size = 6543015 }, - { url = "https://files.pythonhosted.org/packages/9d/0f/d40f8373608caed2255781a3ad9a51d03a594a1248cd632d6a298daca693/pywin32-308-cp312-cp312-win_arm64.whl", hash = "sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091", size = 7976033 }, - { url = "https://files.pythonhosted.org/packages/a9/a4/aa562d8935e3df5e49c161b427a3a2efad2ed4e9cf81c3de636f1fdddfd0/pywin32-308-cp313-cp313-win32.whl", hash = "sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed", size = 5938579 }, - { url = "https://files.pythonhosted.org/packages/c7/50/b0efb8bb66210da67a53ab95fd7a98826a97ee21f1d22949863e6d588b22/pywin32-308-cp313-cp313-win_amd64.whl", hash = "sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4", size = 6542056 }, - { url = "https://files.pythonhosted.org/packages/26/df/2b63e3e4f2df0224f8aaf6d131f54fe4e8c96400eb9df563e2aae2e1a1f9/pywin32-308-cp313-cp313-win_arm64.whl", hash = "sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd", size = 7974986 }, -] - [[package]] name = "pyyaml" version = "6.0.2" From 0d5c6e2afdf20de3421133032619f8339bd89c2d Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 15:54:06 -0500 Subject: [PATCH 15/16] Fix ruff config --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b0de3ccf7..6baf0da63 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,11 +44,11 @@ dev = [ ] [tool.ruff] -exclude = ["packages/jumpstarter_protocol"] +exclude = ["packages/jumpstarter-protocol"] line-length = 120 [tool.ruff.lint] -exclude = ["packages/jumpstarter_protocol"] +exclude = ["packages/jumpstarter-protocol"] extend-select = ["I", "C", "E", "F", "W", "B"] [tool.typos.default] From 41e837e6efeb59b4b263a97992295f6bcf7f5dfd Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 23 Jan 2025 17:02:50 -0500 Subject: [PATCH 16/16] Fix tests --- Makefile | 7 ++----- .../jumpstarter_kubernetes/clients_test.py | 2 ++ packages/jumpstarter-protocol/protocol_test.py | 2 ++ pyproject.toml | 10 +++------- 4 files changed, 9 insertions(+), 12 deletions(-) create mode 100644 packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients_test.py create mode 100644 packages/jumpstarter-protocol/protocol_test.py diff --git a/Makefile b/Makefile index 3df44175b..57269d280 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PKG_TARGETS = $(subst packages/,pkg-,$(wildcard packages/*)) +PKG_TARGETS = $(subst packages/,,$(wildcard packages/*)) EXAMPLE_TARGETS = $(subst examples/,example-,$(wildcard examples/*)) DOC_LISTEN ?= --host 127.0.0.1 @@ -13,10 +13,7 @@ serve-docs: clean-docs: uv run --isolated --all-packages --group docs $(MAKE) -C docs clean -test-jumpstarter: - uv run --isolated --package jumpstarter pytest jumpstarter tests - -test-pkg-%: packages/% +test-%: packages/% uv run --isolated --directory $< pytest test-packages: $(addprefix test-,$(PKG_TARGETS)) diff --git a/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients_test.py b/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients_test.py new file mode 100644 index 000000000..7641b8e6e --- /dev/null +++ b/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clients_test.py @@ -0,0 +1,2 @@ +def test_client(): + pass diff --git a/packages/jumpstarter-protocol/protocol_test.py b/packages/jumpstarter-protocol/protocol_test.py new file mode 100644 index 000000000..a097381b7 --- /dev/null +++ b/packages/jumpstarter-protocol/protocol_test.py @@ -0,0 +1,2 @@ +def test_protocol(): + pass diff --git a/pyproject.toml b/pyproject.toml index 6baf0da63..2745c2cb1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,12 +36,7 @@ docs = [ "sphinx-click>=6.0.0", "sphinx-substitution-extensions>=2024.10.17", ] -dev = [ - "ruff>=0.9.2", - "typos>=1.23.6", - "pre-commit>=3.8.0", - "esbonio>=0.16.5", -] +dev = ["ruff>=0.9.2", "typos>=1.23.6", "pre-commit>=3.8.0", "esbonio>=0.16.5"] [tool.ruff] exclude = ["packages/jumpstarter-protocol"] @@ -56,6 +51,7 @@ locale = "en-us" [tool.coverage.run] omit = ["conftest.py", "test_*.py", "*_test.py", "*_pb2.py", "*_pb2_grpc.py"] +skip_empty = true [tool.pytest.ini_options] -addopts = "--capture=no --verbose --cov --cov-report=html --cov-report=xml --cov-append" +addopts = "--capture=no --cov --cov-report=html --cov-report=xml --cov-append"