From f3cc3b9c90ce6ad172f5212526c36e1e1ff54f1c Mon Sep 17 00:00:00 2001 From: Altynbek Orumbayev Date: Tue, 16 Dec 2025 18:45:02 +0100 Subject: [PATCH 01/19] feat: decoupling from algosdk; installing latest algokit utils --- poetry.lock | 45 ++-- pyproject.toml | 4 +- scripts/package_mac.sh | 2 +- scripts/package_windows.bat | 2 +- src/algokit/cli/project/deploy.py | 7 +- src/algokit/cli/tasks/assets.py | 7 +- src/algokit/cli/tasks/mint.py | 7 +- src/algokit/cli/tasks/send_transaction.py | 81 +++++- src/algokit/cli/tasks/sign_transaction.py | 122 ++++++++- src/algokit/cli/tasks/transfer.py | 4 +- src/algokit/cli/tasks/utils.py | 85 +++--- src/algokit/cli/tasks/wallet.py | 4 +- src/algokit/core/address_utils.py | 57 ++++ src/algokit/core/signing_account.py | 34 +++ src/algokit/core/tasks/mint/mint.py | 250 +++++++++++++----- src/algokit/core/tasks/mint/models.py | 4 +- src/algokit/core/tasks/vanity_address.py | 40 ++- tests/project/deploy/test_deploy.py | 4 +- tests/tasks/conftest.py | 27 +- tests/tasks/test_asset.py | 8 +- tests/tasks/test_mint.py | 25 +- ...essful.address.False.localnet.approved.txt | 2 +- ...cessful.address.False.mainnet.approved.txt | 2 +- ...cessful.address.False.testnet.approved.txt | 2 +- ...uccessful.alias.True.localnet.approved.txt | 2 +- ...successful.alias.True.mainnet.approved.txt | 2 +- ...successful.alias.True.testnet.approved.txt | 2 +- ...ecimals.decimals_given_params.approved.txt | 2 +- ...on_decimals.no_decimals_given.approved.txt | 2 +- tests/tasks/test_nfd_lookup.py | 4 +- tests/tasks/test_send_transaction.py | 105 ++++++-- ...ansaction.test_decoding_error.approved.txt | 3 +- ...st_file_decoding_no_txn_error.approved.txt | 4 +- tests/tasks/test_sign_transaction.py | 88 +++++- ...n_atomic_txn_group_successful.approved.txt | 42 +-- ...stdin_with_address_successful.approved.txt | 19 +- ...m_stdin_with_alias_successful.approved.txt | 19 +- ..._file_with_address_successful.approved.txt | 57 ++-- ...om_file_with_alias_successful.approved.txt | 57 ++-- tests/tasks/test_transfer.py | 24 +- tests/tasks/test_wallet.py | 49 ++-- 41 files changed, 946 insertions(+), 360 deletions(-) create mode 100644 src/algokit/core/address_utils.py create mode 100644 src/algokit/core/signing_account.py diff --git a/poetry.lock b/poetry.lock index de1a9a67a..bf61e2e7c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,18 +14,22 @@ files = [ [[package]] name = "algokit-utils" -version = "4.1.0" +version = "5.0.0a2" description = "Utilities for Algorand development for use by AlgoKit" optional = false -python-versions = "<4.0,>=3.10" +python-versions = "<4,>=3.10" groups = ["main"] files = [ - {file = "algokit_utils-4.1.0-py3-none-any.whl", hash = "sha256:d164d1ad48928040432da582883be997a2e8a7b85b06e3b07de07ad96b566550"}, + {file = "algokit_utils-5.0.0a2-py3-none-any.whl", hash = "sha256:771f4256d26828c27ebce8f00eea18e953d3ef1ffe9c2d3e229f48079c12b129"}, + {file = "algokit_utils-5.0.0a2.tar.gz", hash = "sha256:25f232f655d9d9467976845aa8adb6d0ff62e149f4cd0d92e3e6401a1a138c75"}, ] [package.dependencies] httpx = ">=0.23.1,<=0.28.1" -py-algorand-sdk = ">=2.4.0,<3.0.0" +msgpack = ">=1.0.0,<2" +msgpack-types = ">=0.2.0,<=0.5.0" +pycryptodomex = ">=3.19,<4" +pynacl = ">=1.4.0,<2" typing-extensions = ">=4.6.0" [[package]] @@ -1502,6 +1506,22 @@ files = [ {file = "msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e"}, ] +[[package]] +name = "msgpack-types" +version = "0.5.0" +description = "Type stubs for msgpack" +optional = false +python-versions = "<4.0,>=3.8" +groups = ["main"] +files = [ + {file = "msgpack_types-0.5.0-py3-none-any.whl", hash = "sha256:8b633ed75e495a555fa0615843de559a74b1d176828d59bb393d266e51f6bda7"}, + {file = "msgpack_types-0.5.0.tar.gz", hash = "sha256:aebd1b8da23f8f9966d66ebb1a43bd261b95751c6a267bd21a124d2ccac84201"}, +] + +[package.dependencies] +msgpack = ">=1.1.0,<1.2.0" +typing-extensions = ">=4.6.0" + [[package]] name = "mslex" version = "1.3.0" @@ -1949,23 +1969,6 @@ files = [ [package.dependencies] wcwidth = "*" -[[package]] -name = "py-algorand-sdk" -version = "2.8.0" -description = "Algorand SDK in Python" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "py-algorand-sdk-2.8.0.tar.gz", hash = "sha256:2a2ddc94ab5c0989ed90f1b97eebb9857531b1e9c9d0d3437a57c17539ed6367"}, - {file = "py_algorand_sdk-2.8.0-py3-none-any.whl", hash = "sha256:0647a5aae4c87f0780048f98c1ee1b57a6c8fcec2c38306e3a50e42f0a81eb37"}, -] - -[package.dependencies] -msgpack = ">=1.0.0,<2" -pycryptodomex = ">=3.6.0,<4" -pynacl = ">=1.4.0,<2" - [[package]] name = "py-serializable" version = "2.0.0" diff --git a/pyproject.toml b/pyproject.toml index 5af926c44..b09bb5c51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ keyring = "25.6.0" # this version has been tested to work with the vendored file pyjwt = "^2.10.1" cryptography = "^44.0.2" # pyjwt has a weak dependency on cryptography and explicitly requires it in the vendored file, hence the lock -algokit-utils = "^4.0.1" +algokit-utils = "^5.0.0a2" multiformats = "0.3.1" multiformats_config = "0.3.1" # pinned this to be in lockstep with multiformats jsondiff = "^2.0.0" @@ -71,7 +71,7 @@ docs_generate = "sphinx-build -b markdown -E docs/sphinx docs/cli" docs_toc = "gfm-toc docs/cli/index.md -e 3" docs_title = {shell = "(echo \"# AlgoKit CLI Reference Documentation\\n\\n\"; cat docs/cli/index.md) > docs/cli/temp.md && mv docs/cli/temp.md docs/cli/index.md"} docs = ["docs_generate", "docs_toc", "docs_title"] -package_unix = "pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data './misc/multiformats_config:multiformats_config/' --add-data './src/algokit/resources:algokit/resources/'" +package_unix = "pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --hidden-import algokit_algod_client --hidden-import algokit_transact --hidden-import algokit_common --hidden-import algokit_algosdk --hidden-import algokit_algo25 --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data './misc/multiformats_config:multiformats_config/' --add-data './src/algokit/resources:algokit/resources/'" package_windows = { cmd = "scripts/package_windows.bat" } package_mac = { cmd = "scripts/package_mac.sh" } diff --git a/scripts/package_mac.sh b/scripts/package_mac.sh index c66c46a39..2537062b7 100755 --- a/scripts/package_mac.sh +++ b/scripts/package_mac.sh @@ -1,6 +1,6 @@ #!/bin/bash -CMD="pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data './misc/multiformats_config/multibase-table.json:multiformats_config/' --add-data './misc/multiformats_config/multicodec-table.json:multiformats_config/' --add-data './src/algokit/resources:algokit/resources/'" +CMD="pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --hidden-import algokit_algod_client --hidden-import algokit_transact --hidden-import algokit_common --hidden-import algokit_algosdk --hidden-import algokit_algo25 --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data './misc/multiformats_config/multibase-table.json:multiformats_config/' --add-data './misc/multiformats_config/multicodec-table.json:multiformats_config/' --add-data './src/algokit/resources:algokit/resources/'" if [ ! -z "$APPLE_BUNDLE_ID" ]; then CMD="$CMD --osx-bundle-identifier \"$APPLE_BUNDLE_ID\"" diff --git a/scripts/package_windows.bat b/scripts/package_windows.bat index 10eb82fd7..c50e31343 100644 --- a/scripts/package_windows.bat +++ b/scripts/package_windows.bat @@ -1,2 +1,2 @@ @echo off -pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data ./misc/multiformats_config;multiformats_config/ --add-data ./src/algokit/resources;algokit/resources/ +pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --hidden-import algokit_algod_client --hidden-import algokit_transact --hidden-import algokit_common --hidden-import algokit_algosdk --hidden-import algokit_algo25 --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data ./misc/multiformats_config;multiformats_config/ --add-data ./src/algokit/resources;algokit/resources/ diff --git a/src/algokit/cli/project/deploy.py b/src/algokit/cli/project/deploy.py index f07577667..0db77351a 100644 --- a/src/algokit/cli/project/deploy.py +++ b/src/algokit/cli/project/deploy.py @@ -1,10 +1,11 @@ +import base64 import logging import os import typing as t from pathlib import Path import click -from algosdk.mnemonic import from_private_key +from algokit_utils.algo25 import secret_key_to_mnemonic from algokit.cli.common.utils import MutuallyExclusiveOption, sanitize_extra_args from algokit.core import proc @@ -47,7 +48,9 @@ def _ensure_aliases( raise click.ClickException(f"Error: missing {alias} alias") if not alias_data.private_key: raise click.ClickException(f"Error: missing private key for {alias} alias") - config_env[key] = from_private_key(alias_data.private_key) # type: ignore[no-untyped-call] + # Private key is stored as base64 string, decode to bytes for mnemonic conversion + private_key_bytes = base64.b64decode(alias_data.private_key) + config_env[key] = secret_key_to_mnemonic(private_key_bytes) logger.debug(f"Loaded {alias} alias mnemonic as {key} environment variable") diff --git a/src/algokit/cli/tasks/assets.py b/src/algokit/cli/tasks/assets.py index c68f803a5..1df462835 100644 --- a/src/algokit/cli/tasks/assets.py +++ b/src/algokit/cli/tasks/assets.py @@ -1,8 +1,7 @@ import logging import click -from algosdk import error -from algosdk.v2client.algod import AlgodClient +from algokit_utils.clients import AlgodClient, UnexpectedStatusError from algokit.cli.common.constants import AlgorandNetwork, ExplorerEntityType from algokit.cli.common.utils import get_explorer_url @@ -73,7 +72,7 @@ def opt_in_command(asset_ids: tuple[int], account: str, network: AlgorandNetwork for asset_opt_int_result in response: explorer_url = get_explorer_url(asset_opt_int_result.transaction_id, network, ExplorerEntityType.ASSET) click.echo(f"Check opt-in status for asset {asset_opt_int_result.asset_id} at: {explorer_url}") - except error.AlgodHTTPError as err: + except UnexpectedStatusError as err: raise click.ClickException(str(err)) from err except ValueError as err: logger.debug(err, exc_info=True) @@ -140,7 +139,7 @@ def opt_out_command(*, asset_ids: tuple[int], account: str, network: AlgorandNet asset_opt_out_result.transaction_id, network, ExplorerEntityType.TRANSACTION ) click.echo(f"Check opt-in status for asset {asset_opt_out_result.asset_id} at: {transaction_url}") - except error.AlgodHTTPError as err: + except UnexpectedStatusError as err: raise click.ClickException(str(err)) from err except ConnectionRefusedError as err: raise click.ClickException(str(err)) from err diff --git a/src/algokit/cli/tasks/mint.py b/src/algokit/cli/tasks/mint.py index 381580bbe..3d7837052 100644 --- a/src/algokit/cli/tasks/mint.py +++ b/src/algokit/cli/tasks/mint.py @@ -5,8 +5,8 @@ from pathlib import Path import click -from algokit_utils import AlgoAmount, SigningAccount -from algosdk.error import AlgodHTTPError +from algokit_utils import AlgoAmount +from algokit_utils.clients import UnexpectedStatusError from algokit.cli.common.constants import AlgorandNetwork, ExplorerEntityType from algokit.cli.common.utils import get_explorer_url @@ -16,6 +16,7 @@ run_callback_once, validate_balance, ) +from algokit.core.signing_account import SigningAccount from algokit.core.tasks.ipfs import ( PinataBadRequestError, PinataForbiddenError, @@ -332,7 +333,7 @@ def mint( # noqa: PLR0913 ) as ex: logger.debug(ex) raise click.ClickException(repr(ex)) from ex - except AlgodHTTPError as ex: + except UnexpectedStatusError as ex: raise click.ClickException(str(ex)) from ex except Exception as ex: logger.debug(ex, exc_info=True) diff --git a/src/algokit/cli/tasks/send_transaction.py b/src/algokit/cli/tasks/send_transaction.py index 6d80c7a6f..55f02bb19 100644 --- a/src/algokit/cli/tasks/send_transaction.py +++ b/src/algokit/cli/tasks/send_transaction.py @@ -1,11 +1,13 @@ +import base64 import json import logging from pathlib import Path from typing import TYPE_CHECKING, cast import click -from algosdk import encoding, error -from algosdk.transaction import SignedTransaction, retrieve_from_file +import msgpack +from algokit_utils.clients import UnexpectedStatusError +from algokit_utils.transact import SignedTransaction, decode_signed_transaction, encode_signed_transaction from algokit.cli.common.constants import AlgorandNetwork, ExplorerEntityType from algokit.cli.common.utils import MutuallyExclusiveOption, get_explorer_url @@ -34,6 +36,60 @@ def _is_sign_task_output_txn(item: dict) -> bool: return isinstance(item, dict) and all(key in item for key in ["transaction_id", "content"]) +def _retrieve_transactions_from_file(file_path: Path) -> list[SignedTransaction]: + """ + Load signed transactions from a file containing msgpack-encoded data. + + Args: + file_path: Path to the file containing signed transaction(s) + + Returns: + A list of SignedTransaction objects + + Raises: + click.ClickException: If the file cannot be read or decoded + """ + try: + file_content = file_path.read_bytes() + + # Try to decode as a single transaction first + try: + return [decode_signed_transaction(file_content)] + except Exception: + pass + + # Try to parse multiple concatenated msgpack objects + transactions: list[SignedTransaction] = [] + offset = 0 + + while offset < len(file_content): + # Use msgpack Unpacker to find the boundaries of each msgpack object + unpacker = msgpack.Unpacker(raw=True, strict_map_key=False) + unpacker.feed(file_content[offset:]) + try: + _ = unpacker.unpack() # Advance to get the position + msgpack_bytes_consumed = unpacker.tell() + + # Extract just this msgpack object + encoded_txn = file_content[offset : offset + msgpack_bytes_consumed] + offset += msgpack_bytes_consumed + + # Decode the signed transaction + stx = decode_signed_transaction(encoded_txn) + transactions.append(stx) + except msgpack.OutOfData: + break + except Exception: + break + + if transactions: + return transactions + raise ValueError("No valid transactions found in file") from None + except Exception as ex: + logger.debug(ex, exc_info=True) + raise click.ClickException(f"Failed to read transactions from file: {ex}") from ex + + def _load_from_stdin() -> list[SignedTransaction]: """ Load transaction data from standard input and convert it into a list of SignedTransaction objects. @@ -59,7 +115,7 @@ def _load_from_stdin() -> list[SignedTransaction]: raise click.ClickException("Invalid piped transaction content!") # Convert the content into SignedTransaction objects - return [encoding.msgpack_decode(item["content"]) for item in file_content] # type: ignore[no-untyped-call] + return [decode_signed_transaction(base64.b64decode(item["content"])) for item in file_content] def _get_signed_transactions(file: Path | None = None, transaction: str | None = None) -> list[SignedTransaction]: @@ -80,9 +136,9 @@ def _get_signed_transactions(file: Path | None = None, transaction: str | None = """ try: if file: - txns = retrieve_from_file(str(file)) # type: ignore[no-untyped-call] + txns = _retrieve_transactions_from_file(file) elif transaction: - txns = [encoding.msgpack_decode(transaction)] # type: ignore[no-untyped-call] + txns = [decode_signed_transaction(base64.b64decode(transaction))] else: txns = _load_from_stdin() @@ -90,7 +146,7 @@ def _get_signed_transactions(file: Path | None = None, transaction: str | None = if not isinstance(txn, SignedTransaction): raise click.ClickException("Supplied transaction is not signed!") - return cast("list[SignedTransaction]", txns) + return txns except Exception as ex: logger.debug(ex, exc_info=True) @@ -112,8 +168,11 @@ def _send_transactions(network: AlgorandNetwork, txns: list[SignedTransaction]) """ algod_client = load_algod_client(network) - if any(txn.transaction.group for txn in txns): - txid = algod_client.send_transactions(txns) + if any(txn.txn.group for txn in txns): + # Send all transactions as a group + encoded_txns = [encode_signed_transaction(txn) for txn in txns] + result = algod_client.send_raw_transaction(encoded_txns) + txid = result.tx_id click.echo(f"Transaction group successfully sent with txid: {txid}") click.echo( f"Check transaction group status at: {get_explorer_url(txid, network, ExplorerEntityType.TRANSACTION)}" @@ -121,7 +180,9 @@ def _send_transactions(network: AlgorandNetwork, txns: list[SignedTransaction]) else: for index, txn in enumerate(txns, start=1): click.echo(f"\nSending transaction {index}/{len(txns)}") - txid = algod_client.send_transaction(txn) + encoded_txn = encode_signed_transaction(txn) + result = algod_client.send_raw_transaction(encoded_txn) + txid = result.tx_id click.echo(f"Transaction successfully sent with txid: {txid}") click.echo( f"Check transaction status at: {get_explorer_url(txid, network, ExplorerEntityType.TRANSACTION)}" @@ -169,7 +230,7 @@ def send(*, file: Path | None, transaction: str | None, network: AlgorandNetwork try: _send_transactions(network, txns) - except error.AlgodHTTPError as ex: + except UnexpectedStatusError as ex: raise click.ClickException(str(ex)) from ex except Exception as ex: logger.debug(ex, exc_info=True) diff --git a/src/algokit/cli/tasks/sign_transaction.py b/src/algokit/cli/tasks/sign_transaction.py index 1fdb55e2a..0a82dfcc8 100644 --- a/src/algokit/cli/tasks/sign_transaction.py +++ b/src/algokit/cli/tasks/sign_transaction.py @@ -1,12 +1,22 @@ import base64 import json import logging +from collections.abc import Sequence from pathlib import Path -from typing import Any, cast +from typing import Any import click -from algosdk import encoding -from algosdk.transaction import SignedTransaction, Transaction, retrieve_from_file, write_to_file +import msgpack +from algokit_utils.transact import ( + SignedTransaction, + Transaction, + decode_signed_transaction, + decode_transaction, + encode_signed_transactions, + get_transaction_id, + make_basic_account_transaction_signer, + to_transaction_dto, +) from algokit.cli.common.utils import MutuallyExclusiveOption from algokit.cli.tasks.utils import get_account_with_private_key @@ -21,11 +31,81 @@ def default(self, obj: Any) -> Any: # noqa: ANN401 return super().default(obj) -def _validate_for_signed_txns(txns: list[Transaction]) -> None: +def retrieve_from_file(file_path: str) -> list[Transaction | SignedTransaction]: + """Load transactions from a file (msgpack encoded). + + The file format is concatenated msgpack-encoded transactions, each prefixed with "TX". + Each transaction can be either a Transaction or a SignedTransaction. + + Args: + file_path: Path to the file containing encoded transactions. + + Returns: + List of Transaction or SignedTransaction objects. + """ + with Path(file_path).open("rb") as f: + data = f.read() + + tx_prefix = b"TX" + txns: list[Transaction | SignedTransaction] = [] + offset = 0 + + while offset < len(data): + # Check for TX prefix and skip it if present + has_prefix = data[offset:].startswith(tx_prefix) + if has_prefix: + msgpack_start = offset + len(tx_prefix) + else: + msgpack_start = offset + + # Use Unpacker to find the end of the msgpack object + unpacker = msgpack.Unpacker(raw=True, strict_map_key=False) + unpacker.feed(data[msgpack_start:]) + try: + _ = unpacker.unpack() # Just to advance the position + msgpack_bytes_consumed = unpacker.tell() + + # Include the prefix in the encoded transaction if present + if has_prefix: + encoded_txn = data[offset : msgpack_start + msgpack_bytes_consumed] + else: + encoded_txn = data[offset : offset + msgpack_bytes_consumed] + offset = msgpack_start + msgpack_bytes_consumed + + # Try to decode as SignedTransaction first, then Transaction + try: + txns.append(decode_signed_transaction(encoded_txn)) + except Exception: + txns.append(decode_transaction(encoded_txn)) + except msgpack.OutOfData: + break + + return txns + + +def write_to_file(signed_txns: list[SignedTransaction], file_path: str) -> None: + """Write signed transactions to a file (msgpack encoded). + + The file format is concatenated msgpack-encoded signed transactions. + + Args: + signed_txns: List of SignedTransaction objects to write. + file_path: Path to the output file. + """ + # Encode each signed transaction + encoded_txns = encode_signed_transactions(signed_txns) + + # Write concatenated msgpack objects (not an array) + with Path(file_path).open("wb") as f: + for encoded_txn in encoded_txns: + f.write(encoded_txn) + + +def _validate_for_signed_txns(txns: Sequence[Transaction | SignedTransaction]) -> None: signed_txns = [txn for txn in txns if isinstance(txn, SignedTransaction)] if signed_txns: - transaction_ids = ", ".join([txn.get_txid() for txn in signed_txns]) # type: ignore[no-untyped-call] + transaction_ids = ", ".join([get_transaction_id(txn.txn) for txn in signed_txns]) message = f"Supplied transactions {transaction_ids} are already signed!" raise click.ClickException(message) @@ -33,10 +113,14 @@ def _validate_for_signed_txns(txns: list[Transaction]) -> None: def _get_transactions(file: Path | None, transaction: str | None) -> list[Transaction]: try: if file: - txns: list[Transaction] = retrieve_from_file(str(file)) # type: ignore[no-untyped-call] - return txns + txns_or_signed = retrieve_from_file(str(file)) + # Extract unsigned transactions, filter out any that are already signed + return [txn if isinstance(txn, Transaction) else txn.txn for txn in txns_or_signed] else: - return [cast("Transaction", encoding.msgpack_decode(transaction))] # type: ignore[no-untyped-call] + # Decode base64 string to bytes, then decode as transaction + assert transaction is not None, "Either file or transaction must be provided" + txn_bytes = base64.b64decode(transaction) + return [decode_transaction(txn_bytes)] except Exception as ex: logger.debug(ex, exc_info=True) raise click.ClickException( @@ -49,8 +133,8 @@ def _confirm_transaction(txns: list[Transaction]) -> bool: json.dumps( [ { - "transaction_id": txn.get_txid(), # type: ignore[no-untyped-call] - "content": txn.dictify(), # type: ignore[no-untyped-call] + "transaction_id": get_transaction_id(txn), + "content": to_transaction_dto(txn), } for txn in txns ], @@ -65,15 +149,25 @@ def _confirm_transaction(txns: list[Transaction]) -> bool: def _sign_and_output_transaction(txns: list[Transaction], private_key: str, output: Path | None) -> None: - signed_txns = [txn.sign(private_key) for txn in txns] # type: ignore[no-untyped-call] + # Create a transaction signer from the private key + signer = make_basic_account_transaction_signer(private_key) + + # Sign all transactions - signer returns encoded SignedTransaction bytes + signed_txn_bytes_list = signer(txns, list(range(len(txns)))) + + # Decode the signed transaction bytes to get SignedTransaction objects + signed_txns = [decode_signed_transaction(stx_bytes) for stx_bytes in signed_txn_bytes_list] if output: - write_to_file(signed_txns, str(output)) # type: ignore[no-untyped-call] + write_to_file(signed_txns, str(output)) click.echo(f"Signed transaction written to {output}") else: encoded_signed_txns = [ - {"transaction_id": txn.get_txid(), "content": encoding.msgpack_encode(txn)} # type: ignore[no-untyped-call] - for txn in signed_txns + { + "transaction_id": get_transaction_id(txn.txn), + "content": base64.b64encode(stx_bytes).decode(), + } + for txn, stx_bytes in zip(signed_txns, signed_txn_bytes_list, strict=False) ] click.echo(json.dumps(encoded_signed_txns, indent=2)) diff --git a/src/algokit/cli/tasks/transfer.py b/src/algokit/cli/tasks/transfer.py index a8d971bc9..65fa2f34d 100644 --- a/src/algokit/cli/tasks/transfer.py +++ b/src/algokit/cli/tasks/transfer.py @@ -1,7 +1,7 @@ import logging import click -from algokit_utils import AlgoAmount, AssetTransferParams, PaymentParams, SendAtomicTransactionComposerResults +from algokit_utils import AlgoAmount, AssetTransferParams, PaymentParams, SendTransactionComposerResults from algokit.cli.common.constants import AlgorandNetwork, ExplorerEntityType from algokit.cli.common.utils import get_explorer_url @@ -85,7 +85,7 @@ def transfer( # noqa: PLR0913 validate_balance(algod_client, receiver_address, asset_id) # Transfer algos or assets depending on asset_id - txn_response: SendAtomicTransactionComposerResults | None = None + txn_response: SendTransactionComposerResults | None = None algorand = get_algorand_client_for_network(network) try: if asset_id == 0: diff --git a/src/algokit/cli/tasks/utils.py b/src/algokit/cli/tasks/utils.py index 343b919d8..1664d541b 100644 --- a/src/algokit/cli/tasks/utils.py +++ b/src/algokit/cli/tasks/utils.py @@ -1,5 +1,6 @@ # AlgoKit Tasks related utility functions +import base64 import logging import os import stat @@ -9,17 +10,29 @@ from functools import wraps from typing import Any -import algosdk -import algosdk.encoding import click -from algokit_utils import AlgoAmount, ClientManager, SigningAccount +import nacl.signing +from algokit_utils import AlgoAmount, ClientManager +from algokit_utils.algo25 import seed_from_mnemonic +from algokit_utils.clients import AlgodClient from algokit.cli.common.constants import AlgorandNetwork +from algokit.core.address_utils import ALGORAND_ADDRESS_LENGTH, is_valid_address +from algokit.core.signing_account import SigningAccount from algokit.core.tasks.wallet import get_alias logger = logging.getLogger(__name__) +def _get_account_info_dict(algod_client: AlgodClient, address: str) -> dict: + """Convert AlgodClient account_information response to a dict format.""" + response = algod_client.account_information(address) + return { + "amount": getattr(response, "amount", 0), + "assets": [{"asset-id": a.asset_id, "amount": a.amount} for a in getattr(response, "assets", []) or []], + } + + def _validate_asset_balance(account_info: dict, asset_id: int, decimals: int, amount: int = 0) -> None: asset_record = next((asset for asset in account_info.get("assets", []) if asset["asset-id"] == asset_id), None) @@ -48,7 +61,7 @@ def get_private_key_from_mnemonic() -> str: Converts a mnemonic phrase into a private key. Returns: - str: The private key generated from the mnemonic phrase. + str: The base64-encoded private key (64 bytes: seed + public key) generated from the mnemonic phrase. Raises: click.ClickException: If the entered mnemonic phrase is invalid. @@ -62,27 +75,34 @@ def get_private_key_from_mnemonic() -> str: Flow: 1. Prompts the user to enter a mnemonic phrase. - 2. Converts the entered mnemonic phrase into a private key using `algosdk.mnemonic.to_private_key`. - 3. Returns the private key. + 2. Converts the entered mnemonic phrase into a seed using `seed_from_mnemonic`. + 3. Derives the public key from the seed. + 4. Returns the base64-encoded concatenation of seed + public key. """ mnemonic_phrase = click.prompt("Enter the mnemonic phrase (25 words separated by whitespace)", hide_input=True) try: - return str(algosdk.mnemonic.to_private_key(mnemonic_phrase)) # type: ignore[no-untyped-call] + # Get the 32-byte seed from the mnemonic + seed = seed_from_mnemonic(mnemonic_phrase) + # Generate the public key from the seed using nacl + signing_key = nacl.signing.SigningKey(seed) + public_key = signing_key.verify_key.encode() + # Return base64-encoded 64-byte private key (seed + public key) + return base64.b64encode(seed + public_key).decode() except Exception as err: raise click.ClickException("Invalid mnemonic. Please provide a valid Algorand mnemonic.") from err -def load_algod_client(network: AlgorandNetwork) -> algosdk.v2client.algod.AlgodClient: +def load_algod_client(network: AlgorandNetwork) -> AlgodClient: """ - Returns an instance of the `algosdk.v2client.algod.AlgodClient` class for the specified network. + Returns an instance of the `AlgodClient` class for the specified network. Args: network (str): The network for which the `AlgodClient` instance needs to be loaded. Returns: - algosdk.v2client.algod.AlgodClient: An instance of the `AlgodClient` class for the specified network. + AlgodClient: An instance of the `AlgodClient` class for the specified network. Raises: click.ClickException: If the specified network is invalid. @@ -99,13 +119,13 @@ def load_algod_client(network: AlgorandNetwork) -> algosdk.v2client.algod.AlgodC raise click.ClickException("Invalid network") from err -def get_asset_decimals(asset_id: int, algod_client: algosdk.v2client.algod.AlgodClient) -> int: +def get_asset_decimals(asset_id: int, algod_client: AlgodClient) -> int: """ Retrieves the number of decimal places for a given asset. Args: asset_id (int): The ID of the asset for which the number of decimal places is to be retrieved. (0 for Algo) - algod_client (algosdk.v2client.algod.AlgodClient): An instance of the AlgodClient class. + algod_client (AlgodClient): An instance of the AlgodClient class. Returns: int: The number of decimal places for the given asset. @@ -115,7 +135,7 @@ def get_asset_decimals(asset_id: int, algod_client: algosdk.v2client.algod.Algod Example: asset_id = 123 - algod_client = algosdk.v2client.algod.AlgodClient("https://mainnet-api.algonode.cloud", "API_KEY") + algod_client = AlgodClient(...) decimals = get_asset_decimals(asset_id, algod_client) print(decimals) """ @@ -123,22 +143,21 @@ def get_asset_decimals(asset_id: int, algod_client: algosdk.v2client.algod.Algod if asset_id == 0: return 6 - asset_info = algod_client.asset_info(asset_id) + asset_response = algod_client.get_asset_by_id(asset_id) + decimals = getattr(getattr(asset_response, "params", None), "decimals", None) - if not isinstance(asset_info, dict) or "params" not in asset_info or "decimals" not in asset_info["params"]: + if decimals is None: raise click.ClickException("Invalid asset info response") - return int(asset_info["params"]["decimals"]) + return int(decimals) -def validate_balance( - algod_client: algosdk.v2client.algod.AlgodClient, account: SigningAccount | str, asset_id: int, amount: int = 0 -) -> None: +def validate_balance(algod_client: AlgodClient, account: SigningAccount | str, asset_id: int, amount: int = 0) -> None: """ Validates the balance of an account before an operation. Args: - algod_client (algosdk.v2client.algod.AlgodClient): The AlgodClient object for + algod_client (AlgodClient): The AlgodClient object for interacting with the Algorand blockchain. account (SigningAccount | str): The account object. asset_id (int): The ID of the asset to be checked (0 for Algos). @@ -148,10 +167,7 @@ def validate_balance( click.ClickException: If any validation check fails. """ address = account.address if isinstance(account, SigningAccount) else account - account_info = algod_client.account_info(address) - - if not isinstance(account_info, dict): - raise click.ClickException("Invalid account info response") + account_info = _get_account_info_dict(algod_client, address) if asset_id == 0: _validate_algo_balance(account_info, amount) @@ -174,7 +190,7 @@ def validate_address(address: str) -> None: None """ - if not algosdk.encoding.is_valid_address(address): # type: ignore[no-untyped-call] + if not is_valid_address(address): raise click.ClickException(f"`{address}` is an invalid account address") @@ -234,7 +250,7 @@ def get_address(address: str) -> str: validate_address(parsed_address) return parsed_address except click.ClickException as ex: - if len(parsed_address) == algosdk.constants.address_len: + if len(parsed_address) == ALGORAND_ADDRESS_LENGTH: raise click.ClickException(f"`{parsed_address}` is an invalid account address") from ex alias_data = get_alias(parsed_address) @@ -257,15 +273,13 @@ def stdin_has_content() -> bool: return stat.S_ISFIFO(mode) or stat.S_ISREG(mode) -def validate_account_balance_to_opt_in( - algod_client: algosdk.v2client.algod.AlgodClient, account: SigningAccount, num_assets: int -) -> None: +def validate_account_balance_to_opt_in(algod_client: AlgodClient, account: SigningAccount, num_assets: int) -> None: """ Validates the balance of an account before opt in operation. Each asset requires 0.1 Algos to opt in. Args: - algod_client (algosdk.v2client.algod.AlgodClient): The AlgodClient object for + algod_client (AlgodClient): The AlgodClient object for interacting with the Algorand blockchain. account (SigningAccount | str): The account object. num_assets (int): The number of the assets for opt in (0 for Algos). @@ -275,10 +289,7 @@ def validate_account_balance_to_opt_in( """ address = account.address if isinstance(account, SigningAccount) else account - account_info = algod_client.account_info(address) - - if not isinstance(account_info, dict): - raise click.ClickException("Invalid account info response") + account_info = _get_account_info_dict(algod_client, address) required_microalgos = num_assets * AlgoAmount.from_algo(Decimal("0.1")).micro_algo available_microalgos = account_info.get("amount", 0) @@ -291,10 +302,8 @@ def validate_account_balance_to_opt_in( ) -def get_account_info(algod_client: algosdk.v2client.algod.AlgodClient, account_address: str) -> dict: - account_info = algod_client.account_info(account_address) - assert isinstance(account_info, dict) - return account_info +def get_account_info(algod_client: AlgodClient, account_address: str) -> dict: + return _get_account_info_dict(algod_client, account_address) def run_callback_once(callback: Callable) -> Callable: diff --git a/src/algokit/cli/tasks/wallet.py b/src/algokit/cli/tasks/wallet.py index 0fd0f6d58..ef2271e6d 100644 --- a/src/algokit/cli/tasks/wallet.py +++ b/src/algokit/cli/tasks/wallet.py @@ -2,9 +2,9 @@ import re import click -from algosdk import account from algokit.cli.tasks.utils import get_private_key_from_mnemonic, validate_address +from algokit.core.address_utils import address_from_private_key from algokit.core.tasks.wallet import ( WALLET_ALIASING_MAX_LIMIT, WalletAliasingLimitError, @@ -49,7 +49,7 @@ def add(*, alias_name: str, address: str, use_mnemonic: bool, force: bool) -> No private_key = get_private_key_from_mnemonic() if use_mnemonic else None if use_mnemonic: - derived_address = account.address_from_private_key(private_key) # type: ignore[no-untyped-call] + derived_address = address_from_private_key(private_key) # type: ignore[arg-type] if derived_address != address: click.echo( "Warning: Address from the mnemonic doesn't match the provided address. " diff --git a/src/algokit/core/address_utils.py b/src/algokit/core/address_utils.py new file mode 100644 index 000000000..e75eef9e7 --- /dev/null +++ b/src/algokit/core/address_utils.py @@ -0,0 +1,57 @@ +"""Address utilities for the CLI. + +This module provides address validation and derivation utilities using algokit_common. +""" + +import base64 + +from algokit_utils.common import ( + ADDRESS_LENGTH, + address_from_public_key, + public_key_from_address, +) + +# Standard Algorand address length (58 characters) +ALGORAND_ADDRESS_LENGTH = ADDRESS_LENGTH + + +def is_valid_address(address: str) -> bool: + """Check if an address is a valid Algorand address. + + Args: + address: The address string to validate. + + Returns: + True if the address is valid, False otherwise. + """ + if len(address) != ADDRESS_LENGTH: + return False + + try: + # public_key_from_address will raise if invalid + public_key_from_address(address) + return True + except Exception: + return False + + +def address_from_private_key(private_key: str) -> str: + """Derive the address from a private key. + + The private key is expected to be a base64-encoded string of 64 bytes + (32-byte seed + 32-byte public key). + + Args: + private_key: Base64-encoded private key string. + + Returns: + The Algorand address corresponding to the private key. + """ + # Decode the base64 private key + key_bytes = base64.b64decode(private_key) + + # Extract the public key (last 32 bytes of the 64-byte key) + public_key = key_bytes[32:64] + + # Derive the address from the public key + return address_from_public_key(public_key) diff --git a/src/algokit/core/signing_account.py b/src/algokit/core/signing_account.py new file mode 100644 index 000000000..79cadbe5e --- /dev/null +++ b/src/algokit/core/signing_account.py @@ -0,0 +1,34 @@ +"""SigningAccount compatibility class for CLI. + +This module provides a SigningAccount class that mimics the old algokit-utils +SigningAccount interface for CLI compatibility during the migration to the +new decoupled architecture. +""" + +from dataclasses import dataclass, field + +from algokit_utils.transact import TransactionSigner, make_basic_account_transaction_signer + + +@dataclass +class SigningAccount: + """A simple account with signing capability. + + This class provides compatibility with the old algokit-utils SigningAccount + interface while working with the new decoupled architecture. + + Attributes: + address: The Algorand address of the account. + private_key: The private key of the account (base64-encoded string or hex string). + """ + + address: str + private_key: str + _signer: TransactionSigner | None = field(default=None, repr=False, compare=False) + + @property + def signer(self) -> TransactionSigner: + """Get a transaction signer for this account.""" + if self._signer is None: + object.__setattr__(self, "_signer", make_basic_account_transaction_signer(self.private_key)) + return self._signer # type: ignore[return-value] diff --git a/src/algokit/core/tasks/mint/mint.py b/src/algokit/core/tasks/mint/mint.py index 979dc3b9e..ee44ffc18 100644 --- a/src/algokit/core/tasks/mint/mint.py +++ b/src/algokit/core/tasks/mint/mint.py @@ -5,19 +5,77 @@ import mimetypes import pathlib import re -from dataclasses import asdict -from algokit_utils import SigningAccount -from algosdk import encoding, transaction -from algosdk.transaction import wait_for_confirmation -from algosdk.v2client import algod +from algokit_utils.clients import AlgodClient, algod_models +from algokit_utils.transact import get_transaction_id, make_basic_account_transaction_signer +from algokit_utils.transactions.builders.asset import build_asset_create_transaction +from algokit_utils.transactions.types import AssetCreateParams from multiformats import CID +from algokit.core.signing_account import SigningAccount from algokit.core.tasks.ipfs import upload_to_pinata -from algokit.core.tasks.mint.models import AssetConfigTxnParams, TokenMetadata +from algokit.core.tasks.mint.models import TokenMetadata logger = logging.getLogger(__name__) +# Constants for Algorand address validation +ALGORAND_ADDRESS_LENGTH = 58 +ALGORAND_ADDRESS_DECODED_LENGTH = 36 # 32 bytes address + 4 bytes checksum + + +def _encode_address_from_bytes(digest: bytes) -> str: + """ + Encode an address from a 32-byte digest using Algorand address encoding. + + Args: + digest: 32-byte hash digest + + Returns: + str: Base32-encoded address with checksum + """ + # Standard Algorand checksum uses sha512_256, taking last 4 bytes + h = hashlib.new("sha512_256") + h.update(digest) + checksum = h.digest()[-4:] + address_bytes = digest + checksum + # Base32 encode without padding + encoded = base64.b32encode(address_bytes).decode("utf-8") + # Remove padding + return encoded.rstrip("=") + + +def _is_valid_address(address: str) -> bool: + """ + Validate an Algorand address. + + Args: + address: The address string to validate + + Returns: + bool: True if valid, False otherwise + """ + if len(address) != ALGORAND_ADDRESS_LENGTH: + return False + try: + # Add padding back for base32 decoding + padding_needed = (8 - len(address) % 8) % 8 + padded = address + "=" * padding_needed + decoded = base64.b32decode(padded) + + if len(decoded) != ALGORAND_ADDRESS_DECODED_LENGTH: + return False + + addr_hash = decoded[:32] + checksum = decoded[32:] + + # Standard Algorand checksum uses sha512_256, taking last 4 bytes + h = hashlib.new("sha512_256") + h.update(addr_hash) + expected_checksum = h.digest()[-4:] + return checksum == expected_checksum + except Exception: + return False + def _reserve_address_from_cid(cid: str) -> str: """ @@ -33,8 +91,8 @@ def _reserve_address_from_cid(cid: str) -> str: # Workaround to fix `multiformats` package issue, remove first two bytes before using `encode_address`. # Initial fix using `py-multiformats-cid` and `multihash.decode` was dropped due to PEP 517 incompatibility. digest = CID.decode(cid).digest[2:] - reserve_address = str(encoding.encode_address(digest)) # type: ignore[no-untyped-call] - assert encoding.is_valid_address(reserve_address) # type: ignore[no-untyped-call] + reserve_address = _encode_address_from_bytes(digest) + assert _is_valid_address(reserve_address) return reserve_address @@ -95,55 +153,81 @@ def _file_mimetype(filename: pathlib.Path) -> str: return mimetypes.types_map[extension] -def _create_asset_txn( +def _wait_for_confirmation(client: AlgodClient, txid: str, rounds: int) -> algod_models.PendingTransactionResponse: + """Wait for transaction confirmation. + + Args: + client: AlgodClient instance + txid: Transaction ID to wait for + rounds: Maximum number of rounds to wait + + Returns: + algod_models.PendingTransactionResponse: Transaction confirmation info + + Raises: + Exception: If transaction is rejected or not confirmed in time + """ + status = client.get_status() + last_round = getattr(status, "last_round", 0) + current_round = last_round + + while current_round <= last_round + rounds: + txinfo = client.pending_transaction_information(txid) + confirmed_round = getattr(txinfo, "confirmed_round", None) + if confirmed_round is not None and confirmed_round > 0: + return txinfo + pool_error = getattr(txinfo, "pool_error", None) + if pool_error: + raise Exception(f"Transaction rejected: {pool_error}") + current_round += 1 + client.status_after_block(current_round) + + raise Exception(f"Transaction {txid} not confirmed after {rounds} rounds") + + +def _compute_metadata_hash( *, - asset_config_params: AssetConfigTxnParams, token_metadata: TokenMetadata, use_metadata_hash: bool = True, -) -> transaction.AssetConfigTxn: +) -> bytes: """ - Create an instance of the AssetConfigTxn class by setting the parameters and metadata - for the asset configuration transaction. + Compute the metadata hash for an asset. Args: - asset_config_params (AssetConfigTxnParams): An instance of the AssetConfigTxnParams class - that contains the parameters for the asset configuration transaction. token_metadata (TokenMetadata): An instance of the TokenMetadata class that contains the metadata for the asset. - use_metadata_hash (bool, optional): A boolean flag indicating whether to use the metadata hash - in the asset configuration transaction. Defaults to True. + use_metadata_hash (bool, optional): A boolean flag indicating whether to use the metadata hash. + Defaults to True. Returns: - AssetConfigTxn: An instance of the AssetConfigTxn class representing the asset configuration transaction. + bytes: The computed metadata hash, or empty bytes if use_metadata_hash is False. """ + if not use_metadata_hash: + return b"" + json_metadata = token_metadata.to_json() metadata = json.loads(json_metadata) - if use_metadata_hash: - if "extra_metadata" in metadata: - h = hashlib.new("sha512_256") - h.update(b"arc0003/amj") - h.update(json_metadata.encode("utf-8")) - json_metadata_hash = h.digest() - - h = hashlib.new("sha512_256") - h.update(b"arc0003/am") - - h.update(json_metadata_hash) - h.update(base64.b64decode(metadata["extra_metadata"])) - asset_config_params.metadata_hash = h.digest() - else: - h = hashlib.new("sha256") - h.update(json_metadata.encode("utf-8")) - asset_config_params.metadata_hash = h.digest() - else: - asset_config_params.metadata_hash = b"" + if "extra_metadata" in metadata: + h = hashlib.new("sha512_256") + h.update(b"arc0003/amj") + h.update(json_metadata.encode("utf-8")) + json_metadata_hash = h.digest() + + h = hashlib.new("sha512_256") + h.update(b"arc0003/am") - return transaction.AssetConfigTxn(**asdict(asset_config_params)) # type: ignore[no-untyped-call] + h.update(json_metadata_hash) + h.update(base64.b64decode(metadata["extra_metadata"])) + return h.digest() + else: + h = hashlib.new("sha256") + h.update(json_metadata.encode("utf-8")) + return h.digest() def mint_token( # noqa: PLR0913 *, - client: algod.AlgodClient, + client: AlgodClient, jwt: str, creator_account: SigningAccount, unit_name: str, @@ -156,26 +240,19 @@ def mint_token( # noqa: PLR0913 Mint new token on the Algorand blockchain. Args: - client (algod.AlgodClient): An instance of the `algod.AlgodClient` class representing the Algorand node. + client (AlgodClient): An instance of the `AlgodClient` class representing the Algorand node. jwt (str): The JWT for accessing the Piñata API. creator_account (SigningAccount): An instance of the `SigningAccount` class representing the account that will create the token. - asset_name (str): A string representing the name of the token. unit_name (str): A string representing the unit name of the token. total (int): An integer representing the total supply of the token. token_metadata (TokenMetadata): An instance of the `TokenMetadata` class representing the metadata of the token. mutable (bool): A boolean indicating whether the token is mutable or not. image_path (pathlib.Path | None, optional): A `pathlib.Path` object representing the path to the image file associated with the token. Defaults to None. - decimals (int | None, optional): An integer representing the number of decimal places for the token. - Defaults to 0. Returns: tuple[int, str]: A tuple containing the asset index and transaction ID of the minted token. - - Raises: - ValueError: If the token name in the metadata JSON does not match the provided asset name. - ValueError: If the decimals in the metadata JSON does not match the provided decimals amount. """ if image_path: @@ -192,26 +269,75 @@ def mint_token( # noqa: PLR0913 ) logger.info(f"Metadata uploaded to pinata: {metadata_cid}") - asset_config_params = AssetConfigTxnParams( + # Compute metadata hash + metadata_hash = _compute_metadata_hash( + token_metadata=token_metadata, + use_metadata_hash=not mutable, + ) + + # Build asset creation parameters + asset_create_params = AssetCreateParams( sender=creator_account.address, - sp=client.suggested_params(), - reserve=_reserve_address_from_cid(metadata_cid) if mutable else "", + total=total, + decimals=token_metadata.decimals, + default_frozen=False, unit_name=unit_name, asset_name=token_metadata.name, url=_create_url_from_cid(metadata_cid) + "#arc3" if mutable else "ipfs://" + metadata_cid + "#arc3", - manager=creator_account.address if mutable else "", - total=total, - decimals=token_metadata.decimals, + metadata_hash=metadata_hash if metadata_hash else None, + manager=creator_account.address if mutable else None, + reserve=_reserve_address_from_cid(metadata_cid) if mutable else None, + freeze=None, + clawback=None, ) - logger.debug(f"Asset config params: {asset_config_params.to_json()}") - asset_config_txn = _create_asset_txn( - asset_config_params=asset_config_params, - token_metadata=token_metadata, - use_metadata_hash=not mutable, + logger.debug( + "Asset config params: " + + json.dumps( + { + "sender": asset_create_params.sender, + "unit_name": asset_create_params.unit_name or "", + "asset_name": asset_create_params.asset_name or "", + "url": asset_create_params.url or "", + "manager": asset_create_params.manager or "", + "reserve": asset_create_params.reserve or "", + "total": asset_create_params.total, + "freeze": asset_create_params.freeze or "", + "clawback": asset_create_params.clawback or "", + "note": "", + "decimals": asset_create_params.decimals, + "default_frozen": asset_create_params.default_frozen or False, + "lease": "", + "rekey_to": "", + "strict_empty_address_check": False, + }, + indent=4, + ) ) - signed_asset_config_txn = asset_config_txn.sign(creator_account.private_key) # type: ignore[no-untyped-call] - asset_config_txn_id = client.send_transaction(signed_asset_config_txn) - response = wait_for_confirmation(client, asset_config_txn_id, 4) - return response["asset-index"], asset_config_txn_id + # Build the transaction + suggested_params = client.suggested_params() + built_txn = build_asset_create_transaction( + params=asset_create_params, + suggested_params=suggested_params, + default_validity_window=1000, + default_validity_window_is_explicit=False, + is_localnet=False, + ) + + # Sign the transaction + signer = make_basic_account_transaction_signer(creator_account.private_key) + signed_txn_bytes = signer([built_txn.txn], [0])[0] + + # Send the transaction (signer returns encoded signed transaction bytes) + txid = get_transaction_id(built_txn.txn) + client.send_raw_transaction(signed_txn_bytes) + + # Wait for confirmation + response = _wait_for_confirmation(client, txid, 4) + + asset_index = getattr(response, "asset_index", None) + if asset_index is None: + raise Exception("Asset creation failed: no asset-index in response") + + return asset_index, txid diff --git a/src/algokit/core/tasks/mint/models.py b/src/algokit/core/tasks/mint/models.py index ba51c546f..788f2a131 100644 --- a/src/algokit/core/tasks/mint/models.py +++ b/src/algokit/core/tasks/mint/models.py @@ -3,7 +3,7 @@ from dataclasses import asdict, dataclass from pathlib import Path -from algosdk.transaction import SuggestedParams +from algokit_utils.clients import algod_models MIN_BG_COLOR_LENGTH = 6 # Based on ARC-0003 spec, must be a 6 character hex without a pre-pended # @@ -93,7 +93,7 @@ def from_json_file(cls, file_path: Path | None, name: str, decimals: int = 0) -> @dataclass class AssetConfigTxnParams: sender: str - sp: SuggestedParams + sp: algod_models.SuggestedParams unit_name: str asset_name: str url: str diff --git a/src/algokit/core/tasks/vanity_address.py b/src/algokit/core/tasks/vanity_address.py index 426cefd9f..a8b031dc5 100644 --- a/src/algokit/core/tasks/vanity_address.py +++ b/src/algokit/core/tasks/vanity_address.py @@ -1,3 +1,4 @@ +import base64 import logging import multiprocessing import signal @@ -10,14 +11,37 @@ from multiprocessing import Process, Queue, cpu_count from timeit import default_timer as timer -import algosdk -from algosdk.mnemonic import from_private_key, to_private_key +import nacl.signing +from algokit_utils.algo25 import secret_key_to_mnemonic, seed_from_mnemonic +from algokit_utils.common import address_from_public_key logger = logging.getLogger(__name__) PROGRESS_REFRESH_INTERVAL_SECONDS = 5 +def _generate_account() -> tuple[bytes, str]: + """ + Generate a new Algorand account. + + Returns: + tuple[bytes, str]: A tuple containing the secret key (64 bytes) and the address (string). + The secret key format is seed (32 bytes) + public key (32 bytes). + """ + # Generate a random signing key + signing_key = nacl.signing.SigningKey.generate() + public_key = signing_key.verify_key.encode() + seed = bytes(signing_key) + + # Secret key is seed + public key + secret_key = seed + public_key + + # Generate the address from the public key + address = address_from_public_key(public_key) + + return secret_key, address + + class MatchType(Enum): START = "start" ANYWHERE = "anywhere" @@ -94,14 +118,14 @@ def _search_for_matching_address(keyword: str, match: MatchType, counter: Counte batch_size = 100 while True: - private_key, address = algosdk.account.generate_account() # type: ignore[no-untyped-call] + secret_key, address = _generate_account() local_count += 1 if local_count % batch_size == 0: counter.increment(local_count) local_count = 0 if MATCH_FUNCTIONS[match](address, keyword): - generated_mnemonic = from_private_key(private_key) # type: ignore[no-untyped-call] + generated_mnemonic = secret_key_to_mnemonic(secret_key) queue.put((address, generated_mnemonic)) return except KeyboardInterrupt: @@ -155,8 +179,14 @@ def signal_handler(sig: int, frame: types.FrameType | None) -> typing.NoReturn: for p in jobs: p.terminate() + # Get seed and derive public key to create 64-byte private key (seed + pubkey) + seed = seed_from_mnemonic(mnemonic) + signing_key = nacl.signing.SigningKey(seed) + public_key = signing_key.verify_key.encode() + private_key = base64.b64encode(seed + public_key).decode() + return VanityAccount( mnemonic=mnemonic, address=address, - private_key=to_private_key(mnemonic), # type: ignore[no-untyped-call] + private_key=private_key, ) diff --git a/tests/project/deploy/test_deploy.py b/tests/project/deploy/test_deploy.py index 3e3ff5d38..4e43427e2 100644 --- a/tests/project/deploy/test_deploy.py +++ b/tests/project/deploy/test_deploy.py @@ -4,8 +4,8 @@ import pytest from _pytest.tmpdir import TempPathFactory -from algosdk.account import generate_account -from algosdk.mnemonic import from_private_key +from algokit_algosdk.account import generate_account +from algokit_algosdk.mnemonic import from_private_key from approvaltests.namer import NamerFactory from pytest_mock import MockerFixture diff --git a/tests/tasks/conftest.py b/tests/tasks/conftest.py index 5ffeacbbd..95d36100c 100644 --- a/tests/tasks/conftest.py +++ b/tests/tasks/conftest.py @@ -1,17 +1,28 @@ -from algokit_utils import SigningAccount -from algosdk import transaction +import base64 +from dataclasses import dataclass -DUMMY_SUGGESTED_PARAMS = transaction.SuggestedParams( # type: ignore[no-untyped-call] +from algokit_algod_client.models.suggested_params import SuggestedParams + + +@dataclass +class DummyAccount: + """Simple account holder for testing purposes.""" + + private_key: str + address: str + + +DUMMY_SUGGESTED_PARAMS = SuggestedParams( fee=0, - first=33652328, - last=33653328, - gen="testnet-v1.0", - gh="SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", + first_valid=33652328, + last_valid=33653328, + genesis_id="testnet-v1.0", + genesis_hash=base64.b64decode("SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="), min_fee=1000, flat_fee=True, consensus_version="https://github.com/algorandfoundation/specs/tree/abd3d4823c6f77349fc04c3af7b1e99fe4df699f", ) -DUMMY_ACCOUNT = SigningAccount( +DUMMY_ACCOUNT = DummyAccount( private_key="iLsfFiRDwi0ijFdvdyO1PGkYxooOanbJSgpJ4pPKjKZluk70pvuPX4dYD1Jir85uZP+AImM/8SBmdPRpBSTFAg==", address="MW5E55FG7OHV7B2YB5JGFL6ONZSP7ABCMM77CIDGOT2GSBJEYUBOF3UYKA", ) diff --git a/tests/tasks/test_asset.py b/tests/tasks/test_asset.py index fa93c2dce..ab12eb727 100644 --- a/tests/tasks/test_asset.py +++ b/tests/tasks/test_asset.py @@ -1,7 +1,9 @@ +import base64 import json +from algokit_algosdk import account from algokit_utils import BulkAssetOptInOutResult -from algosdk import account, mnemonic +from algokit_utils.algo25 import secret_key_to_mnemonic from pytest_mock import MockerFixture from algokit.core.tasks.wallet import WALLET_ALIASES_KEYRING_USERNAME @@ -15,7 +17,9 @@ def _generate_account() -> tuple[str, str]: def _get_mnemonic_from_private_key(private_key: str) -> str: - return str(mnemonic.from_private_key(private_key)) # type: ignore[no-untyped-call] + # Convert base64-encoded private key to bytes for secret_key_to_mnemonic + private_key_bytes = base64.b64decode(private_key) + return secret_key_to_mnemonic(private_key_bytes) def test_opt_in_no_args() -> None: diff --git a/tests/tasks/test_mint.py b/tests/tasks/test_mint.py index 3e648ecf6..be1640834 100644 --- a/tests/tasks/test_mint.py +++ b/tests/tasks/test_mint.py @@ -1,10 +1,11 @@ +import base64 import json import re from pathlib import Path import click import pytest -from algosdk.mnemonic import from_private_key +from algokit_utils.algo25 import secret_key_to_mnemonic from approvaltests.namer import NamerFactory from pytest_httpx import HTTPXMock from pytest_mock import MockerFixture @@ -16,6 +17,12 @@ from tests.utils.click_invoker import invoke +def _get_mnemonic_from_private_key(private_key: str) -> str: + """Convert base64-encoded private key to mnemonic.""" + private_key_bytes = base64.b64decode(private_key) + return secret_key_to_mnemonic(private_key_bytes) + + @pytest.mark.parametrize(("account_type", "mutability"), [("alias", "mutable"), ("address", "immutable")]) @pytest.mark.parametrize("network", ["localnet", "testnet", "mainnet"]) def test_mint_token_successful( @@ -34,7 +41,7 @@ def test_mint_token_successful( prompt_input = None if account_type == "address": account = DUMMY_ACCOUNT.address - prompt_input = from_private_key(DUMMY_ACCOUNT.private_key) # type: ignore[no-untyped-call] + prompt_input = _get_mnemonic_from_private_key(DUMMY_ACCOUNT.private_key) else: account = "my_alias" mock_keyring[account] = json.dumps( @@ -54,7 +61,7 @@ def test_mint_token_successful( "bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe", ], ) - mocker.patch("algokit.core.tasks.mint.mint.wait_for_confirmation", return_value={"asset-index": 123}) + mocker.patch("algokit.core.tasks.mint.mint._wait_for_confirmation", return_value=mocker.MagicMock(asset_index=123)) mocker.patch( "algokit.cli.tasks.mint.get_pinata_jwt", return_value="dummy_key", @@ -63,7 +70,7 @@ def test_mint_token_successful( "algokit.cli.tasks.mint.validate_balance", ) algod_mock = mocker.MagicMock() - algod_mock.send_transaction.return_value = "dummy_tx_id" + algod_mock.send_raw_transaction.return_value = mocker.MagicMock(tx_id="dummy_tx_id") algod_mock.suggested_params.return_value = DUMMY_SUGGESTED_PARAMS mocker.patch("algokit.cli.tasks.mint.load_algod_client", return_value=algod_mock) @@ -123,7 +130,7 @@ def test_mint_token_successful_on_decimals( "bafkreiftmc4on252dnckhv7jdqnhkxjkpvlrekpevjwm3gjszygxkus5oe", ], ) - mocker.patch("algokit.core.tasks.mint.mint.wait_for_confirmation", return_value={"asset-index": 123}) + mocker.patch("algokit.core.tasks.mint.mint._wait_for_confirmation", return_value=mocker.MagicMock(asset_index=123)) mocker.patch( "algokit.cli.tasks.mint.get_pinata_jwt", return_value="dummy_key", @@ -132,7 +139,7 @@ def test_mint_token_successful_on_decimals( "algokit.cli.tasks.mint.validate_balance", ) algod_mock = mocker.MagicMock() - algod_mock.send_transaction.return_value = "dummy_tx_id" + algod_mock.send_raw_transaction.return_value = mocker.MagicMock(tx_id="dummy_tx_id") algod_mock.suggested_params.return_value = DUMMY_SUGGESTED_PARAMS mocker.patch("algokit.cli.tasks.mint.load_algod_client", return_value=algod_mock) @@ -157,7 +164,7 @@ def test_mint_token_pure_fractional_nft_ft_validation( network = "localnet" cwd = tmp_path_factory.mktemp("cwd") account = DUMMY_ACCOUNT.address - prompt_input = from_private_key(DUMMY_ACCOUNT.private_key) # type: ignore[no-untyped-call] + prompt_input = _get_mnemonic_from_private_key(DUMMY_ACCOUNT.private_key) (cwd / "image.png").touch() # Act @@ -181,7 +188,7 @@ def test_mint_token_pinata_error( cwd = tmp_path_factory.mktemp("cwd") account = "" account = DUMMY_ACCOUNT.address - prompt_input = from_private_key(DUMMY_ACCOUNT.private_key) # type: ignore[no-untyped-call] + prompt_input = _get_mnemonic_from_private_key(DUMMY_ACCOUNT.private_key) (cwd / "image.png").touch() httpx_mock.add_response(status_code=403, json={"ok": False}) @@ -216,7 +223,7 @@ def test_mint_token_no_pinata_jwt_error( cwd = tmp_path_factory.mktemp("cwd") account = "" account = DUMMY_ACCOUNT.address - prompt_input = from_private_key(DUMMY_ACCOUNT.private_key) # type: ignore[no-untyped-call] + prompt_input = _get_mnemonic_from_private_key(DUMMY_ACCOUNT.private_key) (cwd / "image.png").touch() mocker.patch( diff --git a/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt index 42048fc78..1836425c1 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt @@ -23,4 +23,4 @@ DEBUG: Asset config params: { Successfully minted the asset! Browse your asset at: https://explore.algokit.io/localnet/asset/123 -Check transaction status at: https://explore.algokit.io/localnet/transaction/dummy_tx_id +Check transaction status at: https://explore.algokit.io/localnet/transaction/MCT6IZK25IBEHYCXCCXVYFRHBSSDT3CK6YVBCSRNJ7L36DDLR5YQ diff --git a/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt index be3fd9fd4..4a33c23af 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt @@ -23,4 +23,4 @@ DEBUG: Asset config params: { Successfully minted the asset! Browse your asset at: https://explore.algokit.io/mainnet/asset/123 -Check transaction status at: https://explore.algokit.io/mainnet/transaction/dummy_tx_id +Check transaction status at: https://explore.algokit.io/mainnet/transaction/MCT6IZK25IBEHYCXCCXVYFRHBSSDT3CK6YVBCSRNJ7L36DDLR5YQ diff --git a/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt index 8aa9f3724..15e6d473c 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt @@ -23,4 +23,4 @@ DEBUG: Asset config params: { Successfully minted the asset! Browse your asset at: https://explore.algokit.io/testnet/asset/123 -Check transaction status at: https://explore.algokit.io/testnet/transaction/dummy_tx_id +Check transaction status at: https://explore.algokit.io/testnet/transaction/MCT6IZK25IBEHYCXCCXVYFRHBSSDT3CK6YVBCSRNJ7L36DDLR5YQ diff --git a/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt index f0a9da0de..b3afaa8ad 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt @@ -22,4 +22,4 @@ DEBUG: Asset config params: { Successfully minted the asset! Browse your asset at: https://explore.algokit.io/localnet/asset/123 -Check transaction status at: https://explore.algokit.io/localnet/transaction/dummy_tx_id +Check transaction status at: https://explore.algokit.io/localnet/transaction/I3UTXWJIS25PAOP7KBFCQDHZC3PMDQJDOO4XUQFJHQTB3ZBYBPYA diff --git a/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt index 9c9497bc0..e83d096e7 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt @@ -22,4 +22,4 @@ DEBUG: Asset config params: { Successfully minted the asset! Browse your asset at: https://explore.algokit.io/mainnet/asset/123 -Check transaction status at: https://explore.algokit.io/mainnet/transaction/dummy_tx_id +Check transaction status at: https://explore.algokit.io/mainnet/transaction/I3UTXWJIS25PAOP7KBFCQDHZC3PMDQJDOO4XUQFJHQTB3ZBYBPYA diff --git a/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt index 892d78ae1..dced73bf1 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt @@ -22,4 +22,4 @@ DEBUG: Asset config params: { Successfully minted the asset! Browse your asset at: https://explore.algokit.io/testnet/asset/123 -Check transaction status at: https://explore.algokit.io/testnet/transaction/dummy_tx_id +Check transaction status at: https://explore.algokit.io/testnet/transaction/I3UTXWJIS25PAOP7KBFCQDHZC3PMDQJDOO4XUQFJHQTB3ZBYBPYA diff --git a/tests/tasks/test_mint.test_mint_token_successful_on_decimals.decimals_given_params.approved.txt b/tests/tasks/test_mint.test_mint_token_successful_on_decimals.decimals_given_params.approved.txt index 2d84885d9..bb1ebd954 100644 --- a/tests/tasks/test_mint.test_mint_token_successful_on_decimals.decimals_given_params.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful_on_decimals.decimals_given_params.approved.txt @@ -22,4 +22,4 @@ DEBUG: Asset config params: { Successfully minted the asset! Browse your asset at: https://explore.algokit.io/localnet/asset/123 -Check transaction status at: https://explore.algokit.io/localnet/transaction/dummy_tx_id +Check transaction status at: https://explore.algokit.io/localnet/transaction/Z7YFUSBBC4TQBYZQ3L7PHW75ZZNJ57C6M5LORMFNDRZGJOWIVAZQ diff --git a/tests/tasks/test_mint.test_mint_token_successful_on_decimals.no_decimals_given.approved.txt b/tests/tasks/test_mint.test_mint_token_successful_on_decimals.no_decimals_given.approved.txt index b2ee8eb6c..94a9b43df 100644 --- a/tests/tasks/test_mint.test_mint_token_successful_on_decimals.no_decimals_given.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful_on_decimals.no_decimals_given.approved.txt @@ -23,4 +23,4 @@ DEBUG: Asset config params: { Successfully minted the asset! Browse your asset at: https://explore.algokit.io/localnet/asset/123 -Check transaction status at: https://explore.algokit.io/localnet/transaction/dummy_tx_id +Check transaction status at: https://explore.algokit.io/localnet/transaction/Z7YFUSBBC4TQBYZQ3L7PHW75ZZNJ57C6M5LORMFNDRZGJOWIVAZQ diff --git a/tests/tasks/test_nfd_lookup.py b/tests/tasks/test_nfd_lookup.py index 5eacb29c0..5ceda0197 100644 --- a/tests/tasks/test_nfd_lookup.py +++ b/tests/tasks/test_nfd_lookup.py @@ -1,4 +1,4 @@ -import algosdk +import algokit_algosdk.account from pytest_httpx import HTTPXMock from tests.utils.approvals import verify @@ -27,7 +27,7 @@ def test_nfd_lookup_by_domain_success(httpx_mock: HTTPXMock) -> None: def test_nfd_lookup_by_address_success(httpx_mock: HTTPXMock) -> None: # Arrange - _, dummy_wallet = algosdk.account.generate_account() # type: ignore[no-untyped-call] + _, dummy_wallet = algokit_algosdk.account.generate_account() # type: ignore[no-untyped-call] httpx_mock.add_response( url=f"https://api.nf.domains/nfd/lookup?address={dummy_wallet}&view=thumbnail&allowUnverified=false", json={ diff --git a/tests/tasks/test_send_transaction.py b/tests/tasks/test_send_transaction.py index 7087ed6e1..a2c79fce9 100644 --- a/tests/tasks/test_send_transaction.py +++ b/tests/tasks/test_send_transaction.py @@ -1,8 +1,20 @@ +import base64 import json +from pathlib import Path +from typing import cast import click import pytest -from algosdk import encoding, transaction +from algokit_transact import ( + PaymentTransactionFields, + SignedTransaction, + Transaction, + TransactionType, + decode_signed_transaction, + encode_signed_transaction, + group_transactions, + make_basic_account_transaction_signer, +) from pytest_mock import MockerFixture from tests.tasks.conftest import DUMMY_ACCOUNT, DUMMY_SUGGESTED_PARAMS @@ -10,42 +22,87 @@ from tests.utils.click_invoker import invoke -def _generate_dummy_signed_txn(*, amount: int = 1, encode: bool = False) -> transaction.SignedTransaction | str: - unsigned_txn = transaction.PaymentTxn( # type: ignore[no-untyped-call] - DUMMY_ACCOUNT.address, DUMMY_SUGGESTED_PARAMS, DUMMY_ACCOUNT.address, amt=amount +def _write_signed_transactions_to_file(signed_txns: list[SignedTransaction], file_path: Path) -> None: + """Write signed transactions to a file in msgpack format. + + This mimics the behavior of algosdk's transaction.write_to_file() but uses + algokit_transact's encode_signed_transaction. + """ + with file_path.open("wb") as f: + for stx in signed_txns: + f.write(encode_signed_transaction(stx)) + + +def _generate_dummy_signed_txn(*, amount: int = 1, encode: bool = False) -> SignedTransaction | str: + # Create unsigned transaction + unsigned_txn = Transaction( + transaction_type=TransactionType.Payment, + sender=DUMMY_ACCOUNT.address, + first_valid=DUMMY_SUGGESTED_PARAMS.first_valid, + last_valid=DUMMY_SUGGESTED_PARAMS.last_valid, + fee=DUMMY_SUGGESTED_PARAMS.fee, + genesis_hash=DUMMY_SUGGESTED_PARAMS.genesis_hash, + genesis_id=DUMMY_SUGGESTED_PARAMS.genesis_id, + payment=PaymentTransactionFields( + receiver=DUMMY_ACCOUNT.address, + amount=amount, + close_remainder_to=None, + ), ) - txn = unsigned_txn.sign(DUMMY_ACCOUNT.private_key) # type: ignore[no-untyped-call] + + # Sign the transaction + signer = make_basic_account_transaction_signer(DUMMY_ACCOUNT.private_key) + signed_txn_bytes = signer([unsigned_txn], [0])[0] if encode: - return str(encoding.msgpack_encode(txn)) # type: ignore[no-untyped-call] + # Return base64-encoded string for CLI input + return base64.b64encode(signed_txn_bytes).decode() - return txn # type: ignore[no-any-return] + # Decode back to SignedTransaction object if not encoding + return decode_signed_transaction(signed_txn_bytes) -def _generate_dummy_signed_txn_group() -> list[transaction.SignedTransaction]: +def _generate_dummy_signed_txn_group() -> list[SignedTransaction]: + # Create unsigned transactions txns = [ - transaction.PaymentTxn(DUMMY_ACCOUNT.address, DUMMY_SUGGESTED_PARAMS, DUMMY_ACCOUNT.address, amt=i) # type: ignore[no-untyped-call] + Transaction( + transaction_type=TransactionType.Payment, + sender=DUMMY_ACCOUNT.address, + first_valid=DUMMY_SUGGESTED_PARAMS.first_valid, + last_valid=DUMMY_SUGGESTED_PARAMS.last_valid, + fee=DUMMY_SUGGESTED_PARAMS.fee if i != 0 else 3000, + genesis_hash=DUMMY_SUGGESTED_PARAMS.genesis_hash, + genesis_id=DUMMY_SUGGESTED_PARAMS.genesis_id, + payment=PaymentTransactionFields( + receiver=DUMMY_ACCOUNT.address, + amount=i, + close_remainder_to=None, + ), + ) for i in range(3) ] - txns[0].fee = 3000 - gid = transaction.calculate_group_id(txns) # type: ignore[no-untyped-call] - signed_txns = [] - for txn in txns: - txn.group = gid - signed_txns.append(txn.sign(DUMMY_ACCOUNT.private_key)) # type: ignore[no-untyped-call] + # Group the transactions + grouped_txns = group_transactions(txns) + + # Sign all transactions + signer = make_basic_account_transaction_signer(DUMMY_ACCOUNT.private_key) + signed_txn_bytes_list = signer(grouped_txns, list(range(len(grouped_txns)))) - return signed_txns + # Decode back to SignedTransaction objects + from algokit_transact import decode_signed_transaction + + return [decode_signed_transaction(stx_bytes) for stx_bytes in signed_txn_bytes_list] def test_send_atomic_txn_group_successful(tmp_path_factory: pytest.TempPathFactory, mocker: MockerFixture) -> None: # Arrange cwd = tmp_path_factory.mktemp("cwd") txns = _generate_dummy_signed_txn_group() - transaction.write_to_file(txns, str(cwd / "dummy.txns")) # type: ignore[no-untyped-call] + _write_signed_transactions_to_file(txns, cwd / "dummy.txns") algod_mock = mocker.MagicMock() - algod_mock.send_transactions.return_value = "dummy_tx_id" + algod_mock.send_raw_transaction.return_value = mocker.MagicMock(tx_id="dummy_tx_id") mocker.patch("algokit.cli.tasks.send_transaction.load_algod_client", return_value=algod_mock) # Act @@ -59,7 +116,7 @@ def test_send_atomic_txn_group_successful(tmp_path_factory: pytest.TempPathFacto def test_send_from_transaction_successful(mocker: MockerFixture) -> None: # Arrange algod_mock = mocker.MagicMock() - algod_mock.send_transaction.return_value = "dummy_tx_id" + algod_mock.send_raw_transaction.return_value = mocker.MagicMock(tx_id="dummy_tx_id") mocker.patch("algokit.cli.tasks.send_transaction.load_algod_client", return_value=algod_mock) # Act @@ -77,13 +134,11 @@ def test_send_from_file_successful( # Arrange cwd = tmp_path_factory.mktemp("cwd") - transaction.write_to_file( # type: ignore[no-untyped-call] - [_generate_dummy_signed_txn(amount=i) for i in range(20)], - str(cwd / "dummy.txns"), - ) + signed_txns = [cast("SignedTransaction", _generate_dummy_signed_txn(amount=i)) for i in range(20)] + _write_signed_transactions_to_file(signed_txns, cwd / "dummy.txns") algod_mock = mocker.MagicMock() - algod_mock.send_transaction.side_effect = [f"dummy_tx_id_{i}" for i in range(20)] + algod_mock.send_raw_transaction.side_effect = [mocker.MagicMock(tx_id=f"dummy_tx_id_{i}") for i in range(20)] mocker.patch("algokit.cli.tasks.send_transaction.load_algod_client", return_value=algod_mock) # Act @@ -105,7 +160,7 @@ def test_send_from_piped_input_successful( txns = [{"content": _generate_dummy_signed_txn(amount=i, encode=True), "transaction_id": str(i)} for i in range(20)] algod_mock = mocker.MagicMock() - algod_mock.send_transaction.side_effect = [f"dummy_tx_id_{i}" for i in range(20)] + algod_mock.send_raw_transaction.side_effect = [mocker.MagicMock(tx_id=f"dummy_tx_id_{i}") for i in range(20)] mocker.patch("algokit.cli.tasks.send_transaction.load_algod_client", return_value=algod_mock) mocker.patch("algokit.cli.tasks.send_transaction.stdin_has_content", return_value=True) diff --git a/tests/tasks/test_send_transaction.test_decoding_error.approved.txt b/tests/tasks/test_send_transaction.test_decoding_error.approved.txt index f85218692..a46c58ded 100644 --- a/tests/tasks/test_send_transaction.test_decoding_error.approved.txt +++ b/tests/tasks/test_send_transaction.test_decoding_error.approved.txt @@ -1,2 +1,3 @@ -DEBUG: argument of type 'int' is not iterable +DEBUG: No valid transactions found in file +DEBUG: Failed to read transactions from file: No valid transactions found in file Error: Failed to decode transaction! If you are intending to send multiple transactions use `--file` instead. diff --git a/tests/tasks/test_send_transaction.test_file_decoding_no_txn_error.approved.txt b/tests/tasks/test_send_transaction.test_file_decoding_no_txn_error.approved.txt index ec447b1cb..a46c58ded 100644 --- a/tests/tasks/test_send_transaction.test_file_decoding_no_txn_error.approved.txt +++ b/tests/tasks/test_send_transaction.test_file_decoding_no_txn_error.approved.txt @@ -1 +1,3 @@ -Error: No valid transactions found! +DEBUG: No valid transactions found in file +DEBUG: Failed to read transactions from file: No valid transactions found in file +Error: Failed to decode transaction! If you are intending to send multiple transactions use `--file` instead. diff --git a/tests/tasks/test_sign_transaction.py b/tests/tasks/test_sign_transaction.py index defc82ebc..81e917712 100644 --- a/tests/tasks/test_sign_transaction.py +++ b/tests/tasks/test_sign_transaction.py @@ -1,8 +1,13 @@ +import base64 import json +from pathlib import Path import click import pytest -from algosdk import encoding, mnemonic, transaction +from algokit_transact.models.payment import PaymentTransactionFields +from algokit_transact.models.transaction import Transaction, TransactionType +from algokit_utils.algo25 import secret_key_to_mnemonic +from algokit_utils.transact import decode_transactions, encode_transactions, group_transactions from algokit.core.tasks.wallet import WALLET_ALIASES_KEYRING_USERNAME from tests.tasks.conftest import DUMMY_ACCOUNT, DUMMY_SUGGESTED_PARAMS @@ -10,12 +15,67 @@ from tests.utils.click_invoker import invoke -def _generate_dummy_txn(sender: str, amount: int = 1) -> transaction.PaymentTxn: - return transaction.PaymentTxn(sender, DUMMY_SUGGESTED_PARAMS, sender, amt=amount) # type: ignore[no-untyped-call] +def _write_transactions_to_file(transactions: list[Transaction], file_path: Path | str) -> None: + """Write transactions to a file in msgpack format (compatible with algosdk's write_to_file).""" + encoded_txns = encode_transactions(transactions) + with Path(file_path).open("wb") as f: + for encoded_txn in encoded_txns: + f.write(encoded_txn) + + +def _read_transactions_from_file(file_path: Path | str) -> list[Transaction]: + """Read transactions from a file in msgpack format (compatible with algosdk's retrieve_from_file).""" + import msgpack + + with Path(file_path).open("rb") as f: + content = f.read() + + # Split the concatenated msgpack messages into individual transaction dicts + unpacker = msgpack.Unpacker() + unpacker.feed(content) + + # Collect all top-level msgpack objects (each should be a dict representing a transaction) + transaction_dicts = [] + for unpacked_obj in unpacker: + if isinstance(unpacked_obj, dict): + transaction_dicts.append(unpacked_obj) + + # Re-encode each dict to bytes for decode_transactions + transaction_bytes = [msgpack.packb(txn_dict) for txn_dict in transaction_dicts] + + # Decode using algokit_utils + return decode_transactions(transaction_bytes) + + +def _generate_dummy_txn(sender: str, amount: int = 1) -> Transaction: + """Generate a dummy payment transaction for testing.""" + return Transaction( + transaction_type=TransactionType.Payment, + sender=sender, + first_valid=DUMMY_SUGGESTED_PARAMS.first_valid, + last_valid=DUMMY_SUGGESTED_PARAMS.last_valid, + fee=DUMMY_SUGGESTED_PARAMS.min_fee, + genesis_id=DUMMY_SUGGESTED_PARAMS.genesis_id, + genesis_hash=DUMMY_SUGGESTED_PARAMS.genesis_hash, + payment=PaymentTransactionFields( + amount=amount, + receiver=sender, + ), + ) def _get_mnemonic_from_private_key(private_key: str) -> str: - return str(mnemonic.from_private_key(private_key)) # type: ignore[no-untyped-call] + """Convert a private key to a mnemonic phrase. + + Args: + private_key: Base64-encoded private key string (64 bytes when decoded: 32-byte seed + 32-byte public key) + + Returns: + 25-word mnemonic phrase + """ + # Decode the base64 string to get the actual bytes + private_key_bytes = base64.b64decode(private_key) + return secret_key_to_mnemonic(private_key_bytes) def test_sign_atomic_txn_group_successful( @@ -34,10 +94,8 @@ def test_sign_atomic_txn_group_successful( mock_keyring[WALLET_ALIASES_KEYRING_USERNAME] = json.dumps([alias_name]) txn_a = _generate_dummy_txn(DUMMY_ACCOUNT.address) txn_b = _generate_dummy_txn(DUMMY_ACCOUNT.address) - gid = transaction.calculate_group_id([txn_a, txn_b]) # type: ignore[no-untyped-call] - txn_a.group = gid - txn_b.group = gid - transaction.write_to_file([txn_a, txn_b], str(cwd / "dummy.txns")) # type: ignore[no-untyped-call] + grouped_txns = group_transactions([txn_a, txn_b]) + _write_transactions_to_file(grouped_txns, cwd / "dummy.txns") # Act result = invoke(f"task sign -a {alias_name} --file dummy.txns", input="y", cwd=cwd) @@ -61,7 +119,8 @@ def test_sign_from_stdin_with_alias_successful(mock_keyring: dict[str, str]) -> dummy_txn = _generate_dummy_txn(DUMMY_ACCOUNT.address) # Act - txn = encoding.msgpack_encode({"txn": dummy_txn.dictify()}) # type: ignore[no-untyped-call] + encoded_txns = encode_transactions([dummy_txn]) + txn = base64.b64encode(encoded_txns[0]).decode() result = invoke(f"task sign -a {alias_name} --transaction {txn}", input="y") # Assert @@ -74,7 +133,8 @@ def test_sign_from_stdin_with_address_successful() -> None: dummy_txn = _generate_dummy_txn(DUMMY_ACCOUNT.address) # Act - txn = encoding.msgpack_encode({"txn": dummy_txn.dictify()}) # type: ignore[no-untyped-call] + encoded_txns = encode_transactions([dummy_txn]) + txn = base64.b64encode(encoded_txns[0]).decode() result = invoke( f"task sign -a {DUMMY_ACCOUNT.address} --transaction {txn}", input=f"{_get_mnemonic_from_private_key(DUMMY_ACCOUNT.private_key)}\ny", @@ -100,13 +160,13 @@ def test_sign_many_from_file_with_alias_successful( ) mock_keyring[WALLET_ALIASES_KEYRING_USERNAME] = json.dumps([alias_name]) _generate_dummy_txn(DUMMY_ACCOUNT.address) - transaction.write_to_file( # type: ignore[no-untyped-call] + _write_transactions_to_file( [ _generate_dummy_txn(DUMMY_ACCOUNT.address, 1), _generate_dummy_txn(DUMMY_ACCOUNT.address, 2), _generate_dummy_txn(DUMMY_ACCOUNT.address, 3), ], - str(cwd / "dummy.txns"), + cwd / "dummy.txns", ) # Act @@ -123,13 +183,13 @@ def test_sign_many_from_file_with_address_successful( # Arrange cwd = tmp_path_factory.mktemp("cwd") _generate_dummy_txn(DUMMY_ACCOUNT.address) - transaction.write_to_file( # type: ignore[no-untyped-call] + _write_transactions_to_file( [ _generate_dummy_txn(DUMMY_ACCOUNT.address, 1), _generate_dummy_txn(DUMMY_ACCOUNT.address, 2), _generate_dummy_txn(DUMMY_ACCOUNT.address, 3), ], - str(cwd / "dummy.txns"), + cwd / "dummy.txns", ) # Act diff --git a/tests/tasks/test_sign_transaction.test_sign_atomic_txn_group_successful.approved.txt b/tests/tasks/test_sign_transaction.test_sign_atomic_txn_group_successful.approved.txt index 33a9a5a6a..ae3ce3686 100644 --- a/tests/tasks/test_sign_transaction.test_sign_atomic_txn_group_successful.approved.txt +++ b/tests/tasks/test_sign_transaction.test_sign_atomic_txn_group_successful.approved.txt @@ -1,41 +1,43 @@ [ { - "transaction_id": "RUU4DMAYJ5TLIEZ3ZT3PWTDPUOHCGOFY26JAXMOQXE52J2W6D7UA", + "transaction_id": "LSDGHVZFPJBI5XFP54OMS4PQMLLLNCRSKCEQH556XKA54DLSXBDQ", "content": { - "amt": 1, + "type": "pay", + "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", "fv": 33652328, - "gen": "testnet-v1.0", - "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", - "grp": "Vyhyt7HcQWkkBxcIR4zP+GkJLUAmN2H2D5Hx03fAVvo=", "lv": 33653328, - "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "type": "pay" + "fee": 1000, + "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", + "gen": "testnet-v1.0", + "grp": "FasevOeBXn9mn+ASh4lTgNY6K4T3aI4RP++2NsukL2M=", + "amt": 1, + "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=" } }, { - "transaction_id": "RUU4DMAYJ5TLIEZ3ZT3PWTDPUOHCGOFY26JAXMOQXE52J2W6D7UA", + "transaction_id": "LSDGHVZFPJBI5XFP54OMS4PQMLLLNCRSKCEQH556XKA54DLSXBDQ", "content": { - "amt": 1, + "type": "pay", + "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", "fv": 33652328, - "gen": "testnet-v1.0", - "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", - "grp": "Vyhyt7HcQWkkBxcIR4zP+GkJLUAmN2H2D5Hx03fAVvo=", "lv": 33653328, - "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "type": "pay" + "fee": 1000, + "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", + "gen": "testnet-v1.0", + "grp": "FasevOeBXn9mn+ASh4lTgNY6K4T3aI4RP++2NsukL2M=", + "amt": 1, + "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=" } } ] Would you like to proceed with signing the above? (y, n) [n]: y [ { - "transaction_id": "RUU4DMAYJ5TLIEZ3ZT3PWTDPUOHCGOFY26JAXMOQXE52J2W6D7UA", - "content": "gqNzaWfEQMSdIjL5dbUk+/lVCi0AWs84ikMH0gEErgYxuNHpY/dYkKIvY9XlhiszYNMhk2XlkvTCkrrWGOWmblX3Af43tg+jdHhuiaNhbXQBomZ2zgIBfmijZ2VurHRlc3RuZXQtdjEuMKJnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKjZ3JwxCBXKHK3sdxBaSQHFwhHjM/4aQktQCY3YfYPkfHTd8BW+qJsds4CAYJQo3JjdsQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKjc25kxCBluk70pvuPX4dYD1Jir85uZP+AImM/8SBmdPRpBSTFAqR0eXBlo3BheQ==" + "transaction_id": "LSDGHVZFPJBI5XFP54OMS4PQMLLLNCRSKCEQH556XKA54DLSXBDQ", + "content": "gqNzaWfEQPJQBvnTFZ8GDLTNH41LqGXH4my3oO/PL0tnqS1aHsXRYnYSXc7rf7zjgw8h7l7ReRcvY0o60dCMMecNlW9EGAWjdHhuiqNhbXQBo2ZlZc0D6KJmds4CAX5oo2dlbqx0ZXN0bmV0LXYxLjCiZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToio2dycMQgFasevOeBXn9mn+ASh4lTgNY6K4T3aI4RP++2NsukL2OibHbOAgGCUKNyY3bEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCo3NuZMQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKkdHlwZaNwYXk=" }, { - "transaction_id": "RUU4DMAYJ5TLIEZ3ZT3PWTDPUOHCGOFY26JAXMOQXE52J2W6D7UA", - "content": "gqNzaWfEQMSdIjL5dbUk+/lVCi0AWs84ikMH0gEErgYxuNHpY/dYkKIvY9XlhiszYNMhk2XlkvTCkrrWGOWmblX3Af43tg+jdHhuiaNhbXQBomZ2zgIBfmijZ2VurHRlc3RuZXQtdjEuMKJnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKjZ3JwxCBXKHK3sdxBaSQHFwhHjM/4aQktQCY3YfYPkfHTd8BW+qJsds4CAYJQo3JjdsQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKjc25kxCBluk70pvuPX4dYD1Jir85uZP+AImM/8SBmdPRpBSTFAqR0eXBlo3BheQ==" + "transaction_id": "LSDGHVZFPJBI5XFP54OMS4PQMLLLNCRSKCEQH556XKA54DLSXBDQ", + "content": "gqNzaWfEQPJQBvnTFZ8GDLTNH41LqGXH4my3oO/PL0tnqS1aHsXRYnYSXc7rf7zjgw8h7l7ReRcvY0o60dCMMecNlW9EGAWjdHhuiqNhbXQBo2ZlZc0D6KJmds4CAX5oo2dlbqx0ZXN0bmV0LXYxLjCiZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToio2dycMQgFasevOeBXn9mn+ASh4lTgNY6K4T3aI4RP++2NsukL2OibHbOAgGCUKNyY3bEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCo3NuZMQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKkdHlwZaNwYXk=" } ] diff --git a/tests/tasks/test_sign_transaction.test_sign_from_stdin_with_address_successful.approved.txt b/tests/tasks/test_sign_transaction.test_sign_from_stdin_with_address_successful.approved.txt index b34b60143..11f512b90 100644 --- a/tests/tasks/test_sign_transaction.test_sign_from_stdin_with_address_successful.approved.txt +++ b/tests/tasks/test_sign_transaction.test_sign_from_stdin_with_address_successful.approved.txt @@ -1,23 +1,24 @@ Enter the mnemonic phrase (25 words separated by whitespace): [ { - "transaction_id": "YGSOMX5QSASQALR5V4MH47L4GEHFJZVGSUETJAWUFM2I6PJAQL4Q", + "transaction_id": "FXAXUBFEV7TTXNDPNWDEVIPHP5FFILUBHLFZUU5ZUWO6PDBDHNBA", "content": { - "amt": 1, + "type": "pay", + "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", "fv": 33652328, - "gen": "testnet-v1.0", - "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", "lv": 33653328, - "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "type": "pay" + "fee": 1000, + "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", + "gen": "testnet-v1.0", + "amt": 1, + "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=" } } ] Would you like to proceed with signing the above? (y, n) [n]: y [ { - "transaction_id": "YGSOMX5QSASQALR5V4MH47L4GEHFJZVGSUETJAWUFM2I6PJAQL4Q", - "content": "gqNzaWfEQHHuPbhkAADyq8eKU/NiDCuJ+cnW9MrHT3iAAEPm+okmoio/rmgctA7QUpqqd4eF5aYlUcgz9EbU+uUXS1rFOg2jdHhuiKNhbXQBomZ2zgIBfmijZ2VurHRlc3RuZXQtdjEuMKJnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAgGCUKNyY3bEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCo3NuZMQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKkdHlwZaNwYXk=" + "transaction_id": "FXAXUBFEV7TTXNDPNWDEVIPHP5FFILUBHLFZUU5ZUWO6PDBDHNBA", + "content": "gqNzaWfEQOQpODGqNgY91HdDDSGiDNaAa10DK3TTGBrDclzUpppvRkvxvQtB3GQWVVFXqIg4zsZn6a3xxT5dYmTFixo4gw+jdHhuiaNhbXQBo2ZlZc0D6KJmds4CAX5oo2dlbqx0ZXN0bmV0LXYxLjCiZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToiomx2zgIBglCjcmN2xCBluk70pvuPX4dYD1Jir85uZP+AImM/8SBmdPRpBSTFAqNzbmTEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCpHR5cGWjcGF5" } ] diff --git a/tests/tasks/test_sign_transaction.test_sign_from_stdin_with_alias_successful.approved.txt b/tests/tasks/test_sign_transaction.test_sign_from_stdin_with_alias_successful.approved.txt index c4e9e2b3b..ef92889e5 100644 --- a/tests/tasks/test_sign_transaction.test_sign_from_stdin_with_alias_successful.approved.txt +++ b/tests/tasks/test_sign_transaction.test_sign_from_stdin_with_alias_successful.approved.txt @@ -1,22 +1,23 @@ [ { - "transaction_id": "YGSOMX5QSASQALR5V4MH47L4GEHFJZVGSUETJAWUFM2I6PJAQL4Q", + "transaction_id": "FXAXUBFEV7TTXNDPNWDEVIPHP5FFILUBHLFZUU5ZUWO6PDBDHNBA", "content": { - "amt": 1, + "type": "pay", + "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", "fv": 33652328, - "gen": "testnet-v1.0", - "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", "lv": 33653328, - "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "type": "pay" + "fee": 1000, + "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", + "gen": "testnet-v1.0", + "amt": 1, + "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=" } } ] Would you like to proceed with signing the above? (y, n) [n]: y [ { - "transaction_id": "YGSOMX5QSASQALR5V4MH47L4GEHFJZVGSUETJAWUFM2I6PJAQL4Q", - "content": "gqNzaWfEQHHuPbhkAADyq8eKU/NiDCuJ+cnW9MrHT3iAAEPm+okmoio/rmgctA7QUpqqd4eF5aYlUcgz9EbU+uUXS1rFOg2jdHhuiKNhbXQBomZ2zgIBfmijZ2VurHRlc3RuZXQtdjEuMKJnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAgGCUKNyY3bEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCo3NuZMQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKkdHlwZaNwYXk=" + "transaction_id": "FXAXUBFEV7TTXNDPNWDEVIPHP5FFILUBHLFZUU5ZUWO6PDBDHNBA", + "content": "gqNzaWfEQOQpODGqNgY91HdDDSGiDNaAa10DK3TTGBrDclzUpppvRkvxvQtB3GQWVVFXqIg4zsZn6a3xxT5dYmTFixo4gw+jdHhuiaNhbXQBo2ZlZc0D6KJmds4CAX5oo2dlbqx0ZXN0bmV0LXYxLjCiZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToiomx2zgIBglCjcmN2xCBluk70pvuPX4dYD1Jir85uZP+AImM/8SBmdPRpBSTFAqNzbmTEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCpHR5cGWjcGF5" } ] diff --git a/tests/tasks/test_sign_transaction.test_sign_many_from_file_with_address_successful.approved.txt b/tests/tasks/test_sign_transaction.test_sign_many_from_file_with_address_successful.approved.txt index 906bb31b1..a3f1da84b 100644 --- a/tests/tasks/test_sign_transaction.test_sign_many_from_file_with_address_successful.approved.txt +++ b/tests/tasks/test_sign_transaction.test_sign_many_from_file_with_address_successful.approved.txt @@ -1,57 +1,60 @@ Enter the mnemonic phrase (25 words separated by whitespace): [ { - "transaction_id": "YGSOMX5QSASQALR5V4MH47L4GEHFJZVGSUETJAWUFM2I6PJAQL4Q", + "transaction_id": "FXAXUBFEV7TTXNDPNWDEVIPHP5FFILUBHLFZUU5ZUWO6PDBDHNBA", "content": { - "amt": 1, + "type": "pay", + "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", "fv": 33652328, - "gen": "testnet-v1.0", - "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", "lv": 33653328, - "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "type": "pay" + "fee": 1000, + "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", + "gen": "testnet-v1.0", + "amt": 1, + "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=" } }, { - "transaction_id": "MLS7IUJQVK7GABTCOLTG5QE7NWITX74D6YC3QZLN6Y5SZF23WZBQ", + "transaction_id": "U7BEN5KFHLXU45NWEDZCYOZGR3MAACTPJ3YNOPDWRRCBDCN2OARQ", "content": { - "amt": 2, + "type": "pay", + "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", "fv": 33652328, - "gen": "testnet-v1.0", - "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", "lv": 33653328, - "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "type": "pay" + "fee": 1000, + "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", + "gen": "testnet-v1.0", + "amt": 2, + "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=" } }, { - "transaction_id": "NEI3KU7ALQ6PFOSTYEN3LSJX2CUDEESDH2NH2XUJGYHNR3UVB3OQ", + "transaction_id": "XU2X2APELWEA5F5FJXRY3HY2HN2WZHZ5QXVB3KSWTII2GSFJGANQ", "content": { - "amt": 3, + "type": "pay", + "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", "fv": 33652328, - "gen": "testnet-v1.0", - "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", "lv": 33653328, - "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "type": "pay" + "fee": 1000, + "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", + "gen": "testnet-v1.0", + "amt": 3, + "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=" } } ] Would you like to proceed with signing the above? (y, n) [n]: y [ { - "transaction_id": "YGSOMX5QSASQALR5V4MH47L4GEHFJZVGSUETJAWUFM2I6PJAQL4Q", - "content": "gqNzaWfEQHHuPbhkAADyq8eKU/NiDCuJ+cnW9MrHT3iAAEPm+okmoio/rmgctA7QUpqqd4eF5aYlUcgz9EbU+uUXS1rFOg2jdHhuiKNhbXQBomZ2zgIBfmijZ2VurHRlc3RuZXQtdjEuMKJnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAgGCUKNyY3bEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCo3NuZMQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKkdHlwZaNwYXk=" + "transaction_id": "FXAXUBFEV7TTXNDPNWDEVIPHP5FFILUBHLFZUU5ZUWO6PDBDHNBA", + "content": "gqNzaWfEQOQpODGqNgY91HdDDSGiDNaAa10DK3TTGBrDclzUpppvRkvxvQtB3GQWVVFXqIg4zsZn6a3xxT5dYmTFixo4gw+jdHhuiaNhbXQBo2ZlZc0D6KJmds4CAX5oo2dlbqx0ZXN0bmV0LXYxLjCiZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToiomx2zgIBglCjcmN2xCBluk70pvuPX4dYD1Jir85uZP+AImM/8SBmdPRpBSTFAqNzbmTEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCpHR5cGWjcGF5" }, { - "transaction_id": "MLS7IUJQVK7GABTCOLTG5QE7NWITX74D6YC3QZLN6Y5SZF23WZBQ", - "content": "gqNzaWfEQMDbNg81bX8hvW+MHye1pJhtDxWvk/3Oec8lC8QZ5i0pn7LNnXTEniYzhECzjwxL11ENlTh6w66M2jl1f4YeZwijdHhuiKNhbXQComZ2zgIBfmijZ2VurHRlc3RuZXQtdjEuMKJnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAgGCUKNyY3bEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCo3NuZMQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKkdHlwZaNwYXk=" + "transaction_id": "U7BEN5KFHLXU45NWEDZCYOZGR3MAACTPJ3YNOPDWRRCBDCN2OARQ", + "content": "gqNzaWfEQKfuYSfeVHZOW7O2I388MWbjE1zRhp6zrZE7KJ4oV75XJpx8ExKByk9NIAYpyneekuoGDg4Ks+kVVcvT6X6J9wujdHhuiaNhbXQCo2ZlZc0D6KJmds4CAX5oo2dlbqx0ZXN0bmV0LXYxLjCiZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToiomx2zgIBglCjcmN2xCBluk70pvuPX4dYD1Jir85uZP+AImM/8SBmdPRpBSTFAqNzbmTEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCpHR5cGWjcGF5" }, { - "transaction_id": "NEI3KU7ALQ6PFOSTYEN3LSJX2CUDEESDH2NH2XUJGYHNR3UVB3OQ", - "content": "gqNzaWfEQJPaDlnXKBkMacMv6SNJmDlRf2dBzVBZwhOelc/Q+uriONVXzP0pqmZqqCua/fo3DxH9tbKyCDcSYVmn9MsaLgqjdHhuiKNhbXQDomZ2zgIBfmijZ2VurHRlc3RuZXQtdjEuMKJnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAgGCUKNyY3bEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCo3NuZMQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKkdHlwZaNwYXk=" + "transaction_id": "XU2X2APELWEA5F5FJXRY3HY2HN2WZHZ5QXVB3KSWTII2GSFJGANQ", + "content": "gqNzaWfEQEsValgtAQZFPE1/iDUyIr58QNhNCjogIK72ckwM78kyUaEX3+PYPLZDkoVLvjx5ChMrbB71avpVt0onfrqSvQCjdHhuiaNhbXQDo2ZlZc0D6KJmds4CAX5oo2dlbqx0ZXN0bmV0LXYxLjCiZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToiomx2zgIBglCjcmN2xCBluk70pvuPX4dYD1Jir85uZP+AImM/8SBmdPRpBSTFAqNzbmTEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCpHR5cGWjcGF5" } ] diff --git a/tests/tasks/test_sign_transaction.test_sign_many_from_file_with_alias_successful.approved.txt b/tests/tasks/test_sign_transaction.test_sign_many_from_file_with_alias_successful.approved.txt index ecd969451..43428e904 100644 --- a/tests/tasks/test_sign_transaction.test_sign_many_from_file_with_alias_successful.approved.txt +++ b/tests/tasks/test_sign_transaction.test_sign_many_from_file_with_alias_successful.approved.txt @@ -1,56 +1,59 @@ [ { - "transaction_id": "YGSOMX5QSASQALR5V4MH47L4GEHFJZVGSUETJAWUFM2I6PJAQL4Q", + "transaction_id": "FXAXUBFEV7TTXNDPNWDEVIPHP5FFILUBHLFZUU5ZUWO6PDBDHNBA", "content": { - "amt": 1, + "type": "pay", + "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", "fv": 33652328, - "gen": "testnet-v1.0", - "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", "lv": 33653328, - "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "type": "pay" + "fee": 1000, + "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", + "gen": "testnet-v1.0", + "amt": 1, + "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=" } }, { - "transaction_id": "MLS7IUJQVK7GABTCOLTG5QE7NWITX74D6YC3QZLN6Y5SZF23WZBQ", + "transaction_id": "U7BEN5KFHLXU45NWEDZCYOZGR3MAACTPJ3YNOPDWRRCBDCN2OARQ", "content": { - "amt": 2, + "type": "pay", + "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", "fv": 33652328, - "gen": "testnet-v1.0", - "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", "lv": 33653328, - "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "type": "pay" + "fee": 1000, + "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", + "gen": "testnet-v1.0", + "amt": 2, + "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=" } }, { - "transaction_id": "NEI3KU7ALQ6PFOSTYEN3LSJX2CUDEESDH2NH2XUJGYHNR3UVB3OQ", + "transaction_id": "XU2X2APELWEA5F5FJXRY3HY2HN2WZHZ5QXVB3KSWTII2GSFJGANQ", "content": { - "amt": 3, + "type": "pay", + "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", "fv": 33652328, - "gen": "testnet-v1.0", - "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", "lv": 33653328, - "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "snd": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=", - "type": "pay" + "fee": 1000, + "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", + "gen": "testnet-v1.0", + "amt": 3, + "rcv": "ZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQI=" } } ] Would you like to proceed with signing the above? (y, n) [n]: y [ { - "transaction_id": "YGSOMX5QSASQALR5V4MH47L4GEHFJZVGSUETJAWUFM2I6PJAQL4Q", - "content": "gqNzaWfEQHHuPbhkAADyq8eKU/NiDCuJ+cnW9MrHT3iAAEPm+okmoio/rmgctA7QUpqqd4eF5aYlUcgz9EbU+uUXS1rFOg2jdHhuiKNhbXQBomZ2zgIBfmijZ2VurHRlc3RuZXQtdjEuMKJnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAgGCUKNyY3bEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCo3NuZMQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKkdHlwZaNwYXk=" + "transaction_id": "FXAXUBFEV7TTXNDPNWDEVIPHP5FFILUBHLFZUU5ZUWO6PDBDHNBA", + "content": "gqNzaWfEQOQpODGqNgY91HdDDSGiDNaAa10DK3TTGBrDclzUpppvRkvxvQtB3GQWVVFXqIg4zsZn6a3xxT5dYmTFixo4gw+jdHhuiaNhbXQBo2ZlZc0D6KJmds4CAX5oo2dlbqx0ZXN0bmV0LXYxLjCiZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToiomx2zgIBglCjcmN2xCBluk70pvuPX4dYD1Jir85uZP+AImM/8SBmdPRpBSTFAqNzbmTEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCpHR5cGWjcGF5" }, { - "transaction_id": "MLS7IUJQVK7GABTCOLTG5QE7NWITX74D6YC3QZLN6Y5SZF23WZBQ", - "content": "gqNzaWfEQMDbNg81bX8hvW+MHye1pJhtDxWvk/3Oec8lC8QZ5i0pn7LNnXTEniYzhECzjwxL11ENlTh6w66M2jl1f4YeZwijdHhuiKNhbXQComZ2zgIBfmijZ2VurHRlc3RuZXQtdjEuMKJnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAgGCUKNyY3bEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCo3NuZMQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKkdHlwZaNwYXk=" + "transaction_id": "U7BEN5KFHLXU45NWEDZCYOZGR3MAACTPJ3YNOPDWRRCBDCN2OARQ", + "content": "gqNzaWfEQKfuYSfeVHZOW7O2I388MWbjE1zRhp6zrZE7KJ4oV75XJpx8ExKByk9NIAYpyneekuoGDg4Ks+kVVcvT6X6J9wujdHhuiaNhbXQCo2ZlZc0D6KJmds4CAX5oo2dlbqx0ZXN0bmV0LXYxLjCiZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToiomx2zgIBglCjcmN2xCBluk70pvuPX4dYD1Jir85uZP+AImM/8SBmdPRpBSTFAqNzbmTEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCpHR5cGWjcGF5" }, { - "transaction_id": "NEI3KU7ALQ6PFOSTYEN3LSJX2CUDEESDH2NH2XUJGYHNR3UVB3OQ", - "content": "gqNzaWfEQJPaDlnXKBkMacMv6SNJmDlRf2dBzVBZwhOelc/Q+uriONVXzP0pqmZqqCua/fo3DxH9tbKyCDcSYVmn9MsaLgqjdHhuiKNhbXQDomZ2zgIBfmijZ2VurHRlc3RuZXQtdjEuMKJnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAgGCUKNyY3bEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCo3NuZMQgZbpO9Kb7j1+HWA9SYq/ObmT/gCJjP/EgZnT0aQUkxQKkdHlwZaNwYXk=" + "transaction_id": "XU2X2APELWEA5F5FJXRY3HY2HN2WZHZ5QXVB3KSWTII2GSFJGANQ", + "content": "gqNzaWfEQEsValgtAQZFPE1/iDUyIr58QNhNCjogIK72ckwM78kyUaEX3+PYPLZDkoVLvjx5ChMrbB71avpVt0onfrqSvQCjdHhuiaNhbXQDo2ZlZc0D6KJmds4CAX5oo2dlbqx0ZXN0bmV0LXYxLjCiZ2jEIEhjtRiks8hOyBDyLU8QgcsPcfBZp6wg3sYvf3DlCToiomx2zgIBglCjcmN2xCBluk70pvuPX4dYD1Jir85uZP+AImM/8SBmdPRpBSTFAqNzbmTEIGW6TvSm+49fh1gPUmKvzm5k/4AiYz/xIGZ09GkFJMUCpHR5cGWjcGF5" } ] diff --git a/tests/tasks/test_transfer.py b/tests/tasks/test_transfer.py index 502411b13..12a61b123 100644 --- a/tests/tasks/test_transfer.py +++ b/tests/tasks/test_transfer.py @@ -1,8 +1,10 @@ +import base64 import json import pytest -from algokit_utils import SendAtomicTransactionComposerResults -from algosdk import account, mnemonic +from algokit_algosdk import account +from algokit_utils import SendTransactionComposerResults +from algokit_utils.algo25 import secret_key_to_mnemonic from pytest_mock import MockerFixture from algokit.core.tasks.wallet import WALLET_ALIASES_KEYRING_USERNAME @@ -21,7 +23,9 @@ def _generate_account() -> tuple[str, str]: def _get_mnemonic_from_private_key(private_key: str) -> str: - return str(mnemonic.from_private_key(private_key)) # type: ignore[no-untyped-call] + # Convert base64-encoded private key to bytes for secret_key_to_mnemonic + private_key_bytes = base64.b64decode(private_key) + return secret_key_to_mnemonic(private_key_bytes) def test_transfer_no_args() -> None: @@ -81,7 +85,7 @@ def test_transfer_algo_from_address_successful(mocker: MockerFixture) -> None: algorand_mock = mocker.MagicMock() composer_mock = mocker.MagicMock() composer_mock.add_payment.return_value = composer_mock - composer_mock.send.return_value = SendAtomicTransactionComposerResults( + composer_mock.send.return_value = SendTransactionComposerResults( group_id="dummy_group_id", confirmations=[], tx_ids=["dummy_txid"], @@ -111,7 +115,7 @@ def test_transfer_algo_from_alias_successful(mocker: MockerFixture, mock_keyring algorand_mock = mocker.MagicMock() composer_mock = mocker.MagicMock() composer_mock.add_payment.return_value = composer_mock - composer_mock.send.return_value = SendAtomicTransactionComposerResults( + composer_mock.send.return_value = SendTransactionComposerResults( group_id="dummy_group_id", confirmations=[], tx_ids=["dummy_txid"], @@ -151,7 +155,7 @@ def test_transfer_asset_from_address_successful(mocker: MockerFixture) -> None: algorand_mock = mocker.MagicMock() composer_mock = mocker.MagicMock() composer_mock.add_asset_transfer.return_value = composer_mock - composer_mock.send.return_value = SendAtomicTransactionComposerResults( + composer_mock.send.return_value = SendTransactionComposerResults( group_id="dummy_group_id", confirmations=[], tx_ids=["dummy_txid"], @@ -181,7 +185,7 @@ def test_transfer_asset_from_address_to_alias_successful(mocker: MockerFixture, algorand_mock = mocker.MagicMock() composer_mock = mocker.MagicMock() composer_mock.add_asset_transfer.return_value = composer_mock - composer_mock.send.return_value = SendAtomicTransactionComposerResults( + composer_mock.send.return_value = SendTransactionComposerResults( group_id="dummy_group_id", confirmations=[], tx_ids=["dummy_txid"], @@ -221,7 +225,7 @@ def test_transfer_asset_from_alias_successful(mocker: MockerFixture, mock_keyrin algorand_mock = mocker.MagicMock() composer_mock = mocker.MagicMock() composer_mock.add_asset_transfer.return_value = composer_mock - composer_mock.send.return_value = SendAtomicTransactionComposerResults( + composer_mock.send.return_value = SendTransactionComposerResults( group_id="dummy_group_id", confirmations=[], tx_ids=["dummy_txid"], @@ -294,7 +298,7 @@ def test_transfer_on_testnet(mocker: MockerFixture) -> None: algorand_mock = mocker.MagicMock() composer_mock = mocker.MagicMock() composer_mock.add_payment.return_value = composer_mock - composer_mock.send.return_value = SendAtomicTransactionComposerResults( + composer_mock.send.return_value = SendTransactionComposerResults( group_id="dummy_group_id", confirmations=[], tx_ids=["dummy_txid"], @@ -324,7 +328,7 @@ def test_transfer_on_mainnet(mocker: MockerFixture) -> None: algorand_mock = mocker.MagicMock() composer_mock = mocker.MagicMock() composer_mock.add_payment.return_value = composer_mock - composer_mock.send.return_value = SendAtomicTransactionComposerResults( + composer_mock.send.return_value = SendTransactionComposerResults( group_id="dummy_group_id", confirmations=[], tx_ids=["dummy_txid"], diff --git a/tests/tasks/test_wallet.py b/tests/tasks/test_wallet.py index 45248117b..448b7b101 100644 --- a/tests/tasks/test_wallet.py +++ b/tests/tasks/test_wallet.py @@ -1,7 +1,10 @@ +import base64 import json -import algosdk import pytest +from algokit_common import address_from_public_key +from algokit_utils.algo25 import secret_key_to_mnemonic +from nacl.signing import SigningKey from pytest_mock import MockerFixture from algokit.core.tasks.wallet import WALLET_ALIASES_KEYRING_USERNAME @@ -9,11 +12,25 @@ from tests.utils.click_invoker import invoke +def generate_test_account() -> tuple[str, str]: + """Generate a test account for testing purposes. + + Returns: + tuple[str, str]: A tuple of (private_key, address). + The private key is base64-encoded (64 bytes: 32 bytes secret + 32 bytes public key). + """ + signing_key = SigningKey.generate() + private_key_bytes = signing_key.encode() + signing_key.verify_key.encode() + private_key = base64.b64encode(private_key_bytes).decode() + address = address_from_public_key(signing_key.verify_key.encode()) + return private_key, address + + class TestAddAlias: def test_wallet_add_address_successful(self, mock_keyring: dict[str, str | None]) -> None: # Arrange alias_name = "test_alias" - address = algosdk.account.generate_account()[1] # type: ignore[no-untyped-call] + address = generate_test_account()[1] # Act result = invoke(f"task wallet add {alias_name} -a {address}") @@ -31,8 +48,8 @@ def test_wallet_add_address_successful(self, mock_keyring: dict[str, str | None] def test_wallet_add_account_successful(self, mock_keyring: dict[str, str | None]) -> None: # Arrange alias_name = "test_alias" - pk, address = algosdk.account.generate_account() # type: ignore[no-untyped-call] - mnemonic = algosdk.mnemonic.from_private_key(pk) # type: ignore[no-untyped-call] + pk, address = generate_test_account() + mnemonic = secret_key_to_mnemonic(base64.b64decode(pk)) # Act result = invoke(f"task wallet add {alias_name} -a {address} -m", input=f"{mnemonic}\n") @@ -60,9 +77,9 @@ def test_wallet_add_invalid_address(self, mock_keyring: dict[str, str | None]) - def test_wallet_add_alias_exists(self, mock_keyring: dict[str, str | None]) -> None: # Arrange bob_alias = "test_alias" - bob_address = algosdk.account.generate_account()[1] # type: ignore[no-untyped-call] + bob_address = generate_test_account()[1] mock_keyring[bob_alias] = json.dumps({"alias": bob_alias, "address": bob_address, "private_key": None}) - alice_address = algosdk.account.generate_account()[1] # type: ignore[no-untyped-call] + alice_address = generate_test_account()[1] # Act result = invoke(f"task wallet add {bob_alias} -a {alice_address}", input="y\n") @@ -80,9 +97,9 @@ def test_wallet_add_alias_exists(self, mock_keyring: dict[str, str | None]) -> N def test_wallet_add_alias_mnemonic_differs(self, mock_keyring: dict[str, str | None]) -> None: # Arrange alias_name = "test_alias" - address = algosdk.account.generate_account()[1] # type: ignore[no-untyped-call] - pk = algosdk.account.generate_account()[0] # type: ignore[no-untyped-call] - mnemonic = algosdk.mnemonic.from_private_key(pk) # type: ignore[no-untyped-call] + address = generate_test_account()[1] + pk = generate_test_account()[0] + mnemonic = secret_key_to_mnemonic(base64.b64decode(pk)) # Act result = invoke(f"task wallet add {alias_name} -a {address} -m", input=f"{mnemonic}\n") @@ -99,12 +116,12 @@ def test_wallet_add_alias_limit_error(self, mock_keyring: dict[str, str | None]) for i in range(50): alias_name = f"test_alias_{i}" dummy_aliases.append(alias_name) - address = algosdk.account.generate_account()[1] # type: ignore[no-untyped-call] + address = generate_test_account()[1] mock_keyring[alias_name] = json.dumps({"alias": alias_name, "address": address, "private_key": None}) mock_keyring[WALLET_ALIASES_KEYRING_USERNAME] = json.dumps(dummy_aliases) alias_name = "test_alias" - address = algosdk.account.generate_account()[1] # type: ignore[no-untyped-call] + address = generate_test_account()[1] # Act result = invoke(f"task wallet add {alias_name} -a {address}") @@ -118,7 +135,7 @@ def test_wallet_add_alias_limit_error(self, mock_keyring: dict[str, str | None]) def test_wallet_add_alias_generic_error(self, mocker: MockerFixture, mock_keyring: dict[str, str | None]) -> None: # Arrange alias_name = "test_alias" - address = algosdk.account.generate_account()[1] # type: ignore[no-untyped-call] + address = generate_test_account()[1] mocker.patch("algokit.cli.tasks.wallet.add_alias", side_effect=Exception("test error")) # Act @@ -135,7 +152,7 @@ class TestGetAlias: def test_wallet_get_address_alias_successful(self, mock_keyring: dict[str, str | None]) -> None: # Arrange alias_name = "test_alias" - address = algosdk.account.generate_account()[1] # type: ignore[no-untyped-call] + address = generate_test_account()[1] mock_keyring[alias_name] = json.dumps({"alias": alias_name, "address": address, "private_key": None}) # Act @@ -148,7 +165,7 @@ def test_wallet_get_address_alias_successful(self, mock_keyring: dict[str, str | def test_wallet_get_account_alias_successful(self, mock_keyring: dict[str, str | None]) -> None: # Arrange alias_name = "test_alias" - pk, address = algosdk.account.generate_account() # type: ignore[no-untyped-call] + pk, address = generate_test_account() mock_keyring[alias_name] = json.dumps({"alias": alias_name, "address": address, "private_key": pk}) # Act @@ -176,7 +193,6 @@ def test_wallet_get_alias_not_found( class TestListAliases: def test_wallet_list_aliases_successful(self, mock_keyring: dict[str, str | None]) -> None: # Arrange - algosdk.account.generate_account()[1] # type: ignore[no-untyped-call] mock_keyring["test_alias_1"] = json.dumps( {"alias": "test_alias_1", "address": "test_address_1", "private_key": None}, ) @@ -212,7 +228,7 @@ class TestRemoveAlias: def test_wallet_remove_alias_successful(self, mock_keyring: dict[str, str | None]) -> None: # Arrange alias_name = "test_alias" - address = algosdk.account.generate_account()[1] # type: ignore[no-untyped-call] + address = generate_test_account()[1] mock_keyring[alias_name] = json.dumps({"alias": alias_name, "address": address, "private_key": None}) mock_keyring[WALLET_ALIASES_KEYRING_USERNAME] = json.dumps([alias_name]) @@ -254,7 +270,6 @@ def test_wallet_remove_alias_generic_error(self, mocker: MockerFixture) -> None: class TestResetAliases: def test_wallet_reset_aliases_successful(self, mock_keyring: dict[str, str | None]) -> None: # Arrange - algosdk.account.generate_account()[1] # type: ignore[no-untyped-call] mock_keyring["test_alias_1"] = json.dumps( {"alias": "test_alias_1", "address": "test_address_1", "private_key": None}, ) From 7195f69af38453dafa72e317333cb29014626161 Mon Sep 17 00:00:00 2001 From: Altynbek Orumbayev Date: Tue, 16 Dec 2025 20:23:21 +0100 Subject: [PATCH 02/19] fix: add missing hidden imports for algokit_utils proxy modules Added PyInstaller hidden imports for: - algokit_abi, algokit_indexer_client, algokit_kmd_client (standalone packages) - algokit_utils.algo25, algokit_utils.transact, algokit_utils.common, algokit_utils.clients (proxy modules that re-export from standalone packages) This fixes 'No module named algokit_utils.algo25' error in portability tests. --- .gitignore | 4 ++ pyproject.toml | 2 +- scripts/package_mac.sh | 2 +- scripts/package_windows.bat | 2 +- tests/conftest.py | 24 ++++++++++ tests/project/deploy/test_deploy.py | 7 ++- tests/tasks/test_asset.py | 47 +++++++----------- tests/tasks/test_nfd_lookup.py | 4 +- tests/tasks/test_transfer.py | 74 ++++++++++++----------------- 9 files changed, 83 insertions(+), 83 deletions(-) diff --git a/.gitignore b/.gitignore index 744552e9e..962bf8de0 100644 --- a/.gitignore +++ b/.gitignore @@ -180,3 +180,7 @@ ci_token.txt .algokit/ temp/ + +*.md + +mise.toml diff --git a/pyproject.toml b/pyproject.toml index b09bb5c51..ef62b8dc4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ docs_generate = "sphinx-build -b markdown -E docs/sphinx docs/cli" docs_toc = "gfm-toc docs/cli/index.md -e 3" docs_title = {shell = "(echo \"# AlgoKit CLI Reference Documentation\\n\\n\"; cat docs/cli/index.md) > docs/cli/temp.md && mv docs/cli/temp.md docs/cli/index.md"} docs = ["docs_generate", "docs_toc", "docs_title"] -package_unix = "pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --hidden-import algokit_algod_client --hidden-import algokit_transact --hidden-import algokit_common --hidden-import algokit_algosdk --hidden-import algokit_algo25 --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data './misc/multiformats_config:multiformats_config/' --add-data './src/algokit/resources:algokit/resources/'" +package_unix = "pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --hidden-import algokit_utils.algo25 --hidden-import algokit_utils.transact --hidden-import algokit_utils.common --hidden-import algokit_utils.clients --hidden-import algokit_utils.transactions.builders --hidden-import algokit_utils.transactions.types --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data './misc/multiformats_config:multiformats_config/' --add-data './src/algokit/resources:algokit/resources/'" package_windows = { cmd = "scripts/package_windows.bat" } package_mac = { cmd = "scripts/package_mac.sh" } diff --git a/scripts/package_mac.sh b/scripts/package_mac.sh index 2537062b7..8e9bc151e 100755 --- a/scripts/package_mac.sh +++ b/scripts/package_mac.sh @@ -1,6 +1,6 @@ #!/bin/bash -CMD="pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --hidden-import algokit_algod_client --hidden-import algokit_transact --hidden-import algokit_common --hidden-import algokit_algosdk --hidden-import algokit_algo25 --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data './misc/multiformats_config/multibase-table.json:multiformats_config/' --add-data './misc/multiformats_config/multicodec-table.json:multiformats_config/' --add-data './src/algokit/resources:algokit/resources/'" +CMD="pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --hidden-import algokit_utils.algo25 --hidden-import algokit_utils.transact --hidden-import algokit_utils.common --hidden-import algokit_utils.clients --hidden-import algokit_utils.transactions.builders --hidden-import algokit_utils.transactions.types --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data './misc/multiformats_config/multibase-table.json:multiformats_config/' --add-data './misc/multiformats_config/multicodec-table.json:multiformats_config/' --add-data './src/algokit/resources:algokit/resources/'" if [ ! -z "$APPLE_BUNDLE_ID" ]; then CMD="$CMD --osx-bundle-identifier \"$APPLE_BUNDLE_ID\"" diff --git a/scripts/package_windows.bat b/scripts/package_windows.bat index c50e31343..f310901b7 100644 --- a/scripts/package_windows.bat +++ b/scripts/package_windows.bat @@ -1,2 +1,2 @@ @echo off -pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --hidden-import algokit_algod_client --hidden-import algokit_transact --hidden-import algokit_common --hidden-import algokit_algosdk --hidden-import algokit_algo25 --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data ./misc/multiformats_config;multiformats_config/ --add-data ./src/algokit/resources;algokit/resources/ +pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --hidden-import algokit_utils.algo25 --hidden-import algokit_utils.transact --hidden-import algokit_utils.common --hidden-import algokit_utils.clients --hidden-import algokit_utils.transactions.builders --hidden-import algokit_utils.transactions.types --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data ./misc/multiformats_config;multiformats_config/ --add-data ./src/algokit/resources;algokit/resources/ diff --git a/tests/conftest.py b/tests/conftest.py index 31939d2eb..8164af6af 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -241,3 +241,27 @@ def _always_check_image_versions(mocker: MockerFixture, request: pytest.FixtureR return mocker.patch("algokit.core.sandbox._should_check_image_versions", return_value=True) mocker.patch("algokit.core.sandbox._update_image_version_cache") + + +def generate_test_account() -> tuple[str, str, str]: + """Generate a random test account. + + Returns: + tuple of (private_key_b64, address, mnemonic) + """ + import base64 + + import nacl.signing + from algokit_utils.algo25 import secret_key_to_mnemonic + from algokit_utils.common import address_from_public_key + + signing_key = nacl.signing.SigningKey.generate() + public_key = signing_key.verify_key.encode() + address = address_from_public_key(public_key) + + # Private key is seed (32 bytes) + public key (32 bytes), base64 encoded + private_key_bytes = bytes(signing_key) + public_key + private_key_b64 = base64.b64encode(private_key_bytes).decode() + mnemonic = secret_key_to_mnemonic(private_key_bytes) + + return private_key_b64, address, mnemonic diff --git a/tests/project/deploy/test_deploy.py b/tests/project/deploy/test_deploy.py index 4e43427e2..47c905745 100644 --- a/tests/project/deploy/test_deploy.py +++ b/tests/project/deploy/test_deploy.py @@ -4,14 +4,13 @@ import pytest from _pytest.tmpdir import TempPathFactory -from algokit_algosdk.account import generate_account -from algokit_algosdk.mnemonic import from_private_key from approvaltests.namer import NamerFactory from pytest_mock import MockerFixture from algokit.cli.common.utils import sanitize_extra_args from algokit.core.conf import ALGOKIT_CONFIG from algokit.core.tasks.wallet import WALLET_ALIASES_KEYRING_USERNAME +from tests.conftest import generate_test_account from tests.utils.approvals import verify from tests.utils.click_invoker import invoke from tests.utils.proc_mock import ProcMock @@ -453,7 +452,7 @@ def test_deploy_dispenser_alias( ] """.strip() - dummy_account_pk, dummy_account_addr = generate_account() # type: ignore[no-untyped-call] + dummy_account_pk, dummy_account_addr, dummy_account_mnemonic = generate_test_account() mock_keyring[alias] = json.dumps({"alias": alias, "address": dummy_account_addr, "private_key": dummy_account_pk}) mock_keyring[WALLET_ALIASES_KEYRING_USERNAME] = json.dumps([alias]) @@ -466,7 +465,7 @@ def test_deploy_dispenser_alias( assert proc_mock.called[1].env passed_env_vars = proc_mock.called[1].env - assert passed_env_vars[env_var_name] == from_private_key(dummy_account_pk) # type: ignore[no-untyped-call] + assert passed_env_vars[env_var_name] == dummy_account_mnemonic verify(result.output, options=NamerFactory.with_parameters(alias)) diff --git a/tests/tasks/test_asset.py b/tests/tasks/test_asset.py index ab12eb727..96e471c51 100644 --- a/tests/tasks/test_asset.py +++ b/tests/tasks/test_asset.py @@ -1,27 +1,14 @@ -import base64 import json -from algokit_algosdk import account from algokit_utils import BulkAssetOptInOutResult -from algokit_utils.algo25 import secret_key_to_mnemonic from pytest_mock import MockerFixture from algokit.core.tasks.wallet import WALLET_ALIASES_KEYRING_USERNAME +from tests.conftest import generate_test_account from tests.utils.approvals import verify from tests.utils.click_invoker import invoke -def _generate_account() -> tuple[str, str]: - pk, addr = account.generate_account() # type: ignore[no-untyped-call] - return pk, addr - - -def _get_mnemonic_from_private_key(private_key: str) -> str: - # Convert base64-encoded private key to bytes for secret_key_to_mnemonic - private_key_bytes = base64.b64decode(private_key) - return secret_key_to_mnemonic(private_key_bytes) - - def test_opt_in_no_args() -> None: result = invoke("task opt-in") @@ -30,7 +17,7 @@ def test_opt_in_no_args() -> None: def test_opt_in_invalid_network() -> None: - _, addr = _generate_account() + _, addr, _ = generate_test_account() asset_id = 123 result = invoke(f"task opt-in {addr} {asset_id} --network invalid-network") @@ -46,11 +33,11 @@ def test_opt_in_to_assets_from_account_address_successful(mocker: MockerFixture) algorand_mock = mocker.patch("algokit.cli.tasks.assets.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.assets.validate_address") mocker.patch("algokit.cli.tasks.assets.validate_account_balance_to_opt_in") - dummy_account_pk, dummy_account_address = _generate_account() + dummy_account_pk, dummy_account_address, dummy_account_mnemonic = generate_test_account() asset_id = 123 result = invoke( f"task opt-in -a {dummy_account_address} {asset_id} --network localnet", - input=_get_mnemonic_from_private_key(dummy_account_pk), + input=dummy_account_mnemonic, ) assert result.exit_code == 0 @@ -65,7 +52,7 @@ def test_opt_in_of_assets_from_account_alias_successful(mocker: MockerFixture, m algorand_mock = mocker.patch("algokit.cli.tasks.assets.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.assets.validate_address") mocker.patch("algokit.cli.tasks.assets.validate_account_balance_to_opt_in") - dummy_account_pk, dummy_account_address = _generate_account() + dummy_account_pk, dummy_account_address, dummy_account_mnemonic = generate_test_account() alias_name = "dummy_alias" mock_keyring[alias_name] = json.dumps( @@ -79,7 +66,7 @@ def test_opt_in_of_assets_from_account_alias_successful(mocker: MockerFixture, m result = invoke( f"task opt-in -a {alias_name} {123} --network localnet", - input=_get_mnemonic_from_private_key(dummy_account_pk), + input=dummy_account_mnemonic, ) assert result.exit_code == 0 @@ -92,11 +79,11 @@ def test_opt_in_to_assets_from_account_address_failed(mocker: MockerFixture) -> algorand_mock = mocker.patch("algokit.cli.tasks.assets.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.assets.validate_address") mocker.patch("algokit.cli.tasks.assets.validate_account_balance_to_opt_in") - dummy_account_pk, dummy_account_address = _generate_account() + dummy_account_pk, dummy_account_address, dummy_account_mnemonic = generate_test_account() asset_id = 123 result = invoke( f"task opt-in -a {dummy_account_address} {asset_id} --network localnet", - input=_get_mnemonic_from_private_key(dummy_account_pk), + input=dummy_account_mnemonic, ) assert result.exit_code == 1 @@ -111,7 +98,7 @@ def test_opt_out_no_args() -> None: def test_opt_out_invalid_network() -> None: - _, addr = _generate_account() + _, addr, _ = generate_test_account() asset_id = 123 result = invoke(f"task opt-out {asset_id} {addr} --network invalid-network") @@ -126,11 +113,11 @@ def test_opt_out_of_assets_from_account_address_successful(mocker: MockerFixture ] algorand_mock = mocker.patch("algokit.cli.tasks.assets.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.assets.validate_address") - dummy_account_pk, dummy_account_address = _generate_account() + dummy_account_pk, dummy_account_address, dummy_account_mnemonic = generate_test_account() asset_id = 123 result = invoke( f"task opt-out -a {dummy_account_address} {asset_id} --network localnet", - input=_get_mnemonic_from_private_key(dummy_account_pk), + input=dummy_account_mnemonic, ) assert result.exit_code == 0 @@ -146,10 +133,10 @@ def test_opt_out_of_all_assets_from_account_address_successful(mocker: MockerFix ] algorand_mock = mocker.patch("algokit.cli.tasks.assets.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.assets.validate_address") - dummy_account_pk, dummy_account_address = _generate_account() + dummy_account_pk, dummy_account_address, dummy_account_mnemonic = generate_test_account() result = invoke( f"task opt-out -a {dummy_account_address} --network localnet --all", - input=_get_mnemonic_from_private_key(dummy_account_pk), + input=dummy_account_mnemonic, ) assert result.exit_code == 0 @@ -163,7 +150,7 @@ def test_opt_out_of_assets_from_account_alias_successful(mocker: MockerFixture, ] algorand_mock = mocker.patch("algokit.cli.tasks.assets.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.assets.validate_address") - dummy_account_pk, dummy_account_address = _generate_account() + dummy_account_pk, dummy_account_address, dummy_account_mnemonic = generate_test_account() alias_name = "dummy_alias" mock_keyring[alias_name] = json.dumps( @@ -177,7 +164,7 @@ def test_opt_out_of_assets_from_account_alias_successful(mocker: MockerFixture, result = invoke( f"task opt-out -a {alias_name} 123 --network localnet", - input=_get_mnemonic_from_private_key(dummy_account_pk), + input=dummy_account_mnemonic, ) assert result.exit_code == 0 @@ -189,11 +176,11 @@ def test_opt_out_assets_from_account_address_failed(mocker: MockerFixture) -> No algorand_mock.asset.bulk_opt_out.side_effect = Exception("dummy error") algorand_mock = mocker.patch("algokit.cli.tasks.assets.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.assets.validate_address") - dummy_account_pk, dummy_account_address = _generate_account() + dummy_account_pk, dummy_account_address, dummy_account_mnemonic = generate_test_account() asset_id = 123 result = invoke( f"task opt-out -a {dummy_account_address} {asset_id} --network localnet", - input=_get_mnemonic_from_private_key(dummy_account_pk), + input=dummy_account_mnemonic, ) assert result.exit_code == 1 diff --git a/tests/tasks/test_nfd_lookup.py b/tests/tasks/test_nfd_lookup.py index 5ceda0197..9e37ad5b1 100644 --- a/tests/tasks/test_nfd_lookup.py +++ b/tests/tasks/test_nfd_lookup.py @@ -1,6 +1,6 @@ -import algokit_algosdk.account from pytest_httpx import HTTPXMock +from tests.conftest import generate_test_account from tests.utils.approvals import verify from tests.utils.click_invoker import invoke @@ -27,7 +27,7 @@ def test_nfd_lookup_by_domain_success(httpx_mock: HTTPXMock) -> None: def test_nfd_lookup_by_address_success(httpx_mock: HTTPXMock) -> None: # Arrange - _, dummy_wallet = algokit_algosdk.account.generate_account() # type: ignore[no-untyped-call] + _, dummy_wallet, _ = generate_test_account() httpx_mock.add_response( url=f"https://api.nf.domains/nfd/lookup?address={dummy_wallet}&view=thumbnail&allowUnverified=false", json={ diff --git a/tests/tasks/test_transfer.py b/tests/tasks/test_transfer.py index 12a61b123..9eea83105 100644 --- a/tests/tasks/test_transfer.py +++ b/tests/tasks/test_transfer.py @@ -1,13 +1,11 @@ -import base64 import json import pytest -from algokit_algosdk import account from algokit_utils import SendTransactionComposerResults -from algokit_utils.algo25 import secret_key_to_mnemonic from pytest_mock import MockerFixture from algokit.core.tasks.wallet import WALLET_ALIASES_KEYRING_USERNAME +from tests.conftest import generate_test_account from tests.utils.approvals import verify from tests.utils.click_invoker import invoke @@ -17,17 +15,6 @@ def get_txid(self) -> str: return "dummy_txid" -def _generate_account() -> tuple[str, str]: - pk, addr = account.generate_account() # type: ignore[no-untyped-call] - return pk, addr - - -def _get_mnemonic_from_private_key(private_key: str) -> str: - # Convert base64-encoded private key to bytes for secret_key_to_mnemonic - private_key_bytes = base64.b64decode(private_key) - return secret_key_to_mnemonic(private_key_bytes) - - def test_transfer_no_args() -> None: result = invoke("task transfer") @@ -38,7 +25,7 @@ def test_transfer_no_args() -> None: @pytest.mark.usefixtures("mock_keyring") def test_transfer_invalid_sender_account() -> None: # Arrange - dummy_receiver = _generate_account()[1] + _, dummy_receiver, _ = generate_test_account() # Act result = invoke(f"task transfer -s invalid-address -r {dummy_receiver} -a 1") @@ -51,12 +38,12 @@ def test_transfer_invalid_sender_account() -> None: @pytest.mark.usefixtures("mock_keyring") def test_transfer_invalid_receiver_account() -> None: # Arrange - dummy_sender_pk, dummy_sender_address = _generate_account() + dummy_sender_pk, dummy_sender_address, dummy_sender_mnemonic = generate_test_account() # Act result = invoke( f"task transfer -s {dummy_sender_address} -r invalid-address -a 1", - input=_get_mnemonic_from_private_key(dummy_sender_pk), + input=dummy_sender_mnemonic, ) # Assert @@ -66,13 +53,13 @@ def test_transfer_invalid_receiver_account() -> None: def test_transfer_no_amount() -> None: # Arrange - dummy_sender_pk, dummy_sender_address = _generate_account() - dummy_receiver_address = _generate_account()[1] + dummy_sender_pk, dummy_sender_address, dummy_sender_mnemonic = generate_test_account() + _, dummy_receiver_address, _ = generate_test_account() # Act result = invoke( f"task transfer -s {dummy_sender_address} -r {dummy_receiver_address}", - input=_get_mnemonic_from_private_key(dummy_sender_pk), + input=dummy_sender_mnemonic, ) # Assert @@ -96,13 +83,13 @@ def test_transfer_algo_from_address_successful(mocker: MockerFixture) -> None: mocker.patch("algokit.cli.tasks.transfer.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.transfer.validate_address") mocker.patch("algokit.cli.tasks.transfer.validate_balance") - dummy_sender_pk, dummy_sender_address = _generate_account() - dummy_receiver_address = _generate_account()[1] + dummy_sender_pk, dummy_sender_address, dummy_sender_mnemonic = generate_test_account() + _, dummy_receiver_address, _ = generate_test_account() # Act result = invoke( f"task transfer -s {dummy_sender_address} -r {dummy_receiver_address} -a 1", - input=_get_mnemonic_from_private_key(dummy_sender_pk), + input=dummy_sender_mnemonic, ) # Assert @@ -126,8 +113,8 @@ def test_transfer_algo_from_alias_successful(mocker: MockerFixture, mock_keyring mocker.patch("algokit.cli.tasks.transfer.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.transfer.validate_address") mocker.patch("algokit.cli.tasks.transfer.validate_balance") - dummy_sender_pk, dummy_sender_address = _generate_account() - dummy_receiver_address = _generate_account()[1] + dummy_sender_pk, dummy_sender_address, dummy_sender_mnemonic = generate_test_account() + _, dummy_receiver_address, _ = generate_test_account() alias_name = "dummy_alias" mock_keyring[alias_name] = json.dumps( @@ -142,7 +129,7 @@ def test_transfer_algo_from_alias_successful(mocker: MockerFixture, mock_keyring # Act result = invoke( f"task transfer -s {alias_name} -r {dummy_receiver_address} -a 1", - input=_get_mnemonic_from_private_key(dummy_sender_pk), + input=dummy_sender_mnemonic, ) # Assert @@ -166,13 +153,13 @@ def test_transfer_asset_from_address_successful(mocker: MockerFixture) -> None: mocker.patch("algokit.cli.tasks.transfer.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.transfer.validate_address") mocker.patch("algokit.cli.tasks.transfer.validate_balance") - dummy_sender_pk, dummy_sender_address = _generate_account() - dummy_receiver_address = _generate_account()[1] + dummy_sender_pk, dummy_sender_address, dummy_sender_mnemonic = generate_test_account() + _, dummy_receiver_address, _ = generate_test_account() # Act result = invoke( f"task transfer -s {dummy_sender_address} -r {dummy_receiver_address} -a 1 --id 1234", - input=_get_mnemonic_from_private_key(dummy_sender_pk), + input=dummy_sender_mnemonic, ) # Assert @@ -196,8 +183,7 @@ def test_transfer_asset_from_address_to_alias_successful(mocker: MockerFixture, mocker.patch("algokit.cli.tasks.transfer.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.transfer.validate_address") mocker.patch("algokit.cli.tasks.transfer.validate_balance") - dummy_sender_pk, dummy_sender_address = _generate_account() - _generate_account()[1] + dummy_sender_pk, dummy_sender_address, dummy_sender_mnemonic = generate_test_account() dummy_receiver_alias = "dummy_receiver_alias" mock_keyring[dummy_receiver_alias] = json.dumps( @@ -212,7 +198,7 @@ def test_transfer_asset_from_address_to_alias_successful(mocker: MockerFixture, # Act result = invoke( f"task transfer -s {dummy_sender_address} -r {dummy_receiver_alias} -a 1 --id 1234", - input=_get_mnemonic_from_private_key(dummy_sender_pk), + input=dummy_sender_mnemonic, ) # Assert @@ -236,8 +222,8 @@ def test_transfer_asset_from_alias_successful(mocker: MockerFixture, mock_keyrin mocker.patch("algokit.cli.tasks.transfer.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.transfer.validate_address") mocker.patch("algokit.cli.tasks.transfer.validate_balance") - dummy_sender_pk, dummy_sender_address = _generate_account() - dummy_receiver_address = _generate_account()[1] + dummy_sender_pk, dummy_sender_address, dummy_sender_mnemonic = generate_test_account() + _, dummy_receiver_address, _ = generate_test_account() alias_name = "dummy_alias" mock_keyring[alias_name] = json.dumps( @@ -252,7 +238,7 @@ def test_transfer_asset_from_alias_successful(mocker: MockerFixture, mock_keyrin # Act result = invoke( f"task transfer -s {alias_name} -r {dummy_receiver_address} -a 1 --id 1234", - input=_get_mnemonic_from_private_key(dummy_sender_pk), + input=dummy_sender_mnemonic, ) # Assert @@ -269,8 +255,8 @@ def test_transfer_failed(mocker: MockerFixture, mock_keyring: dict[str, str]) -> mocker.patch("algokit.cli.tasks.transfer.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.transfer.validate_address") mocker.patch("algokit.cli.tasks.transfer.validate_balance") - dummy_sender_pk, dummy_sender_address = _generate_account() - dummy_receiver_address = _generate_account()[1] + dummy_sender_pk, dummy_sender_address, dummy_sender_mnemonic = generate_test_account() + _, dummy_receiver_address, _ = generate_test_account() alias_name = "dummy_alias" mock_keyring[alias_name] = json.dumps( @@ -285,7 +271,7 @@ def test_transfer_failed(mocker: MockerFixture, mock_keyring: dict[str, str]) -> # Act result = invoke( f"task transfer -s {alias_name} -r {dummy_receiver_address} -a 1", - input=_get_mnemonic_from_private_key(dummy_sender_pk), + input=dummy_sender_mnemonic, ) # Assert @@ -309,13 +295,13 @@ def test_transfer_on_testnet(mocker: MockerFixture) -> None: mocker.patch("algokit.cli.tasks.transfer.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.transfer.validate_address") mocker.patch("algokit.cli.tasks.transfer.validate_balance") - dummy_sender_pk, dummy_sender_address = _generate_account() - dummy_receiver_address = _generate_account()[1] + dummy_sender_pk, dummy_sender_address, dummy_sender_mnemonic = generate_test_account() + _, dummy_receiver_address, _ = generate_test_account() # Act result = invoke( f"task transfer -s {dummy_sender_address} -r {dummy_receiver_address} -a 1 -n testnet", - input=_get_mnemonic_from_private_key(dummy_sender_pk), + input=dummy_sender_mnemonic, ) # Assert @@ -339,13 +325,13 @@ def test_transfer_on_mainnet(mocker: MockerFixture) -> None: mocker.patch("algokit.cli.tasks.transfer.get_algorand_client_for_network", return_value=algorand_mock) mocker.patch("algokit.cli.tasks.transfer.validate_address") mocker.patch("algokit.cli.tasks.transfer.validate_balance") - dummy_sender_pk, dummy_sender_address = _generate_account() - dummy_receiver_address = _generate_account()[1] + dummy_sender_pk, dummy_sender_address, dummy_sender_mnemonic = generate_test_account() + _, dummy_receiver_address, _ = generate_test_account() # Act result = invoke( f"task transfer -s {dummy_sender_address} -r {dummy_receiver_address} -a 1 -n mainnet", - input=_get_mnemonic_from_private_key(dummy_sender_pk), + input=dummy_sender_mnemonic, ) # Assert From 20bfb8a6dab8ea2839c7d89a7022463fd4a94863 Mon Sep 17 00:00:00 2001 From: Altynbek Orumbayev Date: Tue, 16 Dec 2025 21:38:49 +0100 Subject: [PATCH 03/19] fix: ensure pyinstaller tests use dist binary instead of venv algokit The portability tests were inadvertently using the venv-installed algokit instead of the PyInstaller binary because 'poetry run' prepends .venv/bin to PATH, causing 'algokit' to resolve to the venv version. - Add _get_algokit_binary() to explicitly find the PyInstaller binary in dist/ - Support PYINSTALLER_BINARY_PATH env var for explicit binary path - Filter out .venv/bin (or .venv/Scripts on Windows) from PATH fallback - Add Windows compatibility with os.pathsep and .exe extension - Remove unused command_str_to_list function --- tests/portability/test_pyinstaller_binary.py | 83 +++++++++++++++----- 1 file changed, 63 insertions(+), 20 deletions(-) diff --git a/tests/portability/test_pyinstaller_binary.py b/tests/portability/test_pyinstaller_binary.py index 459f86f6a..9474c37e1 100644 --- a/tests/portability/test_pyinstaller_binary.py +++ b/tests/portability/test_pyinstaller_binary.py @@ -1,4 +1,6 @@ import logging +import os +import shutil import subprocess import sys import time @@ -7,38 +9,72 @@ import pytest -algokit = "algokit" logger = logging.getLogger(__name__) pytestmark = pytest.mark.pyinstaller_binary_tests -def command_str_to_list(command: str) -> list[str]: - return command.split(" ") +def _get_algokit_binary() -> str: + """Get the path to the algokit binary, preferring the PyInstaller binary over venv-installed version. + + When running via 'poetry run', the .venv/bin directory is prepended to PATH, which causes + the venv-installed algokit to be found before the PyInstaller binary. This function + explicitly looks for the binary in the dist directory first. + """ + # Check for explicit binary path from environment variable + if binary_path := environ.get("PYINSTALLER_BINARY_PATH"): + return binary_path + + # Look for the binary in the dist directory (relative to the repo root) + # This works both locally and in CI + repo_root = Path(__file__).parent.parent.parent + is_windows = sys.platform in ("win32", "cygwin") + binary_name = "algokit.exe" if is_windows else "algokit" + dist_binary = repo_root / "dist" / "algokit" / binary_name + if dist_binary.exists(): + return str(dist_binary) + + # Fall back to PATH resolution, but skip the venv bin directory + # to avoid finding the venv-installed version + venv_subdir = "Scripts" if is_windows else "bin" + venv_bin = repo_root / ".venv" / venv_subdir + original_path = environ.get("PATH", "") + filtered_path = os.pathsep.join(p for p in original_path.split(os.pathsep) if not p.startswith(str(venv_bin))) + + # Use shutil.which with the filtered PATH + if binary := shutil.which("algokit", path=filtered_path): + return binary + + # Last resort: just use 'algokit' and hope it's in PATH + return "algokit" + + +algokit = _get_algokit_binary() @pytest.mark.parametrize( - ("command", "exit_codes"), + ("args", "exit_codes"), [ - (command_str_to_list("algokit --help"), [0]), - (command_str_to_list("algokit doctor"), [0]), - (command_str_to_list("algokit task vanity-address PY"), [0]), + (["--help"], [0]), + (["doctor"], [0]), + (["task", "vanity-address", "PY"], [0]), ], ) def test_non_interactive_algokit_commands( - command: list[str], exit_codes: list[int], tmp_path_factory: pytest.TempPathFactory + args: list[str], exit_codes: list[int], tmp_path_factory: pytest.TempPathFactory ) -> None: cwd = tmp_path_factory.mktemp("cwd") # Create a 'playground' directory - if "build" in command: + if "build" in args: cwd = cwd / "playground" cwd.mkdir(exist_ok=True) + command = [algokit, *args] execution_result = subprocess.run(command, capture_output=True, text=True, check=False, cwd=cwd) logger.info(f"Command {command} returned {execution_result.stdout}") # Parts of doctor will fail in CI on macOS and windows on github actions since docker isn't available by default - if "doctor" in command and sys.platform in ["darwin", "windows", "win32"] and environ.get("CI"): + if "doctor" in args and sys.platform in ["darwin", "windows", "win32"] and environ.get("CI"): exit_codes.append(1) assert execution_result.returncode in exit_codes, f"Command {command} failed with {execution_result.stderr}" @@ -48,7 +84,7 @@ def test_algokit_init_and_project_run(tmp_path_factory: pytest.TempPathFactory) cwd = tmp_path_factory.mktemp("cwd") # Run algokit init - init_command = command_str_to_list("algokit init --name playground -t python --no-git --no-ide --defaults") + init_command = [algokit, "init", "--name", "playground", "-t", "python", "--no-git", "--no-ide", "--defaults"] init_result = subprocess.run(init_command, capture_output=True, text=True, check=False, cwd=cwd) logger.info(f"Command {init_command} returned {init_result.stdout}") assert init_result.returncode == 0, f"Init command failed with {init_result.stderr}" @@ -56,7 +92,7 @@ def test_algokit_init_and_project_run(tmp_path_factory: pytest.TempPathFactory) # Run algokit project run build build_cwd = cwd / "playground" build_cwd.mkdir(exist_ok=True) - build_command = command_str_to_list("algokit -v project run build -- hello_world") + build_command = [algokit, "-v", "project", "run", "build", "--", "hello_world"] build_result = subprocess.run(build_command, capture_output=True, text=True, check=False, cwd=build_cwd) logger.info(f"Command {build_command} returned {build_result.stdout}") assert build_result.returncode == 0, f"Build command failed with {build_result.stderr}" @@ -70,15 +106,22 @@ def test_algokit_init_with_template_url( # template. To cover and test workspace creation on real templates, we need to find a way to have `algokit` # available globally within the worker running the binary IF the template defined custom copier tasks that invoke # global `algokit` executable as part of instantiation of child template (for example fullstack). - command = command_str_to_list( - "init --name testproject " - "--UNSAFE-SECURITY-accept-template-url " - f"--template-url {dummy_algokit_template_with_python_task['template_path']} " - "--template-url-ref=HEAD --no-git --no-ide --defaults --no-workspace" - ) + args = [ + "init", + "--name", + "testproject", + "--UNSAFE-SECURITY-accept-template-url", + "--template-url", + str(dummy_algokit_template_with_python_task["template_path"]), + "--template-url-ref=HEAD", + "--no-git", + "--no-ide", + "--defaults", + "--no-workspace", + ] process = subprocess.Popen( - [algokit, *command], + [algokit, *args], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -87,7 +130,7 @@ def test_algokit_init_with_template_url( ) full_output = "" - logger.info(f"Running command: {' '.join([algokit, *command])}") + logger.info(f"Running command: {' '.join([algokit, *args])}") while process.poll() is None and process.stdout and process.stdin: output = process.stdout.readline() full_output += output # Accumulate the output From b174ca8e43f0ec7bb07ad982465964ca4d09efe8 Mon Sep 17 00:00:00 2001 From: Altynbek Orumbayev Date: Wed, 17 Dec 2025 18:05:12 +0100 Subject: [PATCH 04/19] chore: update to latest alpha 4 with get prefixes stripped from clients --- poetry.lock | 6 +++--- pyproject.toml | 2 +- src/algokit/cli/tasks/utils.py | 2 +- src/algokit/core/tasks/mint/mint.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index bf61e2e7c..a0b1c34a8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,14 +14,14 @@ files = [ [[package]] name = "algokit-utils" -version = "5.0.0a2" +version = "5.0.0a4" description = "Utilities for Algorand development for use by AlgoKit" optional = false python-versions = "<4,>=3.10" groups = ["main"] files = [ - {file = "algokit_utils-5.0.0a2-py3-none-any.whl", hash = "sha256:771f4256d26828c27ebce8f00eea18e953d3ef1ffe9c2d3e229f48079c12b129"}, - {file = "algokit_utils-5.0.0a2.tar.gz", hash = "sha256:25f232f655d9d9467976845aa8adb6d0ff62e149f4cd0d92e3e6401a1a138c75"}, + {file = "algokit_utils-5.0.0a4-py3-none-any.whl", hash = "sha256:4898e757a61f2d0b91068f453816e5e119519c13415af5ad1a0faec340c0084d"}, + {file = "algokit_utils-5.0.0a4.tar.gz", hash = "sha256:92f0aeb9d8627dde7ca6e1257817ffd311bfb1c10e169a54865b8f0d7c9eeee0"}, ] [package.dependencies] diff --git a/pyproject.toml b/pyproject.toml index ef62b8dc4..d333e5ed2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ keyring = "25.6.0" # this version has been tested to work with the vendored file pyjwt = "^2.10.1" cryptography = "^44.0.2" # pyjwt has a weak dependency on cryptography and explicitly requires it in the vendored file, hence the lock -algokit-utils = "^5.0.0a2" +algokit-utils = "^5.0.0a4" multiformats = "0.3.1" multiformats_config = "0.3.1" # pinned this to be in lockstep with multiformats jsondiff = "^2.0.0" diff --git a/src/algokit/cli/tasks/utils.py b/src/algokit/cli/tasks/utils.py index 1664d541b..cd330c4a6 100644 --- a/src/algokit/cli/tasks/utils.py +++ b/src/algokit/cli/tasks/utils.py @@ -143,7 +143,7 @@ def get_asset_decimals(asset_id: int, algod_client: AlgodClient) -> int: if asset_id == 0: return 6 - asset_response = algod_client.get_asset_by_id(asset_id) + asset_response = algod_client.asset_by_id(asset_id) decimals = getattr(getattr(asset_response, "params", None), "decimals", None) if decimals is None: diff --git a/src/algokit/core/tasks/mint/mint.py b/src/algokit/core/tasks/mint/mint.py index ee44ffc18..8a493126c 100644 --- a/src/algokit/core/tasks/mint/mint.py +++ b/src/algokit/core/tasks/mint/mint.py @@ -167,7 +167,7 @@ def _wait_for_confirmation(client: AlgodClient, txid: str, rounds: int) -> algod Raises: Exception: If transaction is rejected or not confirmed in time """ - status = client.get_status() + status = client.status() last_round = getattr(status, "last_round", 0) current_round = last_round From 8b2b32787be7a3596e7c4c8f4e90318927d2bf83 Mon Sep 17 00:00:00 2001 From: Daniel McGregor Date: Wed, 24 Dec 2025 10:05:22 +0800 Subject: [PATCH 05/19] build: bump algokit-utils to 5.0.0a7 --- poetry.lock | 6 +++--- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index a0b1c34a8..211a6acdf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,14 +14,14 @@ files = [ [[package]] name = "algokit-utils" -version = "5.0.0a4" +version = "5.0.0a7" description = "Utilities for Algorand development for use by AlgoKit" optional = false python-versions = "<4,>=3.10" groups = ["main"] files = [ - {file = "algokit_utils-5.0.0a4-py3-none-any.whl", hash = "sha256:4898e757a61f2d0b91068f453816e5e119519c13415af5ad1a0faec340c0084d"}, - {file = "algokit_utils-5.0.0a4.tar.gz", hash = "sha256:92f0aeb9d8627dde7ca6e1257817ffd311bfb1c10e169a54865b8f0d7c9eeee0"}, + {file = "algokit_utils-5.0.0a7-py3-none-any.whl", hash = "sha256:e409dd838e6d29aca978fe91ced43e7f94d2120ab7025eb7ccf548d2849589e1"}, + {file = "algokit_utils-5.0.0a7.tar.gz", hash = "sha256:97212bfdf2854de7e41f8e9ec2da7194a352c90c527e1ca4a11493721b60d8aa"}, ] [package.dependencies] diff --git a/pyproject.toml b/pyproject.toml index d333e5ed2..7bff7a41f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ keyring = "25.6.0" # this version has been tested to work with the vendored file pyjwt = "^2.10.1" cryptography = "^44.0.2" # pyjwt has a weak dependency on cryptography and explicitly requires it in the vendored file, hence the lock -algokit-utils = "^5.0.0a4" +algokit-utils = "^5.0.0a7" multiformats = "0.3.1" multiformats_config = "0.3.1" # pinned this to be in lockstep with multiformats jsondiff = "^2.0.0" From e5541776bf4029b931ec7286aa6c98605c8d1a5f Mon Sep 17 00:00:00 2001 From: Daniel McGregor Date: Wed, 24 Dec 2025 11:15:00 +0800 Subject: [PATCH 06/19] test: included metadata_hash in logger output so it can be part of approvals --- src/algokit/core/tasks/mint/mint.py | 3 +++ ...t_mint_token_successful.address.False.localnet.approved.txt | 1 + ...st_mint_token_successful.address.False.mainnet.approved.txt | 1 + ...st_mint_token_successful.address.False.testnet.approved.txt | 1 + ...test_mint_token_successful.alias.True.localnet.approved.txt | 1 + ....test_mint_token_successful.alias.True.mainnet.approved.txt | 1 + ....test_mint_token_successful.alias.True.testnet.approved.txt | 1 + ...n_successful_on_decimals.decimals_given_params.approved.txt | 1 + ...token_successful_on_decimals.no_decimals_given.approved.txt | 1 + 9 files changed, 11 insertions(+) diff --git a/src/algokit/core/tasks/mint/mint.py b/src/algokit/core/tasks/mint/mint.py index 8a493126c..89591eae4 100644 --- a/src/algokit/core/tasks/mint/mint.py +++ b/src/algokit/core/tasks/mint/mint.py @@ -304,6 +304,9 @@ def mint_token( # noqa: PLR0913 "total": asset_create_params.total, "freeze": asset_create_params.freeze or "", "clawback": asset_create_params.clawback or "", + "metadata_hash": base64.b64encode(asset_create_params.metadata_hash).decode("ascii") + if asset_create_params.metadata_hash + else None, "note": "", "decimals": asset_create_params.decimals, "default_frozen": asset_create_params.default_frozen or False, diff --git a/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt index 1836425c1..11140d24c 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.address.False.localnet.approved.txt @@ -13,6 +13,7 @@ DEBUG: Asset config params: { "total": 1, "freeze": "", "clawback": "", + "metadata_hash": "VR1UyM4COBDD1TEmAj0U8FwpZ0b6J+V1Mi6YqzDSWvg=", "note": "", "decimals": 0, "default_frozen": false, diff --git a/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt index 4a33c23af..7519547d8 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.address.False.mainnet.approved.txt @@ -13,6 +13,7 @@ DEBUG: Asset config params: { "total": 1, "freeze": "", "clawback": "", + "metadata_hash": "VR1UyM4COBDD1TEmAj0U8FwpZ0b6J+V1Mi6YqzDSWvg=", "note": "", "decimals": 0, "default_frozen": false, diff --git a/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt index 15e6d473c..abbd35cfa 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.address.False.testnet.approved.txt @@ -13,6 +13,7 @@ DEBUG: Asset config params: { "total": 1, "freeze": "", "clawback": "", + "metadata_hash": "VR1UyM4COBDD1TEmAj0U8FwpZ0b6J+V1Mi6YqzDSWvg=", "note": "", "decimals": 0, "default_frozen": false, diff --git a/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt index b3afaa8ad..fed895e9b 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.alias.True.localnet.approved.txt @@ -12,6 +12,7 @@ DEBUG: Asset config params: { "total": 1, "freeze": "", "clawback": "", + "metadata_hash": null, "note": "", "decimals": 0, "default_frozen": false, diff --git a/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt index e83d096e7..84a6f5d74 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.alias.True.mainnet.approved.txt @@ -12,6 +12,7 @@ DEBUG: Asset config params: { "total": 1, "freeze": "", "clawback": "", + "metadata_hash": null, "note": "", "decimals": 0, "default_frozen": false, diff --git a/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt b/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt index dced73bf1..89f149b6d 100644 --- a/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful.alias.True.testnet.approved.txt @@ -12,6 +12,7 @@ DEBUG: Asset config params: { "total": 1, "freeze": "", "clawback": "", + "metadata_hash": null, "note": "", "decimals": 0, "default_frozen": false, diff --git a/tests/tasks/test_mint.test_mint_token_successful_on_decimals.decimals_given_params.approved.txt b/tests/tasks/test_mint.test_mint_token_successful_on_decimals.decimals_given_params.approved.txt index bb1ebd954..55a770937 100644 --- a/tests/tasks/test_mint.test_mint_token_successful_on_decimals.decimals_given_params.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful_on_decimals.decimals_given_params.approved.txt @@ -12,6 +12,7 @@ DEBUG: Asset config params: { "total": 100, "freeze": "", "clawback": "", + "metadata_hash": null, "note": "", "decimals": 2, "default_frozen": false, diff --git a/tests/tasks/test_mint.test_mint_token_successful_on_decimals.no_decimals_given.approved.txt b/tests/tasks/test_mint.test_mint_token_successful_on_decimals.no_decimals_given.approved.txt index 94a9b43df..10dafd259 100644 --- a/tests/tasks/test_mint.test_mint_token_successful_on_decimals.no_decimals_given.approved.txt +++ b/tests/tasks/test_mint.test_mint_token_successful_on_decimals.no_decimals_given.approved.txt @@ -13,6 +13,7 @@ DEBUG: Asset config params: { "total": 100, "freeze": "", "clawback": "", + "metadata_hash": null, "note": "", "decimals": 2, "default_frozen": false, From 2aed153001aefca4aaa06cd8d56847dc33fe7e0f Mon Sep 17 00:00:00 2001 From: Daniel McGregor Date: Wed, 24 Dec 2025 11:15:22 +0800 Subject: [PATCH 07/19] refactor: simplify mint implementation --- src/algokit/core/tasks/mint/mint.py | 80 +++-------------------------- 1 file changed, 6 insertions(+), 74 deletions(-) diff --git a/src/algokit/core/tasks/mint/mint.py b/src/algokit/core/tasks/mint/mint.py index 89591eae4..c17ab8947 100644 --- a/src/algokit/core/tasks/mint/mint.py +++ b/src/algokit/core/tasks/mint/mint.py @@ -6,6 +6,7 @@ import pathlib import re +from algokit_common import address_from_public_key, sha512_256 from algokit_utils.clients import AlgodClient, algod_models from algokit_utils.transact import get_transaction_id, make_basic_account_transaction_signer from algokit_utils.transactions.builders.asset import build_asset_create_transaction @@ -18,64 +19,6 @@ logger = logging.getLogger(__name__) -# Constants for Algorand address validation -ALGORAND_ADDRESS_LENGTH = 58 -ALGORAND_ADDRESS_DECODED_LENGTH = 36 # 32 bytes address + 4 bytes checksum - - -def _encode_address_from_bytes(digest: bytes) -> str: - """ - Encode an address from a 32-byte digest using Algorand address encoding. - - Args: - digest: 32-byte hash digest - - Returns: - str: Base32-encoded address with checksum - """ - # Standard Algorand checksum uses sha512_256, taking last 4 bytes - h = hashlib.new("sha512_256") - h.update(digest) - checksum = h.digest()[-4:] - address_bytes = digest + checksum - # Base32 encode without padding - encoded = base64.b32encode(address_bytes).decode("utf-8") - # Remove padding - return encoded.rstrip("=") - - -def _is_valid_address(address: str) -> bool: - """ - Validate an Algorand address. - - Args: - address: The address string to validate - - Returns: - bool: True if valid, False otherwise - """ - if len(address) != ALGORAND_ADDRESS_LENGTH: - return False - try: - # Add padding back for base32 decoding - padding_needed = (8 - len(address) % 8) % 8 - padded = address + "=" * padding_needed - decoded = base64.b32decode(padded) - - if len(decoded) != ALGORAND_ADDRESS_DECODED_LENGTH: - return False - - addr_hash = decoded[:32] - checksum = decoded[32:] - - # Standard Algorand checksum uses sha512_256, taking last 4 bytes - h = hashlib.new("sha512_256") - h.update(addr_hash) - expected_checksum = h.digest()[-4:] - return checksum == expected_checksum - except Exception: - return False - def _reserve_address_from_cid(cid: str) -> str: """ @@ -91,9 +34,7 @@ def _reserve_address_from_cid(cid: str) -> str: # Workaround to fix `multiformats` package issue, remove first two bytes before using `encode_address`. # Initial fix using `py-multiformats-cid` and `multihash.decode` was dropped due to PEP 517 incompatibility. digest = CID.decode(cid).digest[2:] - reserve_address = _encode_address_from_bytes(digest) - assert _is_valid_address(reserve_address) - return reserve_address + return address_from_public_key(digest) def _create_url_from_cid(cid: str) -> str: @@ -205,24 +146,15 @@ def _compute_metadata_hash( return b"" json_metadata = token_metadata.to_json() + json_metadata_bytes = json_metadata.encode("utf-8") metadata = json.loads(json_metadata) if "extra_metadata" in metadata: - h = hashlib.new("sha512_256") - h.update(b"arc0003/amj") - h.update(json_metadata.encode("utf-8")) - json_metadata_hash = h.digest() - - h = hashlib.new("sha512_256") - h.update(b"arc0003/am") + json_metadata_hash = sha512_256(b"arc0003/amj" + json_metadata_bytes) - h.update(json_metadata_hash) - h.update(base64.b64decode(metadata["extra_metadata"])) - return h.digest() + return sha512_256(b"arc0003/am" + json_metadata_hash + base64.b64decode(metadata["extra_metadata"])) else: - h = hashlib.new("sha256") - h.update(json_metadata.encode("utf-8")) - return h.digest() + return hashlib.sha256(json_metadata_bytes).digest() def mint_token( # noqa: PLR0913 From 4d107c1f3bbf8d1ed1627740120c0d9c94750c25 Mon Sep 17 00:00:00 2001 From: Daniel McGregor Date: Wed, 24 Dec 2025 11:16:56 +0800 Subject: [PATCH 08/19] refactor: simplify assets module --- src/algokit/cli/tasks/assets.py | 9 +++---- src/algokit/cli/tasks/utils.py | 47 +++++++++++---------------------- tests/tasks/test_asset.py | 5 ++-- 3 files changed, 22 insertions(+), 39 deletions(-) diff --git a/src/algokit/cli/tasks/assets.py b/src/algokit/cli/tasks/assets.py index 1df462835..ad1913e6e 100644 --- a/src/algokit/cli/tasks/assets.py +++ b/src/algokit/cli/tasks/assets.py @@ -6,7 +6,6 @@ from algokit.cli.common.constants import AlgorandNetwork, ExplorerEntityType from algokit.cli.common.utils import get_explorer_url from algokit.cli.tasks.utils import ( - get_account_info, get_account_with_private_key, load_algod_client, validate_account_balance_to_opt_in, @@ -22,10 +21,10 @@ def _get_zero_balanced_assets( ) -> list[int]: asset_ids_list = [] if all_assets: - account_info = get_account_info(algod_client, address) - for asset in account_info.get("assets", []): - if asset.get("amount", 0) == 0: - asset_ids_list.append(int(asset["asset-id"])) + account_info = algod_client.account_information(address) + for asset in account_info.assets or (): + if asset.amount == 0: + asset_ids_list.append(asset.asset_id) else: for asset_id in provided_asset_ids: asset_ids_list.append(asset_id) diff --git a/src/algokit/cli/tasks/utils.py b/src/algokit/cli/tasks/utils.py index cd330c4a6..37558e7dc 100644 --- a/src/algokit/cli/tasks/utils.py +++ b/src/algokit/cli/tasks/utils.py @@ -12,6 +12,7 @@ import click import nacl.signing +from algokit_algod_client import models as algod from algokit_utils import AlgoAmount, ClientManager from algokit_utils.algo25 import seed_from_mnemonic from algokit_utils.clients import AlgodClient @@ -24,33 +25,24 @@ logger = logging.getLogger(__name__) -def _get_account_info_dict(algod_client: AlgodClient, address: str) -> dict: - """Convert AlgodClient account_information response to a dict format.""" - response = algod_client.account_information(address) - return { - "amount": getattr(response, "amount", 0), - "assets": [{"asset-id": a.asset_id, "amount": a.amount} for a in getattr(response, "assets", []) or []], - } - - -def _validate_asset_balance(account_info: dict, asset_id: int, decimals: int, amount: int = 0) -> None: - asset_record = next((asset for asset in account_info.get("assets", []) if asset["asset-id"] == asset_id), None) - - if not asset_record: - raise click.ClickException("SigningAccount is not opted into the asset") +def _validate_asset_balance(account_info: algod.Account, asset_id: int, decimals: int, amount: int = 0) -> None: + try: + (asset_record,) = (asset for asset in (account_info.assets or ()) if asset.asset_id == asset_id) + except ValueError: + raise click.ClickException("SigningAccount is not opted into the asset") from None - if amount > 0 and asset_record["amount"] < amount: + if amount > 0 and asset_record.amount < amount: required = amount / 10**decimals - available = asset_record["amount"] / 10**decimals + available = asset_record.amount / 10**decimals raise click.ClickException( f"Insufficient asset balance in account, required: {required}, available: {available}" ) -def _validate_algo_balance(account_info: dict, amount: int) -> None: - if account_info.get("amount", 0) < amount: +def _validate_algo_balance(account_info: algod.Account, amount: int) -> None: + if account_info.amount < amount: required = AlgoAmount.from_micro_algo(amount) - available = AlgoAmount.from_micro_algo(account_info.get("amount", 0)) + available = AlgoAmount.from_micro_algo(account_info.amount) raise click.ClickException( f"Insufficient Algos balance in account, required: {required.algo} Algos, available: {available.algo} Algos" ) @@ -144,12 +136,7 @@ def get_asset_decimals(asset_id: int, algod_client: AlgodClient) -> int: return 6 asset_response = algod_client.asset_by_id(asset_id) - decimals = getattr(getattr(asset_response, "params", None), "decimals", None) - - if decimals is None: - raise click.ClickException("Invalid asset info response") - - return int(decimals) + return asset_response.params.decimals def validate_balance(algod_client: AlgodClient, account: SigningAccount | str, asset_id: int, amount: int = 0) -> None: @@ -167,7 +154,7 @@ def validate_balance(algod_client: AlgodClient, account: SigningAccount | str, a click.ClickException: If any validation check fails. """ address = account.address if isinstance(account, SigningAccount) else account - account_info = _get_account_info_dict(algod_client, address) + account_info = algod_client.account_information(address) if asset_id == 0: _validate_algo_balance(account_info, amount) @@ -289,10 +276,10 @@ def validate_account_balance_to_opt_in(algod_client: AlgodClient, account: Signi """ address = account.address if isinstance(account, SigningAccount) else account - account_info = _get_account_info_dict(algod_client, address) + account_info = algod_client.account_information(address) required_microalgos = num_assets * AlgoAmount.from_algo(Decimal("0.1")).micro_algo - available_microalgos = account_info.get("amount", 0) + available_microalgos = account_info.amount if available_microalgos < required_microalgos: required_algo = AlgoAmount.from_micro_algo(required_microalgos).algo available_algos = AlgoAmount.from_micro_algo(available_microalgos).algo @@ -302,10 +289,6 @@ def validate_account_balance_to_opt_in(algod_client: AlgodClient, account: Signi ) -def get_account_info(algod_client: AlgodClient, account_address: str) -> dict: - return _get_account_info_dict(algod_client, account_address) - - def run_callback_once(callback: Callable) -> Callable: """ Click option callbacks run twice, first to validate the prompt input, diff --git a/tests/tasks/test_asset.py b/tests/tasks/test_asset.py index 96e471c51..aab16067c 100644 --- a/tests/tasks/test_asset.py +++ b/tests/tasks/test_asset.py @@ -1,5 +1,6 @@ import json +from algokit_algod_client.models import Account, AssetHolding from algokit_utils import BulkAssetOptInOutResult from pytest_mock import MockerFixture @@ -125,8 +126,8 @@ def test_opt_out_of_assets_from_account_address_successful(mocker: MockerFixture def test_opt_out_of_all_assets_from_account_address_successful(mocker: MockerFixture) -> None: - dummy_account_info = {"assets": [{"asset-id": 1, "amount": 0}]} - mocker.patch("algokit.cli.tasks.assets.get_account_info", return_value=dummy_account_info) + dummy_account_info = Account(assets=[AssetHolding(asset_id=1)]) + mocker.patch("algokit_algod_client.client.AlgodClient.account_information", return_value=dummy_account_info) algorand_mock = mocker.MagicMock() algorand_mock.asset.bulk_opt_out.return_value = [ BulkAssetOptInOutResult(asset_id=123, transaction_id="dummy_txn_id") From d716d36a6a33387c984792b2e69c60994491b044 Mon Sep 17 00:00:00 2001 From: Daniel McGregor Date: Wed, 24 Dec 2025 11:35:08 +0800 Subject: [PATCH 09/19] refactor: reduce usages of private keys --- src/algokit/cli/tasks/sign_transaction.py | 9 ++++----- src/algokit/cli/tasks/utils.py | 5 +++-- src/algokit/core/address_utils.py | 3 --- src/algokit/core/signing_account.py | 20 +++++--------------- src/algokit/core/tasks/mint/mint.py | 4 ++-- 5 files changed, 14 insertions(+), 27 deletions(-) diff --git a/src/algokit/cli/tasks/sign_transaction.py b/src/algokit/cli/tasks/sign_transaction.py index 0a82dfcc8..37674347b 100644 --- a/src/algokit/cli/tasks/sign_transaction.py +++ b/src/algokit/cli/tasks/sign_transaction.py @@ -14,12 +14,12 @@ decode_transaction, encode_signed_transactions, get_transaction_id, - make_basic_account_transaction_signer, to_transaction_dto, ) from algokit.cli.common.utils import MutuallyExclusiveOption from algokit.cli.tasks.utils import get_account_with_private_key +from algokit.core.signing_account import SigningAccount logger = logging.getLogger(__name__) @@ -148,12 +148,11 @@ def _confirm_transaction(txns: list[Transaction]) -> bool: return bool(response == "y") -def _sign_and_output_transaction(txns: list[Transaction], private_key: str, output: Path | None) -> None: +def _sign_and_output_transaction(txns: list[Transaction], signing_account: SigningAccount, output: Path | None) -> None: # Create a transaction signer from the private key - signer = make_basic_account_transaction_signer(private_key) # Sign all transactions - signer returns encoded SignedTransaction bytes - signed_txn_bytes_list = signer(txns, list(range(len(txns)))) + signed_txn_bytes_list = signing_account.signer(txns, list(range(len(txns)))) # Decode the signed transaction bytes to get SignedTransaction objects signed_txns = [decode_signed_transaction(stx_bytes) for stx_bytes in signed_txn_bytes_list] @@ -216,4 +215,4 @@ def sign(*, account: str, file: Path | None, transaction: str | None, output: Pa if not force and not _confirm_transaction(txns): return - _sign_and_output_transaction(txns, signer_account.private_key, output) + _sign_and_output_transaction(txns, signer_account, output) diff --git a/src/algokit/cli/tasks/utils.py b/src/algokit/cli/tasks/utils.py index 37558e7dc..40e708c54 100644 --- a/src/algokit/cli/tasks/utils.py +++ b/src/algokit/cli/tasks/utils.py @@ -16,9 +16,10 @@ from algokit_utils import AlgoAmount, ClientManager from algokit_utils.algo25 import seed_from_mnemonic from algokit_utils.clients import AlgodClient +from algokit_utils.common import ADDRESS_LENGTH from algokit.cli.common.constants import AlgorandNetwork -from algokit.core.address_utils import ALGORAND_ADDRESS_LENGTH, is_valid_address +from algokit.core.address_utils import is_valid_address from algokit.core.signing_account import SigningAccount from algokit.core.tasks.wallet import get_alias @@ -237,7 +238,7 @@ def get_address(address: str) -> str: validate_address(parsed_address) return parsed_address except click.ClickException as ex: - if len(parsed_address) == ALGORAND_ADDRESS_LENGTH: + if len(parsed_address) == ADDRESS_LENGTH: raise click.ClickException(f"`{parsed_address}` is an invalid account address") from ex alias_data = get_alias(parsed_address) diff --git a/src/algokit/core/address_utils.py b/src/algokit/core/address_utils.py index e75eef9e7..5abc5fd39 100644 --- a/src/algokit/core/address_utils.py +++ b/src/algokit/core/address_utils.py @@ -11,9 +11,6 @@ public_key_from_address, ) -# Standard Algorand address length (58 characters) -ALGORAND_ADDRESS_LENGTH = ADDRESS_LENGTH - def is_valid_address(address: str) -> bool: """Check if an address is a valid Algorand address. diff --git a/src/algokit/core/signing_account.py b/src/algokit/core/signing_account.py index 79cadbe5e..b70a17247 100644 --- a/src/algokit/core/signing_account.py +++ b/src/algokit/core/signing_account.py @@ -5,12 +5,9 @@ new decoupled architecture. """ -from dataclasses import dataclass, field +from algokit_utils.transact import make_basic_account_transaction_signer -from algokit_utils.transact import TransactionSigner, make_basic_account_transaction_signer - -@dataclass class SigningAccount: """A simple account with signing capability. @@ -19,16 +16,9 @@ class SigningAccount: Attributes: address: The Algorand address of the account. - private_key: The private key of the account (base64-encoded string or hex string). + signer: A TransactionSigner from supplied private key """ - address: str - private_key: str - _signer: TransactionSigner | None = field(default=None, repr=False, compare=False) - - @property - def signer(self) -> TransactionSigner: - """Get a transaction signer for this account.""" - if self._signer is None: - object.__setattr__(self, "_signer", make_basic_account_transaction_signer(self.private_key)) - return self._signer # type: ignore[return-value] + def __init__(self, address: str, private_key: str) -> None: + self.address = address + self.signer = make_basic_account_transaction_signer(private_key) diff --git a/src/algokit/core/tasks/mint/mint.py b/src/algokit/core/tasks/mint/mint.py index c17ab8947..e7cc2b8be 100644 --- a/src/algokit/core/tasks/mint/mint.py +++ b/src/algokit/core/tasks/mint/mint.py @@ -8,7 +8,7 @@ from algokit_common import address_from_public_key, sha512_256 from algokit_utils.clients import AlgodClient, algod_models -from algokit_utils.transact import get_transaction_id, make_basic_account_transaction_signer +from algokit_utils.transact import get_transaction_id from algokit_utils.transactions.builders.asset import build_asset_create_transaction from algokit_utils.transactions.types import AssetCreateParams from multiformats import CID @@ -261,7 +261,7 @@ def mint_token( # noqa: PLR0913 ) # Sign the transaction - signer = make_basic_account_transaction_signer(creator_account.private_key) + signer = creator_account.signer signed_txn_bytes = signer([built_txn.txn], [0])[0] # Send the transaction (signer returns encoded signed transaction bytes) From c0267c36ed4c3d6e6bc114433a93794baf912193 Mon Sep 17 00:00:00 2001 From: Altynbek Orumbayev Date: Tue, 3 Mar 2026 15:16:33 +0100 Subject: [PATCH 10/19] chore: lockfile --- poetry.lock | 113 +++++++++++++++++++++++++++---------------------- pyproject.toml | 2 +- 2 files changed, 64 insertions(+), 51 deletions(-) diff --git a/poetry.lock b/poetry.lock index 211a6acdf..616f6583d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -618,62 +618,75 @@ toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cryptography" -version = "44.0.3" +version = "46.0.5" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false -python-versions = "!=3.9.0,!=3.9.1,>=3.7" +python-versions = "!=3.9.0,!=3.9.1,>=3.8" groups = ["main", "dev"] files = [ - {file = "cryptography-44.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:962bc30480a08d133e631e8dfd4783ab71cc9e33d5d7c1e192f0b7c06397bb88"}, - {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffc61e8f3bf5b60346d89cd3d37231019c17a081208dfbbd6e1605ba03fa137"}, - {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58968d331425a6f9eedcee087f77fd3c927c88f55368f43ff7e0a19891f2642c"}, - {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e28d62e59a4dbd1d22e747f57d4f00c459af22181f0b2f787ea83f5a876d7c76"}, - {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af653022a0c25ef2e3ffb2c673a50e5a0d02fecc41608f4954176f1933b12359"}, - {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:157f1f3b8d941c2bd8f3ffee0af9b049c9665c39d3da9db2dc338feca5e98a43"}, - {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:c6cd67722619e4d55fdb42ead64ed8843d64638e9c07f4011163e46bc512cf01"}, - {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b424563394c369a804ecbee9b06dfb34997f19d00b3518e39f83a5642618397d"}, - {file = "cryptography-44.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c91fc8e8fd78af553f98bc7f2a1d8db977334e4eea302a4bfd75b9461c2d8904"}, - {file = "cryptography-44.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:25cd194c39fa5a0aa4169125ee27d1172097857b27109a45fadc59653ec06f44"}, - {file = "cryptography-44.0.3-cp37-abi3-win32.whl", hash = "sha256:3be3f649d91cb182c3a6bd336de8b61a0a71965bd13d1a04a0e15b39c3d5809d"}, - {file = "cryptography-44.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:3883076d5c4cc56dbef0b898a74eb6992fdac29a7b9013870b34efe4ddb39a0d"}, - {file = "cryptography-44.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:5639c2b16764c6f76eedf722dbad9a0914960d3489c0cc38694ddf9464f1bb2f"}, - {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ffef566ac88f75967d7abd852ed5f182da252d23fac11b4766da3957766759"}, - {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:192ed30fac1728f7587c6f4613c29c584abdc565d7417c13904708db10206645"}, - {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7d5fe7195c27c32a64955740b949070f21cba664604291c298518d2e255931d2"}, - {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3f07943aa4d7dad689e3bb1638ddc4944cc5e0921e3c227486daae0e31a05e54"}, - {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cb90f60e03d563ca2445099edf605c16ed1d5b15182d21831f58460c48bffb93"}, - {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ab0b005721cc0039e885ac3503825661bd9810b15d4f374e473f8c89b7d5460c"}, - {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:3bb0847e6363c037df8f6ede57d88eaf3410ca2267fb12275370a76f85786a6f"}, - {file = "cryptography-44.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b0cc66c74c797e1db750aaa842ad5b8b78e14805a9b5d1348dc603612d3e3ff5"}, - {file = "cryptography-44.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6866df152b581f9429020320e5eb9794c8780e90f7ccb021940d7f50ee00ae0b"}, - {file = "cryptography-44.0.3-cp39-abi3-win32.whl", hash = "sha256:c138abae3a12a94c75c10499f1cbae81294a6f983b3af066390adee73f433028"}, - {file = "cryptography-44.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:5d186f32e52e66994dce4f766884bcb9c68b8da62d61d9d215bfe5fb56d21334"}, - {file = "cryptography-44.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:cad399780053fb383dc067475135e41c9fe7d901a97dd5d9c5dfb5611afc0d7d"}, - {file = "cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:21a83f6f35b9cc656d71b5de8d519f566df01e660ac2578805ab245ffd8523f8"}, - {file = "cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fc3c9babc1e1faefd62704bb46a69f359a9819eb0292e40df3fb6e3574715cd4"}, - {file = "cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:e909df4053064a97f1e6565153ff8bb389af12c5c8d29c343308760890560aff"}, - {file = "cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:dad80b45c22e05b259e33ddd458e9e2ba099c86ccf4e88db7bbab4b747b18d06"}, - {file = "cryptography-44.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:479d92908277bed6e1a1c69b277734a7771c2b78633c224445b5c60a9f4bc1d9"}, - {file = "cryptography-44.0.3-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:896530bc9107b226f265effa7ef3f21270f18a2026bc09fed1ebd7b66ddf6375"}, - {file = "cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9b4d4a5dbee05a2c390bf212e78b99434efec37b17a4bff42f50285c5c8c9647"}, - {file = "cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02f55fb4f8b79c1221b0961488eaae21015b69b210e18c386b69de182ebb1259"}, - {file = "cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:dd3db61b8fe5be220eee484a17233287d0be6932d056cf5738225b9c05ef4fff"}, - {file = "cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:978631ec51a6bbc0b7e58f23b68a8ce9e5f09721940933e9c217068388789fe5"}, - {file = "cryptography-44.0.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:5d20cc348cca3a8aa7312f42ab953a56e15323800ca3ab0706b8cd452a3a056c"}, - {file = "cryptography-44.0.3.tar.gz", hash = "sha256:fe19d8bc5536a91a24a8133328880a41831b6c5df54599a8417b62fe015d3053"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""] + {file = "cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0"}, + {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731"}, + {file = "cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82"}, + {file = "cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1"}, + {file = "cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48"}, + {file = "cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4"}, + {file = "cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0"}, + {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663"}, + {file = "cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826"}, + {file = "cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d"}, + {file = "cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a"}, + {file = "cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4"}, + {file = "cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d"}, + {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c"}, + {file = "cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4"}, + {file = "cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9"}, + {file = "cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72"}, + {file = "cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257"}, + {file = "cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7"}, + {file = "cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d"}, +] + +[package.dependencies] +cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9.0\" and platform_python_implementation != \"PyPy\""} +typing-extensions = {version = ">=4.13.2", markers = "python_full_version < \"3.11.0\""} + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"] docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""] -pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +nox = ["nox[uv] (>=2024.4.15)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.14)", "ruff (>=0.11.11)"] sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==44.0.3)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] +test = ["certifi (>=2024)", "cryptography-vectors (==46.0.5)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] test-randomorder = ["pytest-randomly"] [[package]] @@ -3459,4 +3472,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<3.15" -content-hash = "1aafa2e9f1424c37ee9138f4674f333b5d42ecec3c50077fc92fd7cc7d87c5d3" +content-hash = "5e34de85e47c53abbef92d89aa9c338bb4c010e57e7e94748ca22a5cb8627dfa" diff --git a/pyproject.toml b/pyproject.toml index 7bff7a41f..d28ec3b04 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ keyring = "25.6.0" # see header in src/algokit/core/_vendor/auth0/authentication/token_verifier.py # this version has been tested to work with the vendored file pyjwt = "^2.10.1" -cryptography = "^44.0.2" # pyjwt has a weak dependency on cryptography and explicitly requires it in the vendored file, hence the lock +cryptography = "^46.0.5" # pyjwt has a weak dependency on cryptography and explicitly requires it in the vendored file, hence the lock algokit-utils = "^5.0.0a7" multiformats = "0.3.1" multiformats_config = "0.3.1" # pinned this to be in lockstep with multiformats From 93b4c70fdad364e8c5f676a90084a7fdc7959ba9 Mon Sep 17 00:00:00 2001 From: Al <7698600+aorumbayev@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:23:35 +0100 Subject: [PATCH 11/19] refactor: migrate to uv-first packaging and distribution (#712) * refactor: migrate to uv - uv as primary distribution method * chore: regen tests * refactor: apply uv migration review refinements - Add UV project detection (uv pip show) to PythonClientGenerator - Decompose bootstrap_uv into focused helper functions - Standardize CI workflows to use composite setup-uv action - Replace silent catch blocks with warning logs in install.ps1 - Update error message URLs to docs.astral.sh/uv/ - Use uv python find instead of grep in install.sh - Rename PowerShell verbs to follow approved conventions - Add debug logging for legacy command normalization - Document sentinel version value in version_prompt.py - Update test assertions and approval snapshots for UV-first resolution * fix: warn on algokit PATH collisions during uv migration * chore: pr comments --- .../actions/build-binaries/linux/action.yaml | 4 +- .../actions/build-binaries/macos/action.yaml | 4 +- .../build-binaries/windows/action.yaml | 4 +- .github/actions/setup-poetry/action.yaml | 32 - .github/actions/setup-uv/action.yaml | 20 + .github/assets/banner.svg | 75 + .github/workflows/build-binaries.yaml | 16 +- .github/workflows/build-python.yaml | 26 +- .github/workflows/cd.yaml | 25 +- .github/workflows/check-python.yaml | 33 +- .github/workflows/clear-caches.yaml | 2 +- .../workflows/publish-release-packages.yaml | 8 +- .pre-commit-config.yaml | 6 +- .python-version | 1 + CONTRIBUTING.md | 30 +- README.md | 158 +- debug.py | 2 +- docs/features/compile.md | 2 +- docs/features/doctor.md | 26 +- docs/features/generate.md | 4 +- docs/tutorials/intro.md | 10 +- poetry.lock | 3475 ----------------- poetry.toml | 2 - pyproject.toml | 123 +- scripts/install/install.ps1 | 124 + scripts/install/install.sh | 126 + src/algokit/cli/__init__.py | 62 + src/algokit/cli/doctor.py | 16 +- src/algokit/cli/project/__init__.py | 18 - src/algokit/core/compilers/python.py | 35 +- .../config_commands/py_package_manager.py | 7 +- .../core/config_commands/version_prompt.py | 13 +- src/algokit/core/dispenser.py | 2 +- src/algokit/core/project/bootstrap.py | 191 +- src/algokit/core/project/run.py | 19 +- src/algokit/core/tasks/analyze.py | 16 +- src/algokit/core/typed_client_generation.py | 63 +- src/algokit/core/utils.py | 87 +- tests/compile/test_python.py | 15 +- ...t_python.test_compile_py_help.approved.txt | 2 + ..._puyapy_is_installed_globally.approved.txt | 2 + ...uyapy_is_installed_in_project.approved.txt | 2 + ...apy_is_not_installed_anywhere.approved.txt | 12 +- ...yapy_version_is_not_installed.approved.txt | 12 +- tests/doctor/test_doctor.py | 4 +- ..._all_commands_bad_exit[linux].approved.txt | 5 +- ..._all_commands_bad_exit[macOS].approved.txt | 5 +- ...ll_commands_bad_exit[windows].approved.txt | 5 +- ...all_commands_not_found[linux].approved.txt | 13 +- ...all_commands_not_found[macOS].approved.txt | 13 +- ...l_commands_not_found[windows].approved.txt | 13 +- ...test_doctor_successful[linux].approved.txt | 5 +- ...test_doctor_successful[macOS].approved.txt | 5 +- ...st_doctor_successful[windows].approved.txt | 5 +- ..._doctor.test_doctor_with_copy.approved.txt | 5 +- ...docker_compose_version_gitpod.approved.txt | 5 +- ...r_compose_version_unparseable.approved.txt | 5 +- ...ocker_compose_version_warning.approved.txt | 5 +- ...ctor_with_weird_values_on_mac.approved.txt | 5 +- ..._with_weird_values_on_windows.approved.txt | 5 +- ...new_algokit_version_available.approved.txt | 5 +- ...or.test_npm_permission_denied.approved.txt | 5 +- ...exception_locating_executable.approved.txt | 5 +- ...st_unparseable_python_version.approved.txt | 5 +- tests/explore/test_explore.py | 2 +- tests/generate/test_generate_client.py | 35 +- ...rate_client_no_app_spec_found.approved.txt | 6 +- ...ate_client_output_path_is_dir.approved.txt | 6 +- ..._name}.py-hello_world_app.py].approved.txt | 20 +- ....0-hello_world_app_client.py].approved.txt | 20 +- ...on-hello_world_app_client.py].approved.txt | 20 +- ...on --version 1.1.2-client.py].approved.txt | 20 +- ... -p --mode minimal-client.py].approved.txt | 20 +- ...ython[-o client.py-client.py].approved.txt | 20 +- ... --language python-client.ts].approved.txt | 20 +- ...n_arc32_filename.-o.client.py.approved.txt | 20 +- ...n_arc56_filename.-o.client.py.approved.txt | 20 +- ...ecs_in_directory.-o.client.py.approved.txt | 20 +- ...est_generate_client_recursive.approved.txt | 24 +- ...rate_client.test_pipx_missing.approved.txt | 5 +- ...nerator_is_installed_globally.approved.txt | 14 +- ...rator_is_installed_in_project.approved.txt | 12 +- ...ion_is_not_installed_anywhere.approved.txt | 22 +- ..._init_bootstrap_broken_poetry.approved.txt | 1 - tests/portability/test_pyinstaller_binary.py | 14 +- ...bootstrap.test_bootstrap_help.approved.txt | 2 - ...strap_all_algokit_min_version.approved.txt | 2 - ...okit_min_version_ignore_error.approved.txt | 2 - ..._all.test_bootstrap_all_empty.approved.txt | 2 - ...ap_all.test_bootstrap_all_env.approved.txt | 2 - ...test_bootstrap_all_npm[linux].approved.txt | 3 - ...test_bootstrap_all_npm[macOS].approved.txt | 3 - ...st_bootstrap_all_npm[windows].approved.txt | 3 - ...all.test_bootstrap_all_poetry.approved.txt | 4 - ...trap_all_poetry_via_pyproject.approved.txt | 4 - ...bootstrap_all_projects_filter.approved.txt | 1 - ...trap_all_projects_name_filter.approved.txt | 4 - ...rojects_name_filter_not_found.approved.txt | 3 - ...trap_all_projects_type_filter.approved.txt | 3 - ...rojects_type_filter_not_found.approved.txt | 3 - ....test_bootstrap_all_skip_dirs.approved.txt | 2 - ...ll.test_bootstrap_all_sub_dir.approved.txt | 4 - ...nv_different_prompt_scenarios.approved.txt | 2 - ...t_bootstrap_env_dotenv_exists.approved.txt | 2 - ...otenv_missing_template_exists.approved.txt | 2 - ...tstrap_env_dotenv_with_values.approved.txt | 2 - ...tstrap_env_multiple_templates.approved.txt | 2 - ...v.test_bootstrap_env_no_files.approved.txt | 2 - ...ap_network_prefixed_envs..env.approved.txt | 2 - ...k_prefixed_envs..env.localnet.approved.txt | 2 - ...d_envs..env.localnet.template.approved.txt | 2 - ...k_prefixed_envs..env.template.approved.txt | 2 - ...ci_mode_with_lock_file[linux].approved.txt | 3 - ...ci_mode_with_lock_file[macOS].approved.txt | 3 - ..._mode_with_lock_file[windows].approved.txt | 3 - ...mode_without_lock_file[linux].approved.txt | 3 - ...mode_without_lock_file[macOS].approved.txt | 3 - ...de_without_lock_file[windows].approved.txt | 3 - ...otstrap_npm_happy_path[linux].approved.txt | 3 - ...otstrap_npm_happy_path[macOS].approved.txt | 3 - ...strap_npm_happy_path[windows].approved.txt | 3 - ...tstrap_npm_without_npm[linux].approved.txt | 3 - ...tstrap_npm_without_npm[macOS].approved.txt | 3 - ...trap_npm_without_npm[windows].approved.txt | 3 - ...t_npm_and_package_file[linux].approved.txt | 3 - ...t_npm_and_package_file[macOS].approved.txt | 3 - ...npm_and_package_file[windows].approved.txt | 3 - ...m_without_package_file[linux].approved.txt | 3 - ...m_without_package_file[macOS].approved.txt | 3 - ...without_package_file[windows].approved.txt | 3 - ...gured_package_managers[linux].approved.txt | 3 - ...gured_package_managers[macOS].approved.txt | 3 - ...red_package_managers[windows].approved.txt | 3 - ...e_over_user_preference[linux].approved.txt | 2 - ...e_over_user_preference[macOS].approved.txt | 2 - ...over_user_preference[windows].approved.txt | 2 - ...npm_ci_mode_without_lock_file.approved.txt | 2 - ...tstrap_pnpm_happy_path[linux].approved.txt | 3 - ...tstrap_pnpm_happy_path[macOS].approved.txt | 3 - ...trap_pnpm_happy_path[windows].approved.txt | 3 - ...rap_pnpm_without_package_file.approved.txt | 2 - .../bootstrap/test_bootstrap_poetry.py | 45 +- ..._bootstrap_poetry_with_poetry.approved.txt | 4 - ...otstrap_poetry_without_poetry.approved.txt | 13 +- ...without_poetry_failed_install.approved.txt | 15 +- ...out_poetry_failed_poetry_path.approved.txt | 15 +- ..._pipx_path[no_system_pythons].approved.txt | 14 +- ...ry_or_pipx_path[python3_only].approved.txt | 14 +- ...pipx_path[python_and_python3].approved.txt | 14 +- ...try_or_pipx_path[python_only].approved.txt | 14 +- ...y_or_pipx_path_failed_install.approved.txt | 16 +- ..._pipx_path_failed_poetry_path.approved.txt | 16 +- ...y_or_pipx_path_or_pipx_module.approved.txt | 9 +- ....test_bootstrap_uv_happy_path.approved.txt | 3 - ...ry_project_migration_declined.approved.txt | 3 - ...trap_uv_user_declines_install.approved.txt | 5 +- tests/project/deploy/test_deploy.py | 20 +- ...st_algokit_config_empty_array.approved.txt | 2 - ...algokit_config_invalid_syntax.approved.txt | 2 - ...t_algokit_config_name_no_base.approved.txt | 3 - ...algokit_config_name_overrides.approved.txt | 3 - ...eploy_only_base_deploy_config.approved.txt | 3 - ...okit_env_and_name_correct_set.approved.txt | 3 - ...test_algokit_env_name_missing.approved.txt | 2 - ...ag_interactivity_mode_via_cli.approved.txt | 3 - ...ag_interactivity_mode_via_env.approved.txt | 3 - ...oy.test_command_bad_exit_code.approved.txt | 3 - ...ocation_and_command_splitting.approved.txt | 2 - ...y.test_command_not_executable.approved.txt | 3 - ...mmand_not_found_and_no_config.approved.txt | 3 - ...command_splitting_from_config.approved.txt | 2 - ...without_splitting_from_config.approved.txt | 2 - ...est_deploy_custom_project_dir.approved.txt | 3 - ...ploy_dispenser_alias.deployer.approved.txt | 3 - ...loy_dispenser_alias.dispenser.approved.txt | 3 - ...ploy_shutil_command_not_found.approved.txt | 2 - ...y.test_deploy_with_extra_args.approved.txt | 3 - ...extra_args_and_custom_command.approved.txt | 3 - ...t_secrets_prompting_via_stdin.approved.txt | 3 - ...ist_command_from_empty_folder.approved.txt | 2 - ...ist.test_list_command_no_args.approved.txt | 2 - tests/project/run/test_run.py | 18 + tests/tasks/test_analyze.py | 3 +- ...ze.test_analyze_error_no_pipx.approved.txt | 2 +- tests/test_utils_path_resolution.py | 68 + tests/utils/approvals.py | 13 +- ...github_when_cache_out_of_date.approved.txt | 2 - ..._queries_github_when_no_cache.approved.txt | 2 - ...check_respects_disable_config.approved.txt | 2 - ...on_check_respects_skip_option.approved.txt | 2 - ...test_version_check_uses_cache.approved.txt | 2 - uv.lock | 2819 +++++++++++++ 192 files changed, 4185 insertions(+), 4556 deletions(-) delete mode 100644 .github/actions/setup-poetry/action.yaml create mode 100644 .github/actions/setup-uv/action.yaml create mode 100644 .github/assets/banner.svg create mode 100644 .python-version delete mode 100644 poetry.lock delete mode 100644 poetry.toml create mode 100644 scripts/install/install.ps1 create mode 100755 scripts/install/install.sh create mode 100644 tests/test_utils_path_resolution.py create mode 100644 uv.lock diff --git a/.github/actions/build-binaries/linux/action.yaml b/.github/actions/build-binaries/linux/action.yaml index a5ee3ff33..4298d5116 100644 --- a/.github/actions/build-binaries/linux/action.yaml +++ b/.github/actions/build-binaries/linux/action.yaml @@ -16,7 +16,7 @@ runs: - name: Build binary shell: bash run: | - poetry run poe package_unix + uv run poe package_unix - name: Package binary artifact shell: bash @@ -27,7 +27,7 @@ runs: cd ../.. - name: Upload binary artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ${{ inputs.package_name }}-snap path: ${{ inputs.artifacts_dir }}/${{ inputs.package_name }}-snap.tar.gz diff --git a/.github/actions/build-binaries/macos/action.yaml b/.github/actions/build-binaries/macos/action.yaml index d1fcc4ca4..6c2ebe859 100644 --- a/.github/actions/build-binaries/macos/action.yaml +++ b/.github/actions/build-binaries/macos/action.yaml @@ -36,7 +36,7 @@ runs: run: | export APPLE_CERT_ID="${{ inputs.with_codesign == 'true' && inputs.apple_cert_id || '' }}" export APPLE_BUNDLE_ID="${{ inputs.with_codesign == 'true' && inputs.apple_bundle_id || format('beta.{0}', inputs.apple_bundle_id) }}" - poetry run poe package_mac + uv run poe package_mac env: APPLE_CERT_ID: ${{ inputs.with_codesign == 'true' && inputs.apple_cert_id || '' }} APPLE_BUNDLE_ID: ${{ inputs.with_codesign == 'true' && inputs.apple_bundle_id || format('beta.{0}', inputs.apple_bundle_id) }} @@ -73,7 +73,7 @@ runs: cd ../.. - name: Upload binary artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ${{ inputs.package_name }} path: ${{ inputs.artifacts_dir }}/${{ inputs.package_name }}-brew.tar.gz diff --git a/.github/actions/build-binaries/windows/action.yaml b/.github/actions/build-binaries/windows/action.yaml index f0b5fe50f..5f7e534e2 100644 --- a/.github/actions/build-binaries/windows/action.yaml +++ b/.github/actions/build-binaries/windows/action.yaml @@ -82,7 +82,7 @@ runs: - name: Build binary shell: bash run: | - poetry run poe package_windows + uv run poe package_windows - name: Add metadata to binary shell: bash @@ -130,7 +130,7 @@ runs: timestamp-digest: SHA256 - name: Upload winget artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ${{ inputs.package_name }}-winget path: ${{ env.WINGET_INSTALLER }} diff --git a/.github/actions/setup-poetry/action.yaml b/.github/actions/setup-poetry/action.yaml deleted file mode 100644 index e74b2eefc..000000000 --- a/.github/actions/setup-poetry/action.yaml +++ /dev/null @@ -1,32 +0,0 @@ -name: "Python Poetry Action" -description: "An action to setup Poetry" -runs: - using: "composite" - steps: - # A workaround for pipx isn't installed on M1 runner. - # We should remove it after this issue is resolved. - # https://github.com/actions/runner-images/issues/9256 - - if: ${{ runner.os == 'macOS' && runner.arch == 'ARM64' }} - run: | - pip install poetry - pip install poetry-plugin-export - shell: bash - - - if: ${{ runner.os != 'macOS' || runner.arch != 'ARM64' }} - run: | - pip install --user pipx - pipx ensurepath - pipx install poetry ${{ runner.os == 'macOS' && '--python "$Python_ROOT_DIR/bin/python"' || '' }} - pipx inject poetry poetry-plugin-export - shell: bash - - - name: Get full Python version - id: full-python-version - shell: bash - run: echo "full_version=$(python -c 'import sys; print(".".join(map(str, sys.version_info[:3])))')" >> $GITHUB_OUTPUT - - - name: Setup poetry cache - uses: actions/cache@v4 - with: - path: ./.venv - key: venv-${{ hashFiles('poetry.lock') }}-${{ runner.os }}-${{ runner.arch }}-${{ steps.full-python-version.outputs.full_version }} diff --git a/.github/actions/setup-uv/action.yaml b/.github/actions/setup-uv/action.yaml new file mode 100644 index 000000000..0c7cd48bc --- /dev/null +++ b/.github/actions/setup-uv/action.yaml @@ -0,0 +1,20 @@ +name: "Setup uv" +description: "Install uv and sync project dependencies" +inputs: + extra-sync-args: + description: "Additional arguments to pass to uv sync (e.g. --group docs)" + required: false + default: "" +runs: + using: "composite" + steps: + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + version: "0.10.x" + enable-cache: true + cache-dependency-glob: "uv.lock" + + - name: Sync dependencies + run: uv sync --frozen ${{ inputs.extra-sync-args }} + shell: bash diff --git a/.github/assets/banner.svg b/.github/assets/banner.svg new file mode 100644 index 000000000..04624edee --- /dev/null +++ b/.github/assets/banner.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + [algokit-cli] + + + + + + + + + + $ uv tool install algokit + + + + + + + + + + + + Extensive CLI + + + + for Algorand + + + + blockchain projects + + + diff --git a/.github/workflows/build-binaries.yaml b/.github/workflows/build-binaries.yaml index 9a85f3a93..f1216c3ad 100644 --- a/.github/workflows/build-binaries.yaml +++ b/.github/workflows/build-binaries.yaml @@ -40,20 +40,18 @@ jobs: shell: bash - name: Checkout source code - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ inputs.release_version != '' && format('v{0}', inputs.release_version) || '' }} - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ inputs.python_version }} - - name: Set up Poetry - uses: ./.github/actions/setup-poetry + - name: Set up uv + uses: ./.github/actions/setup-uv - - name: Install dependencies - run: poetry install --no-interaction - name: Configure build environment shell: bash @@ -116,14 +114,14 @@ jobs: if: ${{ runner.os == 'Windows' }} run: | git config --global user.email "actions@github.com" && git config --global user.name "github-actions" - poetry run pytest tests/ -m pyinstaller_binary_tests --log-cli-level=INFO + uv run pytest tests/ -m pyinstaller_binary_tests --log-cli-level=INFO shell: cmd - name: Run portability tests if: ${{ runner.os != 'Windows' }} run: | git config --global user.email "actions@github.com" && git config --global user.name "github-actions" - poetry run pytest tests/ -m pyinstaller_binary_tests --log-cli-level=INFO + uv run pytest tests/ -m pyinstaller_binary_tests --log-cli-level=INFO shell: bash # softprops/action-gh-release doesn't support the \ character in paths @@ -136,7 +134,7 @@ jobs: - name: Append artifacts to release if: ${{ inputs.production_release == 'true' }} - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: fail_on_unmatched_files: true files: | diff --git a/.github/workflows/build-python.yaml b/.github/workflows/build-python.yaml index efdfc1f62..feff62236 100644 --- a/.github/workflows/build-python.yaml +++ b/.github/workflows/build-python.yaml @@ -12,29 +12,29 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout source code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python }} - name: Set up Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: 20 - - name: Set up Poetry - uses: ./.github/actions/setup-poetry + - name: Set up uv + uses: ./.github/actions/setup-uv - - name: Install dependencies - # TODO: remove fixed pipx dependency once 3.12 compatibility is addressed + - name: Install tealer + # TODO: remove fixed tealer dependency once 3.12 compatibility is addressed # track here -> https://github.com/crytic/tealer/pull/209 - run: poetry install --no-interaction --without docs && pipx install tealer==0.1.2 + run: uv tool install tealer==0.1.2 - name: Install PuyaPy if: ${{ matrix.python == '3.12' }} - run: pipx install puyapy + run: uv tool install puyapy - name: pytest shell: bash @@ -43,7 +43,7 @@ jobs: run: | set -o pipefail git config --global user.email "actions@github.com" && git config --global user.name "github-actions" - poetry run pytest -n auto + uv run pytest -n auto id: pytest - name: pytest + coverage @@ -55,12 +55,12 @@ jobs: run: | set -o pipefail git config --global user.email "actions@github.com" && git config --global user.name "github-actions" - poetry run pytest -n auto --junitxml=pytest-junit.xml --cov-report=term-missing:skip-covered --cov=src | tee pytest-coverage.txt + uv run pytest -n auto --junitxml=pytest-junit.xml --cov-report=term-missing:skip-covered --cov=src | tee pytest-coverage.txt id: pytest-cov - name: Upload received snapshots (in case of failure) if: failure() && (steps.pytest.outcome == 'failure' || steps.pytest-cov.outcome == 'failure') - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: test-artifacts-${{ matrix.os }}-python${{ matrix.python }} path: tests/**/*.received.txt @@ -74,4 +74,4 @@ jobs: junitxml-path: ./pytest-junit.xml - name: Build Wheel - run: poetry build --format wheel + run: uv build --wheel diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml index 92c8dd240..ac1224500 100644 --- a/.github/workflows/cd.yaml +++ b/.github/workflows/cd.yaml @@ -52,22 +52,19 @@ jobs: app-id: ${{ secrets.BOT_ID }} private-key: ${{ secrets.BOT_SK }} - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: # Fetch entire repository history so we can determine version number from it fetch-depth: 0 token: ${{ steps.app_token.outputs.token }} - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: - python-version: "3.10" + python-version: "3.12" - - name: Set up Poetry - uses: ./.github/actions/setup-poetry - - - name: Install dependencies - run: poetry install --no-interaction --no-root + - name: Set up uv + uses: ./.github/actions/setup-uv - name: Get branch name shell: bash @@ -80,7 +77,7 @@ jobs: - name: Create Continuous Deployment - Feature Branch if: steps.get_branch.outputs.branch != 'main' && inputs.production_release != 'true' run: | - poetry run semantic-release \ + uv run semantic-release \ -v DEBUG \ --prerelease \ --patch \ @@ -98,12 +95,12 @@ jobs: - name: Create Continuous Deployment - Beta (non-prod) if: steps.get_branch.outputs.branch == 'main' && inputs.production_release != 'true' run: | - poetry run semantic-release \ + uv run semantic-release \ -v DEBUG \ --prerelease \ --define=branch=main \ publish - release_version="$(poetry run semantic-release print-version --current)" + release_version="$(uv run semantic-release print-version --current)" gh release edit --prerelease "v$release_version" echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV env: @@ -114,14 +111,14 @@ jobs: - name: Create Continuous Deployment - Production if: steps.get_branch.outputs.branch == 'main' && inputs.production_release == 'true' run: | - poetry run semantic-release \ + uv run semantic-release \ -v DEBUG \ --define=version_source="commit" \ --define=patch_without_tag=true \ --define=upload_to_repository=true \ --define=branch=main \ publish - release_version="$(poetry run semantic-release print-version --current)" + release_version="$(uv run semantic-release print-version --current)" echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV env: GH_TOKEN: ${{ steps.app_token.outputs.token }} @@ -134,7 +131,7 @@ jobs: id: get_release_version - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: algokit-cli path: dist/algokit*-py3-none-any.whl diff --git a/.github/workflows/check-python.yaml b/.github/workflows/check-python.yaml index e98d78eed..e799e5305 100644 --- a/.github/workflows/check-python.yaml +++ b/.github/workflows/check-python.yaml @@ -8,40 +8,35 @@ jobs: runs-on: "ubuntu-latest" steps: - name: Checkout source code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up Python 3.12 - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.12" - - name: Set up Poetry - uses: ./.github/actions/setup-poetry - - - name: Install dependencies - run: poetry install --no-interaction --with docs + - name: Set up uv + uses: ./.github/actions/setup-uv + with: + extra-sync-args: "--group docs" - name: Audit with pip-audit run: | - poetry export --without=dev --without=docs -o requirements.txt - poetry run pip-audit -r requirements.txt - # If a vulnerability is found in a dependency without an available fix, - # it can be temporarily ignored by adding --ignore-vuln e.g. poetry run pip-audit -r requirements.txt --ignore-vuln 'GHSA-xxxxx' + set -o pipefail + uv export --no-dev --no-group docs --no-emit-project -o requirements.txt + uv run pip-audit -r requirements.txt - name: Check formatting with Ruff - run: | - # stop the build if there are files that don't meet formatting requirements - poetry run ruff format --check . + run: uv run ruff format --check . - name: Check linting with Ruff - run: | - # stop the build if there are Python syntax errors or undefined names - poetry run ruff check . + run: uv run ruff check . - name: Check types with mypy - run: poetry run mypy + run: uv run mypy - name: Check docs are up to date run: | - poetry run poe docs + set -o pipefail + uv run poe docs [ $(git status --porcelain docs/ | wc -l) -eq "0" ] diff --git a/.github/workflows/clear-caches.yaml b/.github/workflows/clear-caches.yaml index c2050ce84..11b8e947f 100644 --- a/.github/workflows/clear-caches.yaml +++ b/.github/workflows/clear-caches.yaml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Clear all repository caches env: diff --git a/.github/workflows/publish-release-packages.yaml b/.github/workflows/publish-release-packages.yaml index 6026710ca..9629bffff 100644 --- a/.github/workflows/publish-release-packages.yaml +++ b/.github/workflows/publish-release-packages.yaml @@ -66,7 +66,7 @@ jobs: owner: algorandfoundation - name: Checkout source code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Download wheel from release run: gh release download v${{ inputs.release_version }} --pattern "*.whl" --dir dist @@ -91,7 +91,7 @@ jobs: if: ${{ inputs.do_winget }} steps: - name: Checkout source code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Publish to winget shell: pwsh @@ -108,7 +108,7 @@ jobs: steps: - name: Checkout source code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Download binary artifact from release run: | @@ -123,7 +123,7 @@ jobs: ./scripts/snap/create-snapcraft-yaml.sh ${{ github.workspace }} ${{ inputs.release_version }} ${{ env.BINARY_PATH }} "stable" - name: Upload snapcraft.yaml as reference artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: snapcraft-yaml path: ${{ github.workspace }}/snap/snapcraft.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a6f846afb..3f9e3a7ab 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: - id: ruff-format name: ruff-format description: "Run 'ruff format' for extremely fast Python formatting" - entry: poetry run ruff format + entry: uv run ruff format language: system types: [python] args: [--no-cache] @@ -13,7 +13,7 @@ repos: - id: ruff name: ruff description: "Run 'ruff' for extremely fast Python linting" - entry: poetry run ruff check + entry: uv run ruff check language: system "types": [python] args: [--fix, --no-cache] @@ -23,7 +23,7 @@ repos: - id: mypy name: mypy description: "`mypy` will check Python types for correctness" - entry: poetry run mypy + entry: uv run mypy language: system types_or: [python, pyi] require_serial: true diff --git a/.python-version b/.python-version new file mode 100644 index 000000000..e4fba2183 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 32ca79171..9b271dae3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,18 +15,16 @@ AlgoKit development is done within the [AlgoKit Guiding Principles](./docs/algok 1. Clone this repository: `git clone https://github.com/algorandfoundation/algokit-cli` 2. Install pre-requisites: - - Manually: - - Install `Python` - [Link](https://www.python.org/downloads/): The minimum required version is `3.10`, but `3.11` is recommended.) - - Install `Poetry` - [Link](https://python-poetry.org/docs/#installation): The minimum required version is `1.2`. - - If you're not using PyCharm, then run `poetry install` in the repository root directory (this should set up `.venv` and install all Python dependencies - PyCharm will do this for you on startup) - - Via AlgoKit CLI: - - - [Install AlgoKit CLI](./README.md#install) and run `algokit project bootstrap poetry` in the root directory - - Install `tealer` - by running `pipx install tealer==0.1.2`. This is a prerequisite to running `pytest`, tealer is a third party tool for static analysis of TEAL code, algokit uses it in `task analyse` command. AlgoKit uses `pytest-xdist` to speed up the test suite execution by running tests in parallel, this requires `tealer` to be installed globally to avoid race conditions. + - Install [uv](https://docs.astral.sh/uv/) - the project's package manager: + ```shell + curl -LsSf https://astral.sh/uv/install.sh | sh + ``` + - Run `uv sync` in the repository root directory (this sets up `.venv` and installs all Python dependencies) + - Install `tealer` - by running `uv tool install tealer==0.1.2`. This is a prerequisite to running `pytest`, tealer is a third party tool for static analysis of TEAL code, algokit uses it in `task analyse` command. AlgoKit uses `pytest-xdist` to speed up the test suite execution by running tests in parallel, this requires `tealer` to be installed globally to avoid race conditions. 3. Install pre-commit hooks (optional but recommended): - [pre-commit](https://pre-commit.com/) is configured in this repository. To enable it, make sure that `poetry install` has been run and the virtual-env is activated by running `poetry shell`. Then execute `pre-commit install` to install the git hook scripts. + [pre-commit](https://pre-commit.com/) is configured in this repository. To enable it, make sure that `uv sync` has been run. Then execute `uv run pre-commit install` to install the git hook scripts. Once it is done, git will ensure formatting, linting, and static typing (via `mypy`) is correct when you perform a commit. @@ -46,7 +44,7 @@ AlgoKit development is done within the [AlgoKit Guiding Principles](./docs/algok 2. Hit Shift+F9 (or whatever you have debug mapped to) and it should start running with breakpoint debugging - Other 1. Open the repository root in your text editor of choice - 2. In a terminal run `poetry shell` + 2. In a terminal run `uv run python` or activate the venv with `source .venv/bin/activate` 3. Run `./debug.py` through your debugger of choice - In each of the above cases, an `args.in` file will be created in the source root. Each line will be executed in order, with the arguments passed to the cli. @@ -62,7 +60,7 @@ AlgoKit development is done within the [AlgoKit Guiding Principles](./docs/algok ### Subsequently -1. If you update to the latest source code and there are new dependencies you will need to run `poetry install` again +1. If you update to the latest source code and there are new dependencies you will need to run `uv sync` again 2. Follow step 3 above ### Documentation @@ -71,8 +69,8 @@ Markdown documentation can be found within the docs directory of the repo, there To autogenerate the CLI documentation from the click source: -1. Install the docs dependencies: `poetry install --with docs` -2. Run the docs generation: `poetry run poe docs` +1. Install the docs dependencies: `uv sync --group docs` +2. Run the docs generation: `uv run poe docs` Note: this command won't work on Windows. @@ -82,11 +80,9 @@ The CLI docs are generated using Sphinx, and its configuration can be found in ` AlgoKit uses Python as a main language and many Python libraries and tools. This section lists all of them with a tiny brief. -- [Poetry](https://python-poetry.org/): Python packaging and dependency management. -- [pipx](https://github.com/pypa/pipx): Install and Run Python Applications in Isolated Environments +- [uv](https://docs.astral.sh/uv/): Python packaging, dependency management, and tool installation. - [Click](https://palletsprojects.com/p/click/): A Python package for creating beautiful command line interfaces. -- [Black](https://github.com/psf/black): A Python code formatter. -- [Tox](https://tox.wiki/en/latest/): Automate and standardize testing in Python. +- [Ruff](https://docs.astral.sh/ruff/): An extremely fast Python linter and formatter. ## Architecture decisions diff --git a/README.md b/README.md index d2a5079f4..0fd4f5987 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@
- +

@@ -85,46 +85,65 @@ This is an open source project managed by the Algorand Foundation. See the [cont ## Prerequisites -The installation pre-requisites change depending on the method you use to install. Please refer to [Installation Methods](#installation-methods). +No prerequisites are required to install AlgoKit itself. The install script handles everything. Depending on the features you choose to leverage from the AlgoKit CLI, additional dependencies may be required. The AlgoKit CLI will tell you if you are missing one for a given command. These optional dependencies are: - **Git**: Essential for creating and updating projects from templates. Installation guide available at [Git Installation](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). - **Docker**: Necessary for running the AlgoKit LocalNet environment. Docker Compose version 2.5.0 or higher is required. See [Docker Installation](https://docs.docker.com/get-docker/). -- **Python**: For those installing the AlgoKit CLI via `pipx` or building contracts using Algorand Python. **Minimum required version is Python 3.12+ when working with Algorand Python**. See [Python Installation](https://www.python.org/downloads/). - **Node.js**: For those working on frontend templates or building contracts using Algorand TypeScript or TEALScript. **Minimum required versions are Node.js `v22` and npm `v10`**. See [Node.js Installation](https://nodejs.org/en/download/). -> **Note** -> If you have previously installed AlgoKit using `pipx` and would like to switch to a different installation method, please ensure that -> you first uninstall the existing version by running `pipx uninstall algokit`. Once uninstalled, you can follow the installation instructions for your preferred platform. +## Quick Install (Recommended) + +AlgoKit is installed via [uv](https://docs.astral.sh/uv/), which handles Python and dependency management automatically. + +### macOS / Linux + +```shell +curl -fsSL https://raw.githubusercontent.com/algorandfoundation/algokit-cli/decoupling/scripts/install/install.sh | bash +``` + +### Windows (PowerShell) + +```powershell +irm https://raw.githubusercontent.com/algorandfoundation/algokit-cli/decoupling/scripts/install/install.ps1 | iex +``` + +### What the installer does + +1. Installs [uv](https://docs.astral.sh/uv/) if not already present +2. Installs Python 3.12 via uv if not already available +3. Installs AlgoKit via `uv tool install algokit` + +### Maintenance -## Cross-platform installation +- To update AlgoKit: `uv tool upgrade algokit` +- To remove AlgoKit: `uv tool uninstall algokit` -AlgoKit can be installed using OS specific package managers, or using the python tool [pipx](https://pypa.github.io/pipx/). -See below for specific installation instructions. +## Alternative: Install with uv directly -### Installation Methods +If you already have [uv](https://docs.astral.sh/uv/) installed: -- [Windows](#install-algokit-on-windows) -- [Mac](#install-algokit-on-mac) -- [Linux](#install-algokit-on-linux) -- [Universal via pipx](#install-algokit-with-pipx-on-any-os) +```shell +uv tool install algokit +``` -## Install AlgoKit on Windows +## Legacy Installation Methods > **Note** -> AlgoKit is supported on Windows 10 1709 (build 16299) and later. -> We only publish an x64 binary, however it also runs on ARM devices by default using the built in x64 emulation feature. +> The following installation methods are being phased out in favor of the uv-based installation above. +> They will continue to work for existing installations but are no longer the recommended approach. -1. Ensure prerequisites are installed +

+Click to expand legacy installation methods + +### Install AlgoKit on Windows (winget) +1. Ensure prerequisites are installed - [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget/) (should be installed by default on recent Windows 10 or later) - [Git](https://github.com/git-guides/install-git#install-git-on-windows) (or `winget install git.git`) - [Docker](https://docs.docker.com/desktop/install/windows-install/) (or `winget install docker.dockerdesktop`) - > **Note** - > See [our LocalNet documentation](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/localnet.md#prerequisites) for more tips on installing Docker on Windows - - [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) 2. Install using winget @@ -132,27 +151,12 @@ See below for specific installation instructions. winget install algokit ``` -3. [Verify installation](#verify-installation) - -### Maintenance - -Some useful commands for updating or removing AlgoKit in the future. - -- To update AlgoKit: `winget upgrade algokit` -- To remove AlgoKit: `winget uninstall algokit` - -## Install AlgoKit on Mac - -> **Note** -> AlgoKit is supported on macOS Big Sur (11) and later for both x64 and ARM (Apple Silicon) +### Install AlgoKit on Mac (Homebrew) 1. Ensure prerequisites are installed - - [Homebrew](https://docs.brew.sh/Installation) - [Git](https://github.com/git-guides/install-git#install-git-on-mac) (should already be available if `brew` is installed) - [Docker](https://docs.docker.com/desktop/install/mac-install/), (or `brew install --cask docker`) - > **Note** - > Docker requires MacOS 11+ 2. Install using Homebrew @@ -160,24 +164,10 @@ Some useful commands for updating or removing AlgoKit in the future. brew install algorandfoundation/tap/algokit ``` -3. Restart the terminal to ensure AlgoKit is available on the path -4. [Verify installation](#verify-installation) - -### Maintenance - -Some useful commands for updating or removing AlgoKit in the future. - -- To update AlgoKit: `brew upgrade algokit` -- To remove AlgoKit: `brew uninstall algokit` - -## Install AlgoKit on Linux - -> **Note** -> AlgoKit is compatible with Ubuntu 16.04 and later, Debian, RedHat, and any distribution that supports [Snap](https://snapcraft.io/docs/installing-snapd), but it is only supported on x64 architecture; ARM is not supported. +### Install AlgoKit on Linux (snap) 1. Ensure prerequisites are installed - - - [Snap](https://snapcraft.io/docs/installing-snapd) (should be installed by default on Ubuntu 16.04.4 LTS (Xenial Xerus) or later) + - [Snap](https://snapcraft.io/docs/installing-snapd) - [Git](https://github.com/git-guides/install-git#install-git-on-linux) - [Docker](https://docs.docker.com/desktop/install/linux-install/) @@ -187,21 +177,9 @@ Some useful commands for updating or removing AlgoKit in the future. sudo snap install algokit --classic ``` - > For detailed guidelines per each supported linux distro, refer to [Snap Store](https://snapcraft.io/algokit). - -3. [Verify installation](#verify-installation) - -### Maintenance - -Some useful commands for updating or removing AlgoKit in the future. - -- To update AlgoKit: `snap refresh algokit` -- To remove AlgoKit: `snap remove --purge algokit` - -## Install AlgoKit with pipx on any OS +### Install AlgoKit with pipx on any OS 1. Ensure desired prerequisites are installed - - [Python 3.10 - 3.14](https://www.python.org/downloads/) - [pipx](https://pypa.github.io/pipx/installation/) - [Git](https://github.com/git-guides/install-git) @@ -213,62 +191,30 @@ Some useful commands for updating or removing AlgoKit in the future. pipx install algokit ``` -3. Restart the terminal to ensure AlgoKit is available on the path -4. [Verify installation](#verify-installation) - -### Maintenance - -Some useful commands for updating or removing AlgoKit in the future. - -- To update AlgoKit: `pipx upgrade algokit` -- To remove AlgoKit: `pipx uninstall algokit` +
## Verify installation Verify AlgoKit is installed correctly by running `algokit --version` and you should see output similar to: ``` -algokit, version 1.0.1 +algokit, version 2.10.2 ``` > **Note** -> If you get receive one of the following errors: +> If you receive one of the following errors: > > - `command not found: algokit` (bash/zsh) > - `The term 'algokit' is not recognized as the name of a cmdlet, function, script file, or operable program.` (PowerShell) > -> Then ensure that `algokit` is available on the PATH by running `pipx ensurepath` and restarting the terminal. - -It is also recommended that you run `algokit doctor` to verify there are no issues in your local environment and to diagnose any problems if you do have difficulties running AlgoKit. The output of this command will look similar to: - -``` -timestamp: 2023-03-27T01:23:45+00:00 -AlgoKit: 1.0.1 -AlgoKit Python: 3.11.1 (main, Dec 23 2022, 09:28:24) [Clang 14.0.0 (clang-1400.0.29.202)] (location: /Users/algokit/.local/pipx/venvs/algokit) -OS: macOS-13.1-arm64-arm-64bit -docker: 20.10.21 -docker compose: 2.13.0 -git: 2.37.1 -python: 3.10.9 (location: /opt/homebrew/bin/python) -python3: 3.10.9 (location: /opt/homebrew/bin/python3) -pipx: 1.1.0 -poetry: 1.3.2 -node: 18.12.1 -npm: 8.19.2 -brew: 3.6.18 - -If you are experiencing a problem with AlgoKit, feel free to submit an issue via: -https://github.com/algorandfoundation/algokit-cli/issues/new -Please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` -``` +> Ensure that `~/.local/bin` is on your PATH and restart the terminal. -Per the above output, the doctor command output is a helpful tool if you need to ask for support or [raise an issue](https://github.com/algorandfoundation/algokit-cli/issues/new). +It is also recommended that you run `algokit doctor` to verify there are no issues in your local environment and to diagnose any problems if you do have difficulties running AlgoKit. ## Troubleshooting This section addresses specific edge cases and issues that some users might encounter when interacting with the CLI. The following table provides solutions to known edge cases: -| Issue Description | OS(s) with observed behaviour | Steps to mitigate | References | -| --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | -| This scenario may arise if installed `python` was build without `--with-ssl` flag enabled, causing pip to fail when trying to install dependencies. | Debian 12 | Run `sudo apt-get install -y libssl-dev` to install the required openssl dependency. Afterwards, ensure to reinstall python with `--with-ssl` flag enabled. This includes options like [building python from source code](https://medium.com/@enahwe/how-to-06bc8a042345) or using tools like [pyenv](https://github.com/pyenv/pyenv). | | -| `poetry install` invoked directly or via `algokit project bootstrap all` fails on `Could NOT find PkgConfig (missing: PKG_CONFIG_EXECUTABLE)`. | `MacOS` >=14 using `python` 3.13 installed via `homebrew` | Install dependencies deprecated in `3.13` and latest MacOS versions via `brew install pkg-config`, delete the virtual environment folder and retry the `poetry install` command invocation. | N/A | +| Issue Description | OS(s) with observed behaviour | Steps to mitigate | References | +| --------------------------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | +| Python was built without `--with-ssl` flag, causing pip to fail | Debian 12 | Run `sudo apt-get install -y libssl-dev` and reinstall python with `--with-ssl` flag enabled | [setup-python#93](https://github.com/actions/setup-python/issues/93) | diff --git a/debug.py b/debug.py index c9ae7f171..8036f537b 100644 --- a/debug.py +++ b/debug.py @@ -12,7 +12,7 @@ import click except ImportError: print( # noqa: T201 - "ERROR: Couldn't import click, make sure you've run 'poetry install' and activated the virtual environment.\n" + "ERROR: Couldn't import click, make sure you've run 'uv sync' and activated the virtual environment.\n" "For tips on getting started with developing AlgoKit CLI itself see CONTRIBUTING.md.\n", file=sys.stderr, ) diff --git a/docs/features/compile.md b/docs/features/compile.md index e339a7cb5..90b3a5c49 100644 --- a/docs/features/compile.md +++ b/docs/features/compile.md @@ -83,7 +83,7 @@ Any errors detected by PuyaPy during the compilation process will be printed to PuyaPy requires Python 3.12+, so please ensure your Python version satisfies this requirement. -This command will attempt to resolve a matching installed PuyaPy compiler, either globally installed in the system or locally installed in your project (via [Poetry](https://python-poetry.org/)). If no appropriate match is found, the PuyaPy compiler will be dynamically run using [pipx](https://pipx.pypa.io/stable/). In this case pipx is also required. +This command will attempt to resolve a matching installed PuyaPy compiler, either globally installed in the system or locally installed in your project (via [uv](https://docs.astral.sh/uv/) or [Poetry](https://python-poetry.org/)). If no appropriate match is found, the PuyaPy compiler will be dynamically run using [uv](https://docs.astral.sh/uv/) (or [pipx](https://pipx.pypa.io/stable/) as a fallback). #### Examples diff --git a/docs/features/doctor.md b/docs/features/doctor.md index da4dfb241..bd002ea64 100644 --- a/docs/features/doctor.md +++ b/docs/features/doctor.md @@ -8,7 +8,7 @@ The AlgoKit Doctor allows you to make sure that your system has the correct depe Please run this command to if you are facing an issue running AlgoKit. It is recommended to run it before [submitting an issue to AlgoKit](https://github.com/algorandfoundation/algokit-cli/issues/new). You can copy the contents of the Doctor command message (in Markdown format) to your clipboard by providing the `-c` flag to the command as follows `algokit doctor -c`. -> NOTE: You can also use the `--verbose` or `-v` flag to show additional information including package dependencies of the AlgoKit CLI: `algokit -v doctor`. This only works when `algokit` is installed as a Python package (e.g., via `pipx install algokit`). +> NOTE: You can also use the `--verbose` or `-v` flag to show additional information including package dependencies of the AlgoKit CLI: `algokit -v doctor`. This only works when `algokit` is installed as a Python package (e.g., via `uv tool install algokit`). # Examples @@ -17,19 +17,17 @@ For example, running `algokit doctor` with all prerequisites installed will resu ``` $ ~ algokit doctor timestamp: 2023-03-29T03:58:05+00:00 -AlgoKit: 0.6.0 -AlgoKit Python: 3.11.2 (main, Mar 24 2023, 00:16:47) [Clang 14.0.0 (clang-1400.0.29.202)] (location: /Users/algokit/.local/pipx/venvs/algokit) -OS: macOS-13.2.1-arm64-arm-64bit -docker: 20.10.22 -docker compose: 2.15.1 -git: 2.39.1 -python: 3.10.9 (location: /Users/algokit/.asdf/shims/python) -python3: 3.10.9 (location: /Users/algokit/.asdf/shims/python3) -pipx: 1.2.0 -poetry: 1.3.2 -node: 18.12.1 -npm: 8.19.2 -brew: 4.0.10-34-gb753315 +AlgoKit: 2.10.2 +AlgoKit Python: 3.12.11 (location: ~/.local/share/uv/tools/algokit) +OS: macOS-15.0-arm64-arm-64bit +docker: 27.5.1 +docker compose: 2.32.4 +git: 2.47.0 +python: 3.12.11 (location: ~/.local/share/uv/python/cpython-3.12.11) +python3: 3.12.11 (location: ~/.local/share/uv/python/cpython-3.12.11) +uv: 0.10.7 +node: 22.14.0 +npm: 10.9.2 If you are experiencing a problem with AlgoKit, feel free to submit an issue via: https://github.com/algorandfoundation/algokit-cli/issues/new diff --git a/docs/features/generate.md b/docs/features/generate.md index aba6ff883..0a94f97d0 100644 --- a/docs/features/generate.md +++ b/docs/features/generate.md @@ -8,7 +8,7 @@ The `algokit generate client` [command](../cli/index.md#client) can be used to g ### Prerequisites -To generate Python clients an installation of pip and pipx is required. +To generate Python clients an installation of Python and uv (or pipx) is required. To generate TypeScript clients an installation of Node.js and npx is also required. Each generated client will also have a dependency on `algokit-utils` libraries for the target language. @@ -33,7 +33,7 @@ If you want to ensure typed client output stability across different environment To make use of this feature, pass `-v`, `--version`, for example `algokit generate client --version 1.2.3 path/to/application.json`. -Alternatively, you can achieve output stability by installing the underlying [Python](https://github.com/algorandfoundation/algokit-client-generator-py) or [TypeScript](https://github.com/algorandfoundation/algokit-client-generator-ts) client generator package either locally in your project (via `poetry` or `npm` respectively) or globally on your system (via `pipx` or `npm` respectively). AlgoKit will search for a matching installed version before dynamically resolving. +Alternatively, you can achieve output stability by installing the underlying [Python](https://github.com/algorandfoundation/algokit-client-generator-py) or [TypeScript](https://github.com/algorandfoundation/algokit-client-generator-ts) client generator package either locally in your project (via `uv` or `npm` respectively) or globally on your system (via `uv tool` or `npm` respectively). AlgoKit will search for a matching installed version before dynamically resolving. ### Usage diff --git a/docs/tutorials/intro.md b/docs/tutorials/intro.md index accee6658..509227999 100644 --- a/docs/tutorials/intro.md +++ b/docs/tutorials/intro.md @@ -18,25 +18,22 @@ This guide presents installing AlgoKit using an OS agnostic procedure. For OS sp Before proceeding, ensure you have the following components installed: -- [Python 3.10 - 3.14](https://www.python.org/downloads/) -- [pipx](https://pypa.github.io/pipx/#on-linux-install-via-pip-requires-pip-190-or-later) - [git](https://github.com/git-guides/install-git#install-git) - [Docker](https://docs.docker.com/desktop/install/mac-install/) (or [Podman](https://podman.io/getting-started/installation/), see [details](../features/localnet.md#podman-support)) - [VSCode](https://code.visualstudio.com/download) - ## Install AlgoKit 🛠 To install AlgoKit, run the following command from a terminal. ```shell -pipx install algokit +curl -fsSL https://raw.githubusercontent.com/algorandfoundation/algokit-cli/main/scripts/install/install.sh | bash ``` After the installation completes, **restart the terminal**. For more detailed installation documentation, see the [official installation guide](https://github.com/algorandfoundation/algokit-cli#install). -> Please note, `pipx` is only one of the supported installation methods. You can also install AlgoKit via `brew` and _soon_ `winget` and `snap` as pre-build binaries. Refer to the official installation guide. +> The install script handles installing `uv` and Python automatically. For alternative installation methods, see the [official installation guide](https://github.com/algorandfoundation/algokit-cli#install). ## Verify the Installation ✔ @@ -100,8 +97,7 @@ The structure of your fresh algokit project instance will look similar to below: ├── README.md # Quick start on Algorand Python smart contract template based project. ├── .algokit # Hidden folder for AlgoKit AVM debugger and custom generators. ├── .algokit.toml # Project-specific commands and custom generator references. - ├── poetry.lock - ├── poetry.toml # Dependency definitions for {your_project_name}. + ├── pyproject.toml # Dependency definitions for {your_project_name}. ├── pyproject.toml # Project definitions for {your_project_name}. └── smart_contracts ├── README.md # Guide for adding new smart contracts. diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index 616f6583d..000000000 --- a/poetry.lock +++ /dev/null @@ -1,3475 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. - -[[package]] -name = "alabaster" -version = "0.7.16" -description = "A light, configurable Sphinx theme" -optional = false -python-versions = ">=3.9" -groups = ["dev", "docs"] -files = [ - {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, - {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, -] - -[[package]] -name = "algokit-utils" -version = "5.0.0a7" -description = "Utilities for Algorand development for use by AlgoKit" -optional = false -python-versions = "<4,>=3.10" -groups = ["main"] -files = [ - {file = "algokit_utils-5.0.0a7-py3-none-any.whl", hash = "sha256:e409dd838e6d29aca978fe91ced43e7f94d2120ab7025eb7ccf548d2849589e1"}, - {file = "algokit_utils-5.0.0a7.tar.gz", hash = "sha256:97212bfdf2854de7e41f8e9ec2da7194a352c90c527e1ca4a11493721b60d8aa"}, -] - -[package.dependencies] -httpx = ">=0.23.1,<=0.28.1" -msgpack = ">=1.0.0,<2" -msgpack-types = ">=0.2.0,<=0.5.0" -pycryptodomex = ">=3.19,<4" -pynacl = ">=1.4.0,<2" -typing-extensions = ">=4.6.0" - -[[package]] -name = "allpairspy" -version = "2.5.1" -description = "Pairwise test combinations generator" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "allpairspy-2.5.1-py3-none-any.whl", hash = "sha256:3f97cbac2bbee86f4bfceffd0fd91dca740a120c78e9368af2bad81a2b3426e2"}, - {file = "allpairspy-2.5.1.tar.gz", hash = "sha256:f69d31a3b56eee119d1ec6063e9c732dd44fbba352ef738cb22d9699fc4009fe"}, -] - -[package.extras] -test = ["pytest (>=6.0.1)", "pytest-md-report (>=0.3)"] - -[[package]] -name = "altgraph" -version = "0.17.4" -description = "Python graph (network) package" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff"}, - {file = "altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406"}, -] - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "anyio" -version = "4.9.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -files = [ - {file = "anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"}, - {file = "anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028"}, -] - -[package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} -idna = ">=2.8" -sniffio = ">=1.1" -typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} - -[package.extras] -doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] -trio = ["trio (>=0.26.1)"] - -[[package]] -name = "approval-utilities" -version = "7.4.0" -description = "Utilities for your production code that work well with approvaltests" -optional = false -python-versions = ">=3.6.1" -groups = ["dev"] -files = [ - {file = "approval_utilities-7.4.0-py3-none-any.whl", hash = "sha256:d11f545ad318f3520e997657aaeb6511521a4d0b647a0868037ca817af7c73b3"}, - {file = "approval_utilities-7.4.0.tar.gz", hash = "sha256:8e0b146716db2f7d95d01726947438904760a6cb005aa391cee6f7a623d627ee"}, -] - -[[package]] -name = "approvaltests" -version = "7.4.0" -description = "Assertion/verification library to aid testing" -optional = false -python-versions = ">=3.6.1" -groups = ["dev"] -files = [ - {file = "approvaltests-7.4.0-py3-none-any.whl", hash = "sha256:64e8798f843f44ffd047935f18e8ec850caf9d4f924b9b24456008102cbb6aca"}, - {file = "approvaltests-7.4.0.tar.gz", hash = "sha256:e09b2f2af6cd049d71a3dcdc7b3bb4c2cd887cc5eb4b1294b557675360c5f90d"}, -] - -[package.dependencies] -allpairspy = ">=2.1.0" -approval-utilities = "7.4.0" -beautifulsoup4 = ">=4.4.0" -empty-files = ">=0.0.3" -mrjob = ">=0.7.4" -pyperclip = ">=1.5.29" -pytest = ">=4.0.0" -typing-extensions = ">=3.6.2" - -[[package]] -name = "babel" -version = "2.17.0" -description = "Internationalization utilities" -optional = false -python-versions = ">=3.8" -groups = ["dev", "docs"] -files = [ - {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"}, - {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, -] - -[package.extras] -dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] - -[[package]] -name = "backports-tarfile" -version = "1.2.0" -description = "Backport of CPython tarfile module" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -markers = "python_version < \"3.12\"" -files = [ - {file = "backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34"}, - {file = "backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["jaraco.test", "pytest (!=8.0.*)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)"] - -[[package]] -name = "bases" -version = "0.3.0" -description = "Python library for general Base-N encodings." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "bases-0.3.0-py3-none-any.whl", hash = "sha256:a2fef3366f3e522ff473d2e95c21523fe8e44251038d5c6150c01481585ebf5b"}, - {file = "bases-0.3.0.tar.gz", hash = "sha256:70f04a4a45d63245787f9e89095ca11042685b6b64b542ad916575ba3ccd1570"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0" -typing-validation = ">=1.1.0" - -[package.extras] -dev = ["base58", "mypy", "pylint", "pytest", "pytest-cov"] - -[[package]] -name = "beautifulsoup4" -version = "4.13.4" -description = "Screen-scraping library" -optional = false -python-versions = ">=3.7.0" -groups = ["dev"] -files = [ - {file = "beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b"}, - {file = "beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195"}, -] - -[package.dependencies] -soupsieve = ">1.2" -typing-extensions = ">=4.0.0" - -[package.extras] -cchardet = ["cchardet"] -chardet = ["chardet"] -charset-normalizer = ["charset-normalizer"] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "boolean-py" -version = "5.0" -description = "Define boolean algebras, create and parse boolean expressions and create custom boolean DSL." -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "boolean_py-5.0-py3-none-any.whl", hash = "sha256:ef28a70bd43115208441b53a045d1549e2f0ec6e3d08a9d142cbc41c1938e8d9"}, - {file = "boolean_py-5.0.tar.gz", hash = "sha256:60cbc4bad079753721d32649545505362c754e121570ada4658b852a3a318d95"}, -] - -[package.extras] -dev = ["build", "twine"] -docs = ["Sphinx (>=3.3.1)", "doc8 (>=0.8.1)", "sphinx-rtd-theme (>=0.5.0)", "sphinxcontrib-apidoc (>=0.3.0)"] -linting = ["black", "isort", "pycodestyle"] -testing = ["pytest (>=6,!=7.0.0)", "pytest-xdist (>=2)"] - -[[package]] -name = "cachecontrol" -version = "0.14.3" -description = "httplib2 caching for requests" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "cachecontrol-0.14.3-py3-none-any.whl", hash = "sha256:b35e44a3113f17d2a31c1e6b27b9de6d4405f84ae51baa8c1d3cc5b633010cae"}, - {file = "cachecontrol-0.14.3.tar.gz", hash = "sha256:73e7efec4b06b20d9267b441c1f733664f989fb8688391b670ca812d70795d11"}, -] - -[package.dependencies] -filelock = {version = ">=3.8.0", optional = true, markers = "extra == \"filecache\""} -msgpack = ">=0.5.2,<2.0.0" -requests = ">=2.16.0" - -[package.extras] -dev = ["CacheControl[filecache,redis]", "build", "cherrypy", "codespell[tomli]", "furo", "mypy", "pytest", "pytest-cov", "ruff", "sphinx", "sphinx-copybutton", "tox", "types-redis", "types-requests"] -filecache = ["filelock (>=3.8.0)"] -redis = ["redis (>=2.10.5)"] - -[[package]] -name = "certifi" -version = "2025.4.26" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -groups = ["main", "dev", "docs"] -files = [ - {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"}, - {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"}, -] - -[[package]] -name = "cffi" -version = "2.0.0" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -markers = "platform_python_implementation != \"PyPy\"" -files = [ - {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, - {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb"}, - {file = "cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a"}, - {file = "cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739"}, - {file = "cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe"}, - {file = "cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743"}, - {file = "cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5"}, - {file = "cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5"}, - {file = "cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d"}, - {file = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"}, - {file = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"}, - {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"}, - {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"}, - {file = "cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"}, - {file = "cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"}, - {file = "cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"}, - {file = "cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb"}, - {file = "cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26"}, - {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c"}, - {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b"}, - {file = "cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27"}, - {file = "cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75"}, - {file = "cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91"}, - {file = "cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5"}, - {file = "cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775"}, - {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205"}, - {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1"}, - {file = "cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f"}, - {file = "cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25"}, - {file = "cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad"}, - {file = "cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9"}, - {file = "cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592"}, - {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512"}, - {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4"}, - {file = "cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e"}, - {file = "cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6"}, - {file = "cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9"}, - {file = "cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf"}, - {file = "cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322"}, - {file = "cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a"}, - {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, - {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, -] - -[package.dependencies] -pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} - -[[package]] -name = "cfgv" -version = "3.4.0" -description = "Validate configuration and produce human readable error messages." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, - {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.4.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7" -groups = ["main", "dev", "docs"] -files = [ - {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-win32.whl", hash = "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"}, - {file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"}, - {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"}, -] - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "click-log" -version = "0.4.0" -description = "Logging integration for Click" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "click-log-0.4.0.tar.gz", hash = "sha256:3970f8570ac54491237bcdb3d8ab5e3eef6c057df29f8c3d1151a51a9c23b975"}, - {file = "click_log-0.4.0-py2.py3-none-any.whl", hash = "sha256:a43e394b528d52112af599f2fc9e4b7cf3c15f94e53581f74fa6867e68c91756"}, -] - -[package.dependencies] -click = "*" - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev", "docs"] -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -markers = {docs = "sys_platform == \"win32\""} - -[[package]] -name = "copier" -version = "9.11.3" -description = "A library for rendering project templates." -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "copier-9.11.3-py3-none-any.whl", hash = "sha256:ab4bc7e2944edc030b4c14ec84fffd6bf810b9b8fd56938e8ccbab1b169ea6ca"}, - {file = "copier-9.11.3.tar.gz", hash = "sha256:f4da98c7f3dd2243480433541b3b4d9daa788bce13b7b6d43c0c6d84bd50e889"}, -] - -[package.dependencies] -colorama = ">=0.4.6" -dunamai = ">=1.7.0" -funcy = ">=1.17" -jinja2 = ">=3.1.5" -jinja2-ansible-filters = ">=1.3.1" -packaging = ">=23.0" -pathspec = ">=0.9.0" -platformdirs = ">=4.3.6" -plumbum = ">=1.6.9" -pydantic = ">=2.4.2" -pygments = ">=2.7.1" -pyyaml = ">=5.3.1" -questionary = ">=1.8.1" -typing-extensions = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} - -[[package]] -name = "coverage" -version = "7.8.0" -description = "Code coverage measurement for Python" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "coverage-7.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2931f66991175369859b5fd58529cd4b73582461877ecfd859b6549869287ffe"}, - {file = "coverage-7.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52a523153c568d2c0ef8826f6cc23031dc86cffb8c6aeab92c4ff776e7951b28"}, - {file = "coverage-7.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c8a5c139aae4c35cbd7cadca1df02ea8cf28a911534fc1b0456acb0b14234f3"}, - {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a26c0c795c3e0b63ec7da6efded5f0bc856d7c0b24b2ac84b4d1d7bc578d676"}, - {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821f7bcbaa84318287115d54becb1915eece6918136c6f91045bb84e2f88739d"}, - {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a321c61477ff8ee705b8a5fed370b5710c56b3a52d17b983d9215861e37b642a"}, - {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ed2144b8a78f9d94d9515963ed273d620e07846acd5d4b0a642d4849e8d91a0c"}, - {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:042e7841a26498fff7a37d6fda770d17519982f5b7d8bf5278d140b67b61095f"}, - {file = "coverage-7.8.0-cp310-cp310-win32.whl", hash = "sha256:f9983d01d7705b2d1f7a95e10bbe4091fabc03a46881a256c2787637b087003f"}, - {file = "coverage-7.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a570cd9bd20b85d1a0d7b009aaf6c110b52b5755c17be6962f8ccd65d1dbd23"}, - {file = "coverage-7.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7ac22a0bb2c7c49f441f7a6d46c9c80d96e56f5a8bc6972529ed43c8b694e27"}, - {file = "coverage-7.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf13d564d310c156d1c8e53877baf2993fb3073b2fc9f69790ca6a732eb4bfea"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5761c70c017c1b0d21b0815a920ffb94a670c8d5d409d9b38857874c21f70d7"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ff52d790c7e1628241ffbcaeb33e07d14b007b6eb00a19320c7b8a7024c040"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d39fc4817fd67b3915256af5dda75fd4ee10621a3d484524487e33416c6f3543"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b44674870709017e4b4036e3d0d6c17f06a0e6d4436422e0ad29b882c40697d2"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f99eb72bf27cbb167b636eb1726f590c00e1ad375002230607a844d9e9a2318"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b571bf5341ba8c6bc02e0baeaf3b061ab993bf372d982ae509807e7f112554e9"}, - {file = "coverage-7.8.0-cp311-cp311-win32.whl", hash = "sha256:e75a2ad7b647fd8046d58c3132d7eaf31b12d8a53c0e4b21fa9c4d23d6ee6d3c"}, - {file = "coverage-7.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3043ba1c88b2139126fc72cb48574b90e2e0546d4c78b5299317f61b7f718b78"}, - {file = "coverage-7.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbb5cc845a0292e0c520656d19d7ce40e18d0e19b22cb3e0409135a575bf79fc"}, - {file = "coverage-7.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4dfd9a93db9e78666d178d4f08a5408aa3f2474ad4d0e0378ed5f2ef71640cb6"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f017a61399f13aa6d1039f75cd467be388d157cd81f1a119b9d9a68ba6f2830d"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0915742f4c82208ebf47a2b154a5334155ed9ef9fe6190674b8a46c2fb89cb05"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a40fcf208e021eb14b0fac6bdb045c0e0cab53105f93ba0d03fd934c956143a"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a1f406a8e0995d654b2ad87c62caf6befa767885301f3b8f6f73e6f3c31ec3a6"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77af0f6447a582fdc7de5e06fa3757a3ef87769fbb0fdbdeba78c23049140a47"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f2d32f95922927186c6dbc8bc60df0d186b6edb828d299ab10898ef3f40052fe"}, - {file = "coverage-7.8.0-cp312-cp312-win32.whl", hash = "sha256:769773614e676f9d8e8a0980dd7740f09a6ea386d0f383db6821df07d0f08545"}, - {file = "coverage-7.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5d2b9be5b0693cf21eb4ce0ec8d211efb43966f6657807f6859aab3814f946b"}, - {file = "coverage-7.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ac46d0c2dd5820ce93943a501ac5f6548ea81594777ca585bf002aa8854cacd"}, - {file = "coverage-7.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:771eb7587a0563ca5bb6f622b9ed7f9d07bd08900f7589b4febff05f469bea00"}, - {file = "coverage-7.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42421e04069fb2cbcbca5a696c4050b84a43b05392679d4068acbe65449b5c64"}, - {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554fec1199d93ab30adaa751db68acec2b41c5602ac944bb19187cb9a41a8067"}, - {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aaeb00761f985007b38cf463b1d160a14a22c34eb3f6a39d9ad6fc27cb73008"}, - {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:581a40c7b94921fffd6457ffe532259813fc68eb2bdda60fa8cc343414ce3733"}, - {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f319bae0321bc838e205bf9e5bc28f0a3165f30c203b610f17ab5552cff90323"}, - {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04bfec25a8ef1c5f41f5e7e5c842f6b615599ca8ba8391ec33a9290d9d2db3a3"}, - {file = "coverage-7.8.0-cp313-cp313-win32.whl", hash = "sha256:dd19608788b50eed889e13a5d71d832edc34fc9dfce606f66e8f9f917eef910d"}, - {file = "coverage-7.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:a9abbccd778d98e9c7e85038e35e91e67f5b520776781d9a1e2ee9d400869487"}, - {file = "coverage-7.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:18c5ae6d061ad5b3e7eef4363fb27a0576012a7447af48be6c75b88494c6cf25"}, - {file = "coverage-7.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:95aa6ae391a22bbbce1b77ddac846c98c5473de0372ba5c463480043a07bff42"}, - {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e013b07ba1c748dacc2a80e69a46286ff145935f260eb8c72df7185bf048f502"}, - {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d766a4f0e5aa1ba056ec3496243150698dc0481902e2b8559314368717be82b1"}, - {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad80e6b4a0c3cb6f10f29ae4c60e991f424e6b14219d46f1e7d442b938ee68a4"}, - {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b87eb6fc9e1bb8f98892a2458781348fa37e6925f35bb6ceb9d4afd54ba36c73"}, - {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d1ba00ae33be84066cfbe7361d4e04dec78445b2b88bdb734d0d1cbab916025a"}, - {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f3c38e4e5ccbdc9198aecc766cedbb134b2d89bf64533973678dfcf07effd883"}, - {file = "coverage-7.8.0-cp313-cp313t-win32.whl", hash = "sha256:379fe315e206b14e21db5240f89dc0774bdd3e25c3c58c2c733c99eca96f1ada"}, - {file = "coverage-7.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e4b6b87bb0c846a9315e3ab4be2d52fac905100565f4b92f02c445c8799e257"}, - {file = "coverage-7.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa260de59dfb143af06dcf30c2be0b200bed2a73737a8a59248fcb9fa601ef0f"}, - {file = "coverage-7.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:96121edfa4c2dfdda409877ea8608dd01de816a4dc4a0523356067b305e4e17a"}, - {file = "coverage-7.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8af63b9afa1031c0ef05b217faa598f3069148eeee6bb24b79da9012423b82"}, - {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89b1f4af0d4afe495cd4787a68e00f30f1d15939f550e869de90a86efa7e0814"}, - {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ec0be97723ae72d63d3aa41961a0b9a6f5a53ff599813c324548d18e3b9e8c"}, - {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a1d96e780bdb2d0cbb297325711701f7c0b6f89199a57f2049e90064c29f6bd"}, - {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f1d8a2a57b47142b10374902777e798784abf400a004b14f1b0b9eaf1e528ba4"}, - {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cf60dd2696b457b710dd40bf17ad269d5f5457b96442f7f85722bdb16fa6c899"}, - {file = "coverage-7.8.0-cp39-cp39-win32.whl", hash = "sha256:be945402e03de47ba1872cd5236395e0f4ad635526185a930735f66710e1bd3f"}, - {file = "coverage-7.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:90e7fbc6216ecaffa5a880cdc9c77b7418c1dcb166166b78dbc630d07f278cc3"}, - {file = "coverage-7.8.0-pp39.pp310.pp311-none-any.whl", hash = "sha256:b8194fb8e50d556d5849753de991d390c5a1edeeba50f68e3a9253fbd8bf8ccd"}, - {file = "coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7"}, - {file = "coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501"}, -] - -[package.dependencies] -tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} - -[package.extras] -toml = ["tomli ; python_full_version <= \"3.11.0a6\""] - -[[package]] -name = "cryptography" -version = "46.0.5" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = "!=3.9.0,!=3.9.1,>=3.8" -groups = ["main", "dev"] -files = [ - {file = "cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0"}, - {file = "cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731"}, - {file = "cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82"}, - {file = "cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1"}, - {file = "cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48"}, - {file = "cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4"}, - {file = "cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0"}, - {file = "cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663"}, - {file = "cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826"}, - {file = "cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d"}, - {file = "cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a"}, - {file = "cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4"}, - {file = "cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d"}, - {file = "cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c"}, - {file = "cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4"}, - {file = "cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9"}, - {file = "cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72"}, - {file = "cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257"}, - {file = "cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7"}, - {file = "cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d"}, -] - -[package.dependencies] -cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9.0\" and platform_python_implementation != \"PyPy\""} -typing-extensions = {version = ">=4.13.2", markers = "python_full_version < \"3.11.0\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"] -docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox[uv] (>=2024.4.15)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.14)", "ruff (>=0.11.11)"] -sdist = ["build (>=1.0.0)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==46.0.5)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] -test-randomorder = ["pytest-randomly"] - -[[package]] -name = "cyclonedx-python-lib" -version = "9.1.0" -description = "Python library for CycloneDX" -optional = false -python-versions = "<4.0,>=3.8" -groups = ["dev"] -files = [ - {file = "cyclonedx_python_lib-9.1.0-py3-none-any.whl", hash = "sha256:55693fca8edaecc3363b24af14e82cc6e659eb1e8353e58b587c42652ce0fb52"}, - {file = "cyclonedx_python_lib-9.1.0.tar.gz", hash = "sha256:86935f2c88a7b47a529b93c724dbd3e903bc573f6f8bd977628a7ca1b5dadea1"}, -] - -[package.dependencies] -license-expression = ">=30,<31" -packageurl-python = ">=0.11,<2" -py-serializable = ">=2.0.0,<3.0.0" -sortedcontainers = ">=2.4.0,<3.0.0" - -[package.extras] -json-validation = ["jsonschema[format] (>=4.18,<5.0)"] -validation = ["jsonschema[format] (>=4.18,<5.0)", "lxml (>=4,<6)"] -xml-validation = ["lxml (>=4,<6)"] - -[[package]] -name = "defusedxml" -version = "0.7.1" -description = "XML bomb protection for Python stdlib modules" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["dev"] -files = [ - {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, - {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, -] - -[[package]] -name = "distlib" -version = "0.3.9" -description = "Distribution utilities" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, - {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, -] - -[[package]] -name = "docutils" -version = "0.19" -description = "Docutils -- Python Documentation Utilities" -optional = false -python-versions = ">=3.7" -groups = ["dev", "docs"] -files = [ - {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"}, - {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, -] - -[[package]] -name = "dotty-dict" -version = "1.3.1" -description = "Dictionary wrapper for quick access to deeply nested keys." -optional = false -python-versions = ">=3.5,<4.0" -groups = ["dev"] -files = [ - {file = "dotty_dict-1.3.1-py3-none-any.whl", hash = "sha256:5022d234d9922f13aa711b4950372a06a6d64cb6d6db9ba43d0ba133ebfce31f"}, - {file = "dotty_dict-1.3.1.tar.gz", hash = "sha256:4b016e03b8ae265539757a53eba24b9bfda506fb94fbce0bee843c6f05541a15"}, -] - -[[package]] -name = "dunamai" -version = "1.24.1" -description = "Dynamic version generation" -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "dunamai-1.24.1-py3-none-any.whl", hash = "sha256:4370e406d8ce195fc4b066b5c326bfa9adb269c4b8719b4e4fd90b63a2144bf7"}, - {file = "dunamai-1.24.1.tar.gz", hash = "sha256:3aa3348f77242da8628b23f11e89569343440f0f912bcef32a1fa891cf8e7215"}, -] - -[package.dependencies] -packaging = ">=20.9" - -[[package]] -name = "empty-files" -version = "0.0.9" -description = "Serves empty files of many types" -optional = false -python-versions = ">=3.7.1" -groups = ["dev"] -files = [ - {file = "empty-files-0.0.9.tar.gz", hash = "sha256:22e74de327271ef9592a661aaa53bb1d5fa6cfd539dac7315625c8b30b7292ae"}, - {file = "empty_files-0.0.9-py3-none-any.whl", hash = "sha256:9af04feacd5858d1255a00e76926a2d760f6d05c3c5a8df58abd6be21da742c2"}, -] - -[package.dependencies] -requests = "*" - -[[package]] -name = "exceptiongroup" -version = "1.2.2" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -markers = "python_version == \"3.10\"" -files = [ - {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, - {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "execnet" -version = "2.1.1" -description = "execnet: rapid multi-Python deployment" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, - {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, -] - -[package.extras] -testing = ["hatch", "pre-commit", "pytest", "tox"] - -[[package]] -name = "filelock" -version = "3.18.0" -description = "A platform independent file lock." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de"}, - {file = "filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] -typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] - -[[package]] -name = "funcy" -version = "2.0" -description = "A fancy and practical functional tools" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "funcy-2.0-py2.py3-none-any.whl", hash = "sha256:53df23c8bb1651b12f095df764bfb057935d49537a56de211b098f4c79614bb0"}, - {file = "funcy-2.0.tar.gz", hash = "sha256:3963315d59d41c6f30c04bc910e10ab50a3ac4a225868bfa96feed133df075cb"}, -] - -[[package]] -name = "gfm-toc" -version = "0.0.7" -description = "Simple and customizable way to generate TOC for Github Markdown files." -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "gfm-toc-0.0.7.tar.gz", hash = "sha256:c53ed0e2cd400e89051377017ca98c11c9cef628b2effddf787db4fc19ff343d"}, - {file = "gfm_toc-0.0.7-py3-none-any.whl", hash = "sha256:247af7267a6cbbdd4213f8383157997bcb07e39e819db737bd2dbfbdb94ee7ae"}, -] - -[[package]] -name = "gitdb" -version = "4.0.12" -description = "Git Object Database" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, - {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.44" -description = "GitPython is a Python library used to interact with Git repositories" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, - {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" - -[package.extras] -doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] -test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] - -[[package]] -name = "h11" -version = "0.16.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, - {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, -] - -[[package]] -name = "html2text" -version = "2025.4.15" -description = "Turn HTML into equivalent Markdown-structured text." -optional = false -python-versions = ">=3.9" -groups = ["docs"] -files = [ - {file = "html2text-2025.4.15-py3-none-any.whl", hash = "sha256:00569167ffdab3d7767a4cdf589b7f57e777a5ed28d12907d8c58769ec734acc"}, - {file = "html2text-2025.4.15.tar.gz", hash = "sha256:948a645f8f0bc3abe7fd587019a2197a12436cd73d0d4908af95bfc8da337588"}, -] - -[[package]] -name = "httpcore" -version = "1.0.9" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, - {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, -] - -[package.dependencies] -certifi = "*" -h11 = ">=0.16" - -[package.extras] -asyncio = ["anyio (>=4.0,<5.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<1.0)"] - -[[package]] -name = "httpx" -version = "0.28.1" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, - {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, -] - -[package.dependencies] -anyio = "*" -certifi = "*" -httpcore = "==1.*" -idna = "*" - -[package.extras] -brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "identify" -version = "2.6.10" -description = "File identification library for Python" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "identify-2.6.10-py2.py3-none-any.whl", hash = "sha256:5f34248f54136beed1a7ba6a6b5c4b6cf21ff495aac7c359e1ef831ae3b8ab25"}, - {file = "identify-2.6.10.tar.gz", hash = "sha256:45e92fd704f3da71cc3880036633f48b4b7265fd4de2b57627cb157216eb7eb8"}, -] - -[package.extras] -license = ["ukkonen"] - -[[package]] -name = "idna" -version = "3.10" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -groups = ["main", "dev", "docs"] -files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, -] - -[package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "imagesize" -version = "1.4.1" -description = "Getting image size from png/jpeg/jpeg2000/gif file" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["dev", "docs"] -files = [ - {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, - {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, -] - -[[package]] -name = "importlib-metadata" -version = "8.7.0" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -files = [ - {file = "importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd"}, - {file = "importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000"}, -] -markers = {main = "python_version < \"3.12\""} - -[package.dependencies] -zipp = ">=3.20" - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -perf = ["ipython"] -test = ["flufl.flake8", "importlib_resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] -type = ["pytest-mypy"] - -[[package]] -name = "iniconfig" -version = "2.1.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, - {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, -] - -[[package]] -name = "invoke" -version = "2.2.0" -description = "Pythonic task execution" -optional = false -python-versions = ">=3.6" -groups = ["dev"] -files = [ - {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"}, - {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, -] - -[[package]] -name = "jaraco-classes" -version = "3.4.0" -description = "Utility functions for Python class constructs" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790"}, - {file = "jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd"}, -] - -[package.dependencies] -more-itertools = "*" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)"] - -[[package]] -name = "jaraco-context" -version = "6.1.0" -description = "Useful decorators and context managers" -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -files = [ - {file = "jaraco_context-6.1.0-py3-none-any.whl", hash = "sha256:a43b5ed85815223d0d3cfdb6d7ca0d2bc8946f28f30b6f3216bda070f68badda"}, - {file = "jaraco_context-6.1.0.tar.gz", hash = "sha256:129a341b0a85a7db7879e22acd66902fda67882db771754574338898b2d5d86f"}, -] - -[package.dependencies] -"backports.tarfile" = {version = "*", markers = "python_version < \"3.12\""} - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=3.4)"] -test = ["jaraco.test (>=5.6.0)", "portend", "pytest (>=6,!=8.1.*)"] -type = ["mypy (<1.19) ; platform_python_implementation == \"PyPy\"", "pytest-mypy (>=1.0.1)"] - -[[package]] -name = "jaraco-functools" -version = "4.1.0" -description = "Functools like those found in stdlib" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "jaraco.functools-4.1.0-py3-none-any.whl", hash = "sha256:ad159f13428bc4acbf5541ad6dec511f91573b90fba04df61dafa2a1231cf649"}, - {file = "jaraco_functools-4.1.0.tar.gz", hash = "sha256:70f7e0e2ae076498e212562325e805204fc092d7b4c17e0e86c959e249701a9d"}, -] - -[package.dependencies] -more-itertools = "*" - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["jaraco.classes", "pytest (>=6,!=8.1.*)"] -type = ["pytest-mypy"] - -[[package]] -name = "jeepney" -version = "0.9.0" -description = "Low-level, pure Python DBus protocol wrapper." -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -markers = "sys_platform == \"linux\"" -files = [ - {file = "jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683"}, - {file = "jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732"}, -] - -[package.extras] -test = ["async-timeout ; python_version < \"3.11\"", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"] -trio = ["trio"] - -[[package]] -name = "jinja2" -version = "3.1.6" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -groups = ["main", "dev", "docs"] -files = [ - {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, - {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "jinja2-ansible-filters" -version = "1.3.2" -description = "A port of Ansible's jinja2 filters without requiring ansible core." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "jinja2-ansible-filters-1.3.2.tar.gz", hash = "sha256:07c10cf44d7073f4f01102ca12d9a2dc31b41d47e4c61ed92ef6a6d2669b356b"}, - {file = "jinja2_ansible_filters-1.3.2-py3-none-any.whl", hash = "sha256:e1082f5564917649c76fed239117820610516ec10f87735d0338688800a55b34"}, -] - -[package.dependencies] -Jinja2 = "*" -PyYAML = "*" - -[package.extras] -test = ["pytest", "pytest-cov"] - -[[package]] -name = "jsondiff" -version = "2.2.1" -description = "Diff JSON and JSON-like structures in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "jsondiff-2.2.1-py3-none-any.whl", hash = "sha256:b1f0f7e2421881848b1d556d541ac01a91680cfcc14f51a9b62cdf4da0e56722"}, - {file = "jsondiff-2.2.1.tar.gz", hash = "sha256:658d162c8a86ba86de26303cd86a7b37e1b2c1ec98b569a60e2ca6180545f7fe"}, -] - -[package.dependencies] -pyyaml = "*" - -[package.extras] -dev = ["build", "hypothesis", "pytest", "setuptools-scm"] - -[[package]] -name = "keyring" -version = "25.6.0" -description = "Store and access your passwords safely." -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -files = [ - {file = "keyring-25.6.0-py3-none-any.whl", hash = "sha256:552a3f7af126ece7ed5c89753650eec89c7eaae8617d0aa4d9ad2b75111266bd"}, - {file = "keyring-25.6.0.tar.gz", hash = "sha256:0b39998aa941431eb3d9b0d4b2460bc773b9df6fed7621c2dfb291a7e0187a66"}, -] - -[package.dependencies] -importlib_metadata = {version = ">=4.11.4", markers = "python_version < \"3.12\""} -"jaraco.classes" = "*" -"jaraco.context" = "*" -"jaraco.functools" = "*" -jeepney = {version = ">=0.4.2", markers = "sys_platform == \"linux\""} -pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""} -SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] -completion = ["shtab (>=1.1.0)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["pyfakefs", "pytest (>=6,!=8.1.*)"] -type = ["pygobject-stubs", "pytest-mypy", "shtab", "types-pywin32"] - -[[package]] -name = "license-expression" -version = "30.4.1" -description = "license-expression is a comprehensive utility library to parse, compare, simplify and normalize license expressions (such as SPDX license expressions) using boolean logic." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "license_expression-30.4.1-py3-none-any.whl", hash = "sha256:679646bc3261a17690494a3e1cada446e5ee342dbd87dcfa4a0c24cc5dce13ee"}, - {file = "license_expression-30.4.1.tar.gz", hash = "sha256:9f02105f9e0fcecba6a85dfbbed7d94ea1c3a70cf23ddbfb5adf3438a6f6fce0"}, -] - -[package.dependencies] -"boolean.py" = ">=4.0" - -[package.extras] -docs = ["Sphinx (>=5.0.2)", "doc8 (>=0.11.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-reredirects (>=0.1.2)", "sphinx-rtd-dark-mode (>=1.3.0)", "sphinx-rtd-theme (>=1.0.0)", "sphinxcontrib-apidoc (>=0.4.0)"] -testing = ["black", "isort", "pytest (>=6,!=7.0.0)", "pytest-xdist (>=2)", "twine"] - -[[package]] -name = "linkify-it-py" -version = "2.0.3" -description = "Links recognition library with FULL unicode support." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "linkify-it-py-2.0.3.tar.gz", hash = "sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048"}, - {file = "linkify_it_py-2.0.3-py3-none-any.whl", hash = "sha256:6bcbc417b0ac14323382aef5c5192c0075bf8a9d6b41820a2b66371eac6b6d79"}, -] - -[package.dependencies] -uc-micro-py = "*" - -[package.extras] -benchmark = ["pytest", "pytest-benchmark"] -dev = ["black", "flake8", "isort", "pre-commit", "pyproject-flake8"] -doc = ["myst-parser", "sphinx", "sphinx-book-theme"] -test = ["coverage", "pytest", "pytest-cov"] - -[[package]] -name = "macholib" -version = "1.16.3" -description = "Mach-O header analysis and editing" -optional = false -python-versions = "*" -groups = ["dev"] -markers = "sys_platform == \"darwin\"" -files = [ - {file = "macholib-1.16.3-py2.py3-none-any.whl", hash = "sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c"}, - {file = "macholib-1.16.3.tar.gz", hash = "sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30"}, -] - -[package.dependencies] -altgraph = ">=0.17" - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, -] - -[package.dependencies] -linkify-it-py = {version = ">=1,<3", optional = true, markers = "extra == \"linkify\""} -mdit-py-plugins = {version = "*", optional = true, markers = "extra == \"plugins\""} -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "markupsafe" -version = "3.0.2" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.9" -groups = ["main", "dev", "docs"] -files = [ - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, - {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, -] - -[[package]] -name = "mdit-py-plugins" -version = "0.4.2" -description = "Collection of plugins for markdown-it-py" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636"}, - {file = "mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"}, -] - -[package.dependencies] -markdown-it-py = ">=1.0.0,<4.0.0" - -[package.extras] -code-style = ["pre-commit"] -rtd = ["myst-parser", "sphinx-book-theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - -[[package]] -name = "more-itertools" -version = "10.7.0" -description = "More routines for operating on iterables, beyond itertools" -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -files = [ - {file = "more_itertools-10.7.0-py3-none-any.whl", hash = "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e"}, - {file = "more_itertools-10.7.0.tar.gz", hash = "sha256:9fddd5403be01a94b204faadcff459ec3568cf110265d3c54323e1e866ad29d3"}, -] - -[[package]] -name = "mrjob" -version = "0.7.4" -description = "Python MapReduce framework" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "mrjob-0.7.4-py2.py3-none-any.whl", hash = "sha256:d8fa1bafcada0ffe3e7166896a27e996815e2cb835088aec025e3dd12c7146ce"}, - {file = "mrjob-0.7.4.tar.gz", hash = "sha256:2c8d8dc8aa4b354a97de18d0260f551f018693af74af104b3d41daf165eebdd4"}, -] - -[package.dependencies] -PyYAML = ">=3.10" - -[package.extras] -aws = ["boto3 (>=1.10.0)", "botocore (>=1.13.26)"] -google = ["google-cloud-dataproc (>=0.3.0,<=1.1.0)", "google-cloud-logging (>=1.9.0)", "google-cloud-storage (>=1.13.1)"] -rapidjson = ["python-rapidjson"] -simplejson = ["simplejson"] -ujson = ["ujson"] - -[[package]] -name = "msgpack" -version = "1.1.0" -description = "MessagePack serializer" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "msgpack-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd"}, - {file = "msgpack-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d"}, - {file = "msgpack-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5"}, - {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5"}, - {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e"}, - {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b"}, - {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f"}, - {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68"}, - {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b"}, - {file = "msgpack-1.1.0-cp310-cp310-win32.whl", hash = "sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044"}, - {file = "msgpack-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f"}, - {file = "msgpack-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7"}, - {file = "msgpack-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa"}, - {file = "msgpack-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701"}, - {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6"}, - {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59"}, - {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0"}, - {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e"}, - {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6"}, - {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5"}, - {file = "msgpack-1.1.0-cp311-cp311-win32.whl", hash = "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88"}, - {file = "msgpack-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788"}, - {file = "msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d"}, - {file = "msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2"}, - {file = "msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420"}, - {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2"}, - {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39"}, - {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f"}, - {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247"}, - {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c"}, - {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b"}, - {file = "msgpack-1.1.0-cp312-cp312-win32.whl", hash = "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b"}, - {file = "msgpack-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f"}, - {file = "msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf"}, - {file = "msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330"}, - {file = "msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734"}, - {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e"}, - {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca"}, - {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915"}, - {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d"}, - {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434"}, - {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c"}, - {file = "msgpack-1.1.0-cp313-cp313-win32.whl", hash = "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc"}, - {file = "msgpack-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f"}, - {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c40ffa9a15d74e05ba1fe2681ea33b9caffd886675412612d93ab17b58ea2fec"}, - {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1ba6136e650898082d9d5a5217d5906d1e138024f836ff48691784bbe1adf96"}, - {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0856a2b7e8dcb874be44fea031d22e5b3a19121be92a1e098f46068a11b0870"}, - {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:471e27a5787a2e3f974ba023f9e265a8c7cfd373632247deb225617e3100a3c7"}, - {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:646afc8102935a388ffc3914b336d22d1c2d6209c773f3eb5dd4d6d3b6f8c1cb"}, - {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:13599f8829cfbe0158f6456374e9eea9f44eee08076291771d8ae93eda56607f"}, - {file = "msgpack-1.1.0-cp38-cp38-win32.whl", hash = "sha256:8a84efb768fb968381e525eeeb3d92857e4985aacc39f3c47ffd00eb4509315b"}, - {file = "msgpack-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:879a7b7b0ad82481c52d3c7eb99bf6f0645dbdec5134a4bddbd16f3506947feb"}, - {file = "msgpack-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:53258eeb7a80fc46f62fd59c876957a2d0e15e6449a9e71842b6d24419d88ca1"}, - {file = "msgpack-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7e7b853bbc44fb03fbdba34feb4bd414322180135e2cb5164f20ce1c9795ee48"}, - {file = "msgpack-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3e9b4936df53b970513eac1758f3882c88658a220b58dcc1e39606dccaaf01c"}, - {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46c34e99110762a76e3911fc923222472c9d681f1094096ac4102c18319e6468"}, - {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a706d1e74dd3dea05cb54580d9bd8b2880e9264856ce5068027eed09680aa74"}, - {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:534480ee5690ab3cbed89d4c8971a5c631b69a8c0883ecfea96c19118510c846"}, - {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8cf9e8c3a2153934a23ac160cc4cba0ec035f6867c8013cc6077a79823370346"}, - {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3180065ec2abbe13a4ad37688b61b99d7f9e012a535b930e0e683ad6bc30155b"}, - {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5a91481a3cc573ac8c0d9aace09345d989dc4a0202b7fcb312c88c26d4e71a8"}, - {file = "msgpack-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f80bc7d47f76089633763f952e67f8214cb7b3ee6bfa489b3cb6a84cfac114cd"}, - {file = "msgpack-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:4d1b7ff2d6146e16e8bd665ac726a89c74163ef8cd39fa8c1087d4e52d3a2325"}, - {file = "msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e"}, -] - -[[package]] -name = "msgpack-types" -version = "0.5.0" -description = "Type stubs for msgpack" -optional = false -python-versions = "<4.0,>=3.8" -groups = ["main"] -files = [ - {file = "msgpack_types-0.5.0-py3-none-any.whl", hash = "sha256:8b633ed75e495a555fa0615843de559a74b1d176828d59bb393d266e51f6bda7"}, - {file = "msgpack_types-0.5.0.tar.gz", hash = "sha256:aebd1b8da23f8f9966d66ebb1a43bd261b95751c6a267bd21a124d2ccac84201"}, -] - -[package.dependencies] -msgpack = ">=1.1.0,<1.2.0" -typing-extensions = ">=4.6.0" - -[[package]] -name = "mslex" -version = "1.3.0" -description = "shlex for windows" -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "mslex-1.3.0-py3-none-any.whl", hash = "sha256:c7074b347201b3466fc077c5692fbce9b5f62a63a51f537a53fbbd02eff2eea4"}, - {file = "mslex-1.3.0.tar.gz", hash = "sha256:641c887d1d3db610eee2af37a8e5abda3f70b3006cdfd2d0d29dc0d1ae28a85d"}, -] - -[[package]] -name = "multiformats" -version = "0.3.1" -description = "Python implementation of multiformats protocols." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "multiformats-0.3.1-py3-none-any.whl", hash = "sha256:e194bae88004cb41ca8df83cd330d97e0a566c46db99e915831761cbf0a319a4"}, - {file = "multiformats-0.3.1.tar.gz", hash = "sha256:6b011e780d8283395c3062e16def6a61636ee265a3a8c94cc83d7a80293e70e5"}, -] - -[package.dependencies] -bases = ">=0.3.0" -multiformats-config = ">=0.3.0" -typing-extensions = ">=4.6.0" -typing-validation = ">=1.1.0" - -[package.extras] -dev = ["blake3", "mmh3", "mypy", "pycryptodomex", "pylint", "pyskein", "pytest", "pytest-cov", "rich"] -full = ["blake3", "mmh3", "pycryptodomex", "pyskein", "rich"] - -[[package]] -name = "multiformats-config" -version = "0.3.1" -description = "Pre-loading configuration module for the 'multiformats' package." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "multiformats-config-0.3.1.tar.gz", hash = "sha256:7eaa80ef5d9c5ee9b86612d21f93a087c4a655cbcb68960457e61adbc62b47a7"}, - {file = "multiformats_config-0.3.1-py3-none-any.whl", hash = "sha256:dec4c9d42ed0d9305889b67440f72e8e8d74b82b80abd7219667764b5b0a8e1d"}, -] - -[package.dependencies] -multiformats = "*" - -[package.extras] -dev = ["mypy", "pylint", "pytest", "pytest-cov"] - -[[package]] -name = "mypy" -version = "1.16.1" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a"}, - {file = "mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72"}, - {file = "mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea"}, - {file = "mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574"}, - {file = "mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d"}, - {file = "mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6"}, - {file = "mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc"}, - {file = "mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782"}, - {file = "mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507"}, - {file = "mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca"}, - {file = "mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4"}, - {file = "mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6"}, - {file = "mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d"}, - {file = "mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9"}, - {file = "mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79"}, - {file = "mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15"}, - {file = "mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd"}, - {file = "mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b"}, - {file = "mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438"}, - {file = "mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536"}, - {file = "mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f"}, - {file = "mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359"}, - {file = "mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be"}, - {file = "mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee"}, - {file = "mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069"}, - {file = "mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da"}, - {file = "mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c"}, - {file = "mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383"}, - {file = "mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40"}, - {file = "mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b"}, - {file = "mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37"}, - {file = "mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -pathspec = ">=0.9.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "nh3" -version = "0.2.21" -description = "Python binding to Ammonia HTML sanitizer Rust crate" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "nh3-0.2.21-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:fcff321bd60c6c5c9cb4ddf2554e22772bb41ebd93ad88171bbbb6f271255286"}, - {file = "nh3-0.2.21-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31eedcd7d08b0eae28ba47f43fd33a653b4cdb271d64f1aeda47001618348fde"}, - {file = "nh3-0.2.21-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d426d7be1a2f3d896950fe263332ed1662f6c78525b4520c8e9861f8d7f0d243"}, - {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9d67709bc0d7d1f5797b21db26e7a8b3d15d21c9c5f58ccfe48b5328483b685b"}, - {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:55823c5ea1f6b267a4fad5de39bc0524d49a47783e1fe094bcf9c537a37df251"}, - {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:818f2b6df3763e058efa9e69677b5a92f9bc0acff3295af5ed013da544250d5b"}, - {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b3b5c58161e08549904ac4abd450dacd94ff648916f7c376ae4b2c0652b98ff9"}, - {file = "nh3-0.2.21-cp313-cp313t-win32.whl", hash = "sha256:637d4a10c834e1b7d9548592c7aad760611415fcd5bd346f77fd8a064309ae6d"}, - {file = "nh3-0.2.21-cp313-cp313t-win_amd64.whl", hash = "sha256:713d16686596e556b65e7f8c58328c2df63f1a7abe1277d87625dcbbc012ef82"}, - {file = "nh3-0.2.21-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a772dec5b7b7325780922dd904709f0f5f3a79fbf756de5291c01370f6df0967"}, - {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d002b648592bf3033adfd875a48f09b8ecc000abd7f6a8769ed86b6ccc70c759"}, - {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2a5174551f95f2836f2ad6a8074560f261cf9740a48437d6151fd2d4d7d617ab"}, - {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b8d55ea1fc7ae3633d758a92aafa3505cd3cc5a6e40470c9164d54dff6f96d42"}, - {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ae319f17cd8960d0612f0f0ddff5a90700fa71926ca800e9028e7851ce44a6f"}, - {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:63ca02ac6f27fc80f9894409eb61de2cb20ef0a23740c7e29f9ec827139fa578"}, - {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5f77e62aed5c4acad635239ac1290404c7e940c81abe561fd2af011ff59f585"}, - {file = "nh3-0.2.21-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:087ffadfdcd497658c3adc797258ce0f06be8a537786a7217649fc1c0c60c293"}, - {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ac7006c3abd097790e611fe4646ecb19a8d7f2184b882f6093293b8d9b887431"}, - {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:6141caabe00bbddc869665b35fc56a478eb774a8c1dfd6fba9fe1dfdf29e6efa"}, - {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:20979783526641c81d2f5bfa6ca5ccca3d1e4472474b162c6256745fbfe31cd1"}, - {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a7ea28cd49293749d67e4fcf326c554c83ec912cd09cd94aa7ec3ab1921c8283"}, - {file = "nh3-0.2.21-cp38-abi3-win32.whl", hash = "sha256:6c9c30b8b0d291a7c5ab0967ab200598ba33208f754f2f4920e9343bdd88f79a"}, - {file = "nh3-0.2.21-cp38-abi3-win_amd64.whl", hash = "sha256:bb0014948f04d7976aabae43fcd4cb7f551f9f8ce785a4c9ef66e6c2590f8629"}, - {file = "nh3-0.2.21.tar.gz", hash = "sha256:4990e7ee6a55490dbf00d61a6f476c9a3258e31e711e13713b2ea7d6616f670e"}, -] - -[[package]] -name = "nodeenv" -version = "1.9.1" -description = "Node.js virtual environment builder" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["dev"] -files = [ - {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, - {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, -] - -[[package]] -name = "packageurl-python" -version = "0.16.0" -description = "A purl aka. Package URL parser and builder" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "packageurl_python-0.16.0-py3-none-any.whl", hash = "sha256:5c3872638b177b0f1cf01c3673017b7b27ebee485693ae12a8bed70fa7fa7c35"}, - {file = "packageurl_python-0.16.0.tar.gz", hash = "sha256:69e3bf8a3932fe9c2400f56aaeb9f86911ecee2f9398dbe1b58ec34340be365d"}, -] - -[package.extras] -build = ["setuptools", "wheel"] -lint = ["black", "isort", "mypy"] -sqlalchemy = ["sqlalchemy (>=2.0.0)"] -test = ["pytest"] - -[[package]] -name = "packaging" -version = "25.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev", "docs"] -files = [ - {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, - {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, -] - -[[package]] -name = "pasteboard" -version = "0.3.3" -description = "Pasteboard - Python interface for reading from NSPasteboard (macOS clipboard)" -optional = false -python-versions = ">=3.6,<4.0" -groups = ["main"] -markers = "platform_system == \"Darwin\"" -files = [ - {file = "pasteboard-0.3.3-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:afd171e200316f6b3d3da381476921ca57cb8f26d2fa418f779454913918dbb9"}, - {file = "pasteboard-0.3.3-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:f99dd6c7039b755756b2068942c4c2487d6366e5a56eafd6db0ae7aa2a371a0e"}, - {file = "pasteboard-0.3.3-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:19229dfa28f41afb5e731ac81e52bbc4212f67d678c082d3e3621cec0628a773"}, - {file = "pasteboard-0.3.3-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:20a5c53bae8ac8186ecdd621020fb1b072d45a35f9f11a8e4cd5e82d76b485d0"}, - {file = "pasteboard-0.3.3.tar.gz", hash = "sha256:d80275e76ff1eaaa5ca3d0e0fd8aecd5ea1298523dfd51f3774b5aaebdde02cf"}, -] - -[[package]] -name = "pastel" -version = "0.2.1" -description = "Bring colors to your terminal." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["dev"] -files = [ - {file = "pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364"}, - {file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "pefile" -version = "2023.2.7" -description = "Python PE parsing module" -optional = false -python-versions = ">=3.6.0" -groups = ["dev"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"}, - {file = "pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc"}, -] - -[[package]] -name = "pip" -version = "25.1.1" -description = "The PyPA recommended tool for installing Python packages." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pip-25.1.1-py3-none-any.whl", hash = "sha256:2913a38a2abf4ea6b64ab507bd9e967f3b53dc1ede74b01b0931e1ce548751af"}, - {file = "pip-25.1.1.tar.gz", hash = "sha256:3de45d411d308d5054c2168185d8da7f9a2cd753dbac8acbfa88a8909ecd9077"}, -] - -[[package]] -name = "pip-api" -version = "0.0.34" -description = "An unofficial, importable pip API" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pip_api-0.0.34-py3-none-any.whl", hash = "sha256:8b2d7d7c37f2447373aa2cf8b1f60a2f2b27a84e1e9e0294a3f6ef10eb3ba6bb"}, - {file = "pip_api-0.0.34.tar.gz", hash = "sha256:9b75e958f14c5a2614bae415f2adf7eeb54d50a2cfbe7e24fd4826471bac3625"}, -] - -[package.dependencies] -pip = "*" - -[[package]] -name = "pip-audit" -version = "2.9.0" -description = "A tool for scanning Python environments for known vulnerabilities" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pip_audit-2.9.0-py3-none-any.whl", hash = "sha256:348b16e60895749a0839875d7cc27ebd692e1584ebe5d5cb145941c8e25a80bd"}, - {file = "pip_audit-2.9.0.tar.gz", hash = "sha256:0b998410b58339d7a231e5aa004326a294e4c7c6295289cdc9d5e1ef07b1f44d"}, -] - -[package.dependencies] -CacheControl = {version = ">=0.13.0", extras = ["filecache"]} -cyclonedx-python-lib = ">=5,<10" -packaging = ">=23.0.0" -pip-api = ">=0.0.28" -pip-requirements-parser = ">=32.0.0" -platformdirs = ">=4.2.0" -requests = ">=2.31.0" -rich = ">=12.4" -toml = ">=0.10" - -[package.extras] -dev = ["build", "pip-audit[doc,lint,test]"] -doc = ["pdoc"] -lint = ["interrogate (>=1.6,<2.0)", "mypy", "ruff (>=0.9,<1.0)", "types-requests", "types-toml"] -test = ["coverage[toml] (>=7.0,!=7.3.3,<8.0)", "pretend", "pytest", "pytest-cov"] - -[[package]] -name = "pip-requirements-parser" -version = "32.0.1" -description = "pip requirements parser - a mostly correct pip requirements parsing library because it uses pip's own code." -optional = false -python-versions = ">=3.6.0" -groups = ["dev"] -files = [ - {file = "pip-requirements-parser-32.0.1.tar.gz", hash = "sha256:b4fa3a7a0be38243123cf9d1f3518da10c51bdb165a2b2985566247f9155a7d3"}, - {file = "pip_requirements_parser-32.0.1-py3-none-any.whl", hash = "sha256:4659bc2a667783e7a15d190f6fccf8b2486685b6dba4c19c3876314769c57526"}, -] - -[package.dependencies] -packaging = "*" -pyparsing = "*" - -[package.extras] -docs = ["Sphinx (>=3.3.1)", "doc8 (>=0.8.1)", "sphinx-rtd-theme (>=0.5.0)"] -testing = ["aboutcode-toolkit (>=6.0.0)", "black", "pytest (>=6,!=7.0.0)", "pytest-xdist (>=2)"] - -[[package]] -name = "pkginfo" -version = "1.12.1.2" -description = "Query metadata from sdists / bdists / installed packages." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pkginfo-1.12.1.2-py3-none-any.whl", hash = "sha256:c783ac885519cab2c34927ccfa6bf64b5a704d7c69afaea583dd9b7afe969343"}, - {file = "pkginfo-1.12.1.2.tar.gz", hash = "sha256:5cd957824ac36f140260964eba3c6be6442a8359b8c48f4adf90210f33a04b7b"}, -] - -[package.extras] -testing = ["pytest", "pytest-cov", "wheel"] - -[[package]] -name = "platformdirs" -version = "4.3.8" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.9" -groups = ["main", "dev", "docs"] -files = [ - {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, - {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.14.1)"] - -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "plumbum" -version = "1.9.0" -description = "Plumbum: shell combinators library" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "plumbum-1.9.0-py3-none-any.whl", hash = "sha256:9fd0d3b0e8d86e4b581af36edf3f3bbe9d1ae15b45b8caab28de1bcb27aaa7f5"}, - {file = "plumbum-1.9.0.tar.gz", hash = "sha256:e640062b72642c3873bd5bdc3effed75ba4d3c70ef6b6a7b907357a84d909219"}, -] - -[package.dependencies] -pywin32 = {version = "*", markers = "platform_system == \"Windows\" and platform_python_implementation != \"PyPy\""} - -[package.extras] -dev = ["coverage[toml]", "paramiko", "psutil", "pytest (>=6.0)", "pytest-cov", "pytest-mock", "pytest-timeout"] -docs = ["sphinx (>=4.0.0)", "sphinx-rtd-theme (>=1.0.0)"] -ssh = ["paramiko"] -test = ["coverage[toml]", "paramiko", "psutil", "pytest (>=6.0)", "pytest-cov", "pytest-mock", "pytest-timeout"] - -[[package]] -name = "poethepoet" -version = "0.36.0" -description = "A task runner that works well with poetry and uv." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "poethepoet-0.36.0-py3-none-any.whl", hash = "sha256:693e3c1eae9f6731d3613c3c0c40f747d3c5c68a375beda42e590a63c5623308"}, - {file = "poethepoet-0.36.0.tar.gz", hash = "sha256:2217b49cb4e4c64af0b42ff8c4814b17f02e107d38bc461542517348ede25663"}, -] - -[package.dependencies] -pastel = ">=0.2.1,<0.3.0" -pyyaml = ">=6.0.2,<7.0" -tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} - -[package.extras] -poetry-plugin = ["poetry (>=1.2.0,<3.0.0) ; python_version < \"4.0\""] - -[[package]] -name = "pre-commit" -version = "3.8.0" -description = "A framework for managing and maintaining multi-language pre-commit hooks." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"}, - {file = "pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af"}, -] - -[package.dependencies] -cfgv = ">=2.0.0" -identify = ">=1.0.0" -nodeenv = ">=0.11.1" -pyyaml = ">=5.1" -virtualenv = ">=20.10.0" - -[[package]] -name = "prompt-toolkit" -version = "3.0.51" -description = "Library for building powerful interactive command lines in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07"}, - {file = "prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed"}, -] - -[package.dependencies] -wcwidth = "*" - -[[package]] -name = "py-serializable" -version = "2.0.0" -description = "Library for serializing and deserializing Python Objects to and from JSON and XML." -optional = false -python-versions = "<4.0,>=3.8" -groups = ["dev"] -files = [ - {file = "py_serializable-2.0.0-py3-none-any.whl", hash = "sha256:1721e4c0368adeec965c183168da4b912024702f19e15e13f8577098b9a4f8fe"}, - {file = "py_serializable-2.0.0.tar.gz", hash = "sha256:e9e6491dd7d29c31daf1050232b57f9657f9e8a43b867cca1ff204752cf420a5"}, -] - -[package.dependencies] -defusedxml = ">=0.7.1,<0.8.0" - -[[package]] -name = "pyclip" -version = "0.7.0" -description = "Cross-platform clipboard utilities supporting both binary and text data." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pyclip-0.7.0-py3-none-any.whl", hash = "sha256:a7b7ea2cfad2dd61e86a529af588d006070d3eb0bd32981afaee5215f4604fec"}, - {file = "pyclip-0.7.0.tar.gz", hash = "sha256:57602047a4ceab709bdcd42f3dde6449a3349b95c16154cfdce27376a2072491"}, -] - -[package.dependencies] -pasteboard = {version = "0.3.3", markers = "platform_system == \"Darwin\""} -pywin32 = {version = ">=1.0", markers = "platform_system == \"Windows\""} - -[package.extras] -test = ["pytest"] - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pycryptodomex" -version = "3.22.0" -description = "Cryptographic library for Python" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main"] -files = [ - {file = "pycryptodomex-3.22.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:41673e5cc39a8524557a0472077635d981172182c9fe39ce0b5f5c19381ffaff"}, - {file = "pycryptodomex-3.22.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:276be1ed006e8fd01bba00d9bd9b60a0151e478033e86ea1cb37447bbc057edc"}, - {file = "pycryptodomex-3.22.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:813e57da5ceb4b549bab96fa548781d9a63f49f1d68fdb148eeac846238056b7"}, - {file = "pycryptodomex-3.22.0-cp27-cp27m-win32.whl", hash = "sha256:d7beeacb5394765aa8dabed135389a11ee322d3ee16160d178adc7f8ee3e1f65"}, - {file = "pycryptodomex-3.22.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:b3746dedf74787da43e4a2f85bd78f5ec14d2469eb299ddce22518b3891f16ea"}, - {file = "pycryptodomex-3.22.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5ebc09b7d8964654aaf8a4f5ac325f2b0cc038af9bea12efff0cd4a5bb19aa42"}, - {file = "pycryptodomex-3.22.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:aef4590263b9f2f6283469e998574d0bd45c14fb262241c27055b82727426157"}, - {file = "pycryptodomex-3.22.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:5ac608a6dce9418d4f300fab7ba2f7d499a96b462f2b9b5c90d8d994cd36dcad"}, - {file = "pycryptodomex-3.22.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a24f681365ec9757ccd69b85868bbd7216ba451d0f86f6ea0eed75eeb6975db"}, - {file = "pycryptodomex-3.22.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:259664c4803a1fa260d5afb322972813c5fe30ea8b43e54b03b7e3a27b30856b"}, - {file = "pycryptodomex-3.22.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7127d9de3c7ce20339e06bcd4f16f1a1a77f1471bcf04e3b704306dde101b719"}, - {file = "pycryptodomex-3.22.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ee75067b35c93cc18b38af47b7c0664998d8815174cfc66dd00ea1e244eb27e6"}, - {file = "pycryptodomex-3.22.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:1a8b0c5ba061ace4bcd03496d42702c3927003db805b8ec619ea6506080b381d"}, - {file = "pycryptodomex-3.22.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:bfe4fe3233ef3e58028a3ad8f28473653b78c6d56e088ea04fe7550c63d4d16b"}, - {file = "pycryptodomex-3.22.0-cp37-abi3-win32.whl", hash = "sha256:2cac9ed5c343bb3d0075db6e797e6112514764d08d667c74cb89b931aac9dddd"}, - {file = "pycryptodomex-3.22.0-cp37-abi3-win_amd64.whl", hash = "sha256:ff46212fda7ee86ec2f4a64016c994e8ad80f11ef748131753adb67e9b722ebd"}, - {file = "pycryptodomex-3.22.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:5bf3ce9211d2a9877b00b8e524593e2209e370a287b3d5e61a8c45f5198487e2"}, - {file = "pycryptodomex-3.22.0-pp27-pypy_73-win32.whl", hash = "sha256:684cb57812cd243217c3d1e01a720c5844b30f0b7b64bb1a49679f7e1e8a54ac"}, - {file = "pycryptodomex-3.22.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c8cffb03f5dee1026e3f892f7cffd79926a538c67c34f8b07c90c0bd5c834e27"}, - {file = "pycryptodomex-3.22.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:140b27caa68a36d0501b05eb247bd33afa5f854c1ee04140e38af63c750d4e39"}, - {file = "pycryptodomex-3.22.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:644834b1836bb8e1d304afaf794d5ae98a1d637bd6e140c9be7dd192b5374811"}, - {file = "pycryptodomex-3.22.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72c506aba3318505dbeecf821ed7b9a9f86f422ed085e2d79c4fba0ae669920a"}, - {file = "pycryptodomex-3.22.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7cd39f7a110c1ab97ce9ee3459b8bc615920344dc00e56d1b709628965fba3f2"}, - {file = "pycryptodomex-3.22.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e4eaaf6163ff13788c1f8f615ad60cdc69efac6d3bf7b310b21e8cfe5f46c801"}, - {file = "pycryptodomex-3.22.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eac39e237d65981554c2d4c6668192dc7051ad61ab5fc383ed0ba049e4007ca2"}, - {file = "pycryptodomex-3.22.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ab0d89d1761959b608952c7b347b0e76a32d1a5bb278afbaa10a7f3eaef9a0a"}, - {file = "pycryptodomex-3.22.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e64164f816f5e43fd69f8ed98eb28f98157faf68208cd19c44ed9d8e72d33e8"}, - {file = "pycryptodomex-3.22.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f005de31efad6f9acefc417296c641f13b720be7dbfec90edeaca601c0fab048"}, - {file = "pycryptodomex-3.22.0.tar.gz", hash = "sha256:a1da61bacc22f93a91cbe690e3eb2022a03ab4123690ab16c46abb693a9df63d"}, -] - -[[package]] -name = "pydantic" -version = "2.12.5" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, - {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.41.5" -typing-extensions = ">=4.14.1" -typing-inspection = ">=0.4.2" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.41.5" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146"}, - {file = "pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2"}, - {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97"}, - {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9"}, - {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52"}, - {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941"}, - {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a"}, - {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c"}, - {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2"}, - {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556"}, - {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49"}, - {file = "pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba"}, - {file = "pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9"}, - {file = "pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6"}, - {file = "pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b"}, - {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a"}, - {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8"}, - {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e"}, - {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1"}, - {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b"}, - {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b"}, - {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284"}, - {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594"}, - {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e"}, - {file = "pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b"}, - {file = "pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe"}, - {file = "pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f"}, - {file = "pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7"}, - {file = "pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0"}, - {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69"}, - {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75"}, - {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05"}, - {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc"}, - {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c"}, - {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5"}, - {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c"}, - {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294"}, - {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1"}, - {file = "pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d"}, - {file = "pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815"}, - {file = "pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3"}, - {file = "pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9"}, - {file = "pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34"}, - {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0"}, - {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33"}, - {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e"}, - {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2"}, - {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586"}, - {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d"}, - {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740"}, - {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e"}, - {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858"}, - {file = "pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36"}, - {file = "pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11"}, - {file = "pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd"}, - {file = "pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a"}, - {file = "pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14"}, - {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1"}, - {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66"}, - {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869"}, - {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2"}, - {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375"}, - {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553"}, - {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90"}, - {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07"}, - {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb"}, - {file = "pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23"}, - {file = "pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf"}, - {file = "pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c"}, - {file = "pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008"}, - {file = "pydantic_core-2.41.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf"}, - {file = "pydantic_core-2.41.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5"}, - {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d"}, - {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60"}, - {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82"}, - {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5"}, - {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3"}, - {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425"}, - {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504"}, - {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5"}, - {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3"}, - {file = "pydantic_core-2.41.5-cp39-cp39-win32.whl", hash = "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460"}, - {file = "pydantic_core-2.41.5-cp39-cp39-win_amd64.whl", hash = "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b"}, - {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034"}, - {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c"}, - {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2"}, - {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad"}, - {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd"}, - {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc"}, - {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56"}, - {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b"}, - {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8"}, - {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a"}, - {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b"}, - {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2"}, - {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093"}, - {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a"}, - {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963"}, - {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a"}, - {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26"}, - {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808"}, - {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc"}, - {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1"}, - {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84"}, - {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770"}, - {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f"}, - {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, - {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, -] - -[package.dependencies] -typing-extensions = ">=4.14.1" - -[[package]] -name = "pydash" -version = "8.0.5" -description = "The kitchen sink of Python utility libraries for doing \"stuff\" in a functional way. Based on the Lo-Dash Javascript library." -optional = false -python-versions = ">=3.8" -groups = ["docs"] -files = [ - {file = "pydash-8.0.5-py3-none-any.whl", hash = "sha256:b2625f8981862e19911daa07f80ed47b315ce20d9b5eb57aaf97aaf570c3892f"}, - {file = "pydash-8.0.5.tar.gz", hash = "sha256:7cc44ebfe5d362f4f5f06c74c8684143c5ac481376b059ff02570705523f9e2e"}, -] - -[package.dependencies] -typing-extensions = ">3.10,<4.6.0 || >4.6.0" - -[package.extras] -dev = ["build", "coverage", "furo", "invoke", "mypy", "pytest", "pytest-cov", "pytest-mypy-testing", "ruff", "sphinx", "sphinx-autodoc-typehints", "tox", "twine", "wheel"] - -[[package]] -name = "pygments" -version = "2.19.1" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev", "docs"] -files = [ - {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, - {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, -] - -[package.extras] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pyinstaller" -version = "6.18.0" -description = "PyInstaller bundles a Python application and all its dependencies into a single package." -optional = false -python-versions = "<3.15,>=3.8" -groups = ["dev"] -files = [ - {file = "pyinstaller-6.18.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:cb7aa5a71bfa7c0af17a4a4e21855663c89e4bd7c40f1d337c8370636d8847c3"}, - {file = "pyinstaller-6.18.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:07785459b3bf8a48889eac0b4d0667ade84aef8930ce030bc7cbb32f41283b33"}, - {file = "pyinstaller-6.18.0-py3-none-manylinux2014_i686.whl", hash = "sha256:f998675b7ccb2dabbb1dc2d6f18af61d55428ad6d38e6c4d700417411b697d37"}, - {file = "pyinstaller-6.18.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:779817a0cf69604cddcdb5be1fd4959dc2ce048d6355c73e5da97884df2f3387"}, - {file = "pyinstaller-6.18.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:31b5d109f8405be0b7cddcede43e7b074792bc9a5bbd54ec000a3e779183c2af"}, - {file = "pyinstaller-6.18.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:4328c9837f1aef4fe1a127d4ff1b09a12ce53c827ce87c94117628b0e1fd098b"}, - {file = "pyinstaller-6.18.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:3638fc81eb948e5e5eab1d4ad8f216e3fec6d4a350648304f0adb227b746ee5e"}, - {file = "pyinstaller-6.18.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:8fbe59da34269e637f97fd3c43024f764586fc319141d245ff1a2e9af1036aa3"}, - {file = "pyinstaller-6.18.0-py3-none-win32.whl", hash = "sha256:496205e4fa92ec944f9696eb597962a83aef4d4c3479abfab83d730e1edf016b"}, - {file = "pyinstaller-6.18.0-py3-none-win_amd64.whl", hash = "sha256:976fabd90ecfbda47571c87055ad73413ec615ff7dea35e12a4304174de78de9"}, - {file = "pyinstaller-6.18.0-py3-none-win_arm64.whl", hash = "sha256:dba4b70e3c9ba09aab51152c72a08e58a751851548f77ad35944d32a300c8381"}, - {file = "pyinstaller-6.18.0.tar.gz", hash = "sha256:cdc507542783511cad4856fce582fdc37e9f29665ca596889c663c83ec8c6ec9"}, -] - -[package.dependencies] -altgraph = "*" -macholib = {version = ">=1.8", markers = "sys_platform == \"darwin\""} -packaging = ">=22.0" -pefile = {version = ">=2022.5.30", markers = "sys_platform == \"win32\""} -pyinstaller-hooks-contrib = ">=2025.9" -pywin32-ctypes = {version = ">=0.2.1", markers = "sys_platform == \"win32\""} -setuptools = ">=42.0.0" - -[package.extras] -completion = ["argcomplete"] -hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] - -[[package]] -name = "pyinstaller-hooks-contrib" -version = "2026.0" -description = "Community maintained hooks for PyInstaller" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pyinstaller_hooks_contrib-2026.0-py3-none-any.whl", hash = "sha256:0590db8edeba3e6c30c8474937021f5cd39c0602b4d10f74a064c73911efaca5"}, - {file = "pyinstaller_hooks_contrib-2026.0.tar.gz", hash = "sha256:0120893de491a000845470ca9c0b39284731ac6bace26f6849dea9627aaed48e"}, -] - -[package.dependencies] -packaging = ">=22.0" -setuptools = ">=42.0.0" - -[[package]] -name = "pyjwt" -version = "2.10.1" -description = "JSON Web Token implementation in Python" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, - {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, -] - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pynacl" -version = "1.6.2" -description = "Python binding to the Networking and Cryptography (NaCl) library" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pynacl-1.6.2-cp314-cp314t-macosx_10_10_universal2.whl", hash = "sha256:622d7b07cc5c02c666795792931b50c91f3ce3c2649762efb1ef0d5684c81594"}, - {file = "pynacl-1.6.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d071c6a9a4c94d79eb665db4ce5cedc537faf74f2355e4d502591d850d3913c0"}, - {file = "pynacl-1.6.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe9847ca47d287af41e82be1dd5e23023d3c31a951da134121ab02e42ac218c9"}, - {file = "pynacl-1.6.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:04316d1fc625d860b6c162fff704eb8426b1a8bcd3abacea11142cbd99a6b574"}, - {file = "pynacl-1.6.2-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44081faff368d6c5553ccf55322ef2819abb40e25afaec7e740f159f74813634"}, - {file = "pynacl-1.6.2-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:a9f9932d8d2811ce1a8ffa79dcbdf3970e7355b5c8eb0c1a881a57e7f7d96e88"}, - {file = "pynacl-1.6.2-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:bc4a36b28dd72fb4845e5d8f9760610588a96d5a51f01d84d8c6ff9849968c14"}, - {file = "pynacl-1.6.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3bffb6d0f6becacb6526f8f42adfb5efb26337056ee0831fb9a7044d1a964444"}, - {file = "pynacl-1.6.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2fef529ef3ee487ad8113d287a593fa26f48ee3620d92ecc6f1d09ea38e0709b"}, - {file = "pynacl-1.6.2-cp314-cp314t-win32.whl", hash = "sha256:a84bf1c20339d06dc0c85d9aea9637a24f718f375d861b2668b2f9f96fa51145"}, - {file = "pynacl-1.6.2-cp314-cp314t-win_amd64.whl", hash = "sha256:320ef68a41c87547c91a8b58903c9caa641ab01e8512ce291085b5fe2fcb7590"}, - {file = "pynacl-1.6.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d29bfe37e20e015a7d8b23cfc8bd6aa7909c92a1b8f41ee416bbb3e79ef182b2"}, - {file = "pynacl-1.6.2-cp38-abi3-macosx_10_10_universal2.whl", hash = "sha256:c949ea47e4206af7c8f604b8278093b674f7c79ed0d4719cc836902bf4517465"}, - {file = "pynacl-1.6.2-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8845c0631c0be43abdd865511c41eab235e0be69c81dc66a50911594198679b0"}, - {file = "pynacl-1.6.2-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:22de65bb9010a725b0dac248f353bb072969c94fa8d6b1f34b87d7953cf7bbe4"}, - {file = "pynacl-1.6.2-cp38-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:46065496ab748469cdd999246d17e301b2c24ae2fdf739132e580a0e94c94a87"}, - {file = "pynacl-1.6.2-cp38-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a66d6fb6ae7661c58995f9c6435bda2b1e68b54b598a6a10247bfcdadac996c"}, - {file = "pynacl-1.6.2-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:26bfcd00dcf2cf160f122186af731ae30ab120c18e8375684ec2670dccd28130"}, - {file = "pynacl-1.6.2-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c8a231e36ec2cab018c4ad4358c386e36eede0319a0c41fed24f840b1dac59f6"}, - {file = "pynacl-1.6.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:68be3a09455743ff9505491220b64440ced8973fe930f270c8e07ccfa25b1f9e"}, - {file = "pynacl-1.6.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:8b097553b380236d51ed11356c953bf8ce36a29a3e596e934ecabe76c985a577"}, - {file = "pynacl-1.6.2-cp38-abi3-win32.whl", hash = "sha256:5811c72b473b2f38f7e2a3dc4f8642e3a3e9b5e7317266e4ced1fba85cae41aa"}, - {file = "pynacl-1.6.2-cp38-abi3-win_amd64.whl", hash = "sha256:62985f233210dee6548c223301b6c25440852e13d59a8b81490203c3227c5ba0"}, - {file = "pynacl-1.6.2-cp38-abi3-win_arm64.whl", hash = "sha256:834a43af110f743a754448463e8fd61259cd4ab5bbedcf70f9dabad1d28a394c"}, - {file = "pynacl-1.6.2.tar.gz", hash = "sha256:018494d6d696ae03c7e656e5e74cdfd8ea1326962cc401bcf018f1ed8436811c"}, -] - -[package.dependencies] -cffi = {version = ">=2.0.0", markers = "platform_python_implementation != \"PyPy\" and python_version >= \"3.9\""} - -[package.extras] -docs = ["sphinx (<7)", "sphinx_rtd_theme"] -tests = ["hypothesis (>=3.27.0)", "pytest (>=7.4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] - -[[package]] -name = "pyparsing" -version = "3.2.3" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf"}, - {file = "pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be"}, -] - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[[package]] -name = "pyperclip" -version = "1.9.0" -description = "A cross-platform clipboard module for Python. (Only handles plain text for now.)" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "pyperclip-1.9.0.tar.gz", hash = "sha256:b7de0142ddc81bfc5c7507eea19da920b92252b548b96186caf94a5e2527d310"}, -] - -[[package]] -name = "pytest" -version = "8.4.1" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, - {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, -] - -[package.dependencies] -colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} -iniconfig = ">=1" -packaging = ">=20" -pluggy = ">=1.5,<2" -pygments = ">=2.7.2" -tomli = {version = ">=1", markers = "python_version < \"3.11\""} - -[package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "pytest-cov" -version = "4.1.0" -description = "Pytest plugin for measuring coverage." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, - {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, -] - -[package.dependencies] -coverage = {version = ">=5.2.1", extras = ["toml"]} -pytest = ">=4.6" - -[package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] - -[[package]] -name = "pytest-httpx" -version = "0.35.0" -description = "Send responses to httpx." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pytest_httpx-0.35.0-py3-none-any.whl", hash = "sha256:ee11a00ffcea94a5cbff47af2114d34c5b231c326902458deed73f9c459fd744"}, - {file = "pytest_httpx-0.35.0.tar.gz", hash = "sha256:d619ad5d2e67734abfbb224c3d9025d64795d4b8711116b1a13f72a251ae511f"}, -] - -[package.dependencies] -httpx = "==0.28.*" -pytest = "==8.*" - -[package.extras] -testing = ["pytest-asyncio (==0.24.*)", "pytest-cov (==6.*)"] - -[[package]] -name = "pytest-mock" -version = "3.14.1" -description = "Thin-wrapper around the mock package for easier use with pytest" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0"}, - {file = "pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e"}, -] - -[package.dependencies] -pytest = ">=6.2.5" - -[package.extras] -dev = ["pre-commit", "pytest-asyncio", "tox"] - -[[package]] -name = "pytest-sugar" -version = "1.0.0" -description = "pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly)." -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "pytest-sugar-1.0.0.tar.gz", hash = "sha256:6422e83258f5b0c04ce7c632176c7732cab5fdb909cb39cca5c9139f81276c0a"}, - {file = "pytest_sugar-1.0.0-py3-none-any.whl", hash = "sha256:70ebcd8fc5795dc457ff8b69d266a4e2e8a74ae0c3edc749381c64b5246c8dfd"}, -] - -[package.dependencies] -packaging = ">=21.3" -pytest = ">=6.2.0" -termcolor = ">=2.1.0" - -[package.extras] -dev = ["black", "flake8", "pre-commit"] - -[[package]] -name = "pytest-xdist" -version = "3.8.0" -description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88"}, - {file = "pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1"}, -] - -[package.dependencies] -execnet = ">=2.1" -pytest = ">=7.0.0" - -[package.extras] -psutil = ["psutil (>=3.0)"] -setproctitle = ["setproctitle"] -testing = ["filelock"] - -[[package]] -name = "python-dotenv" -version = "1.1.1" -description = "Read key-value pairs from a .env file and set them as environment variables" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc"}, - {file = "python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab"}, -] - -[package.extras] -cli = ["click (>=5.0)"] - -[[package]] -name = "python-gitlab" -version = "3.15.0" -description = "Interact with GitLab API" -optional = false -python-versions = ">=3.7.0" -groups = ["dev"] -files = [ - {file = "python-gitlab-3.15.0.tar.gz", hash = "sha256:c9e65eb7612a9fbb8abf0339972eca7fd7a73d4da66c9b446ffe528930aff534"}, - {file = "python_gitlab-3.15.0-py3-none-any.whl", hash = "sha256:8f8d1c0d387f642eb1ac7bf5e8e0cd8b3dd49c6f34170cee3c7deb7d384611f3"}, -] - -[package.dependencies] -requests = ">=2.25.0" -requests-toolbelt = ">=0.10.1" - -[package.extras] -autocompletion = ["argcomplete (>=1.10.0,<3)"] -yaml = ["PyYaml (>=5.2)"] - -[[package]] -name = "python-semantic-release" -version = "7.34.6" -description = "Automatic Semantic Versioning for Python projects" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "python-semantic-release-7.34.6.tar.gz", hash = "sha256:e9b8fb788024ae9510a924136d573588415a16eeca31cc5240f2754a80a2e831"}, - {file = "python_semantic_release-7.34.6-py3-none-any.whl", hash = "sha256:7e3969ba4663d9b2087b02bf3ac140e202551377bf045c34e09bfe19753e19ab"}, -] - -[package.dependencies] -click = ">=7,<9" -click-log = ">=0.3,<1" -dotty-dict = ">=1.3.0,<2" -gitpython = ">=3.0.8,<4" -invoke = ">=1.4.1,<3" -packaging = "*" -python-gitlab = ">=2,<4" -requests = ">=2.25,<3" -semver = ">=2.10,<3" -tomlkit = ">=0.10,<1.0" -twine = ">=3,<4" -wheel = "*" - -[package.extras] -dev = ["black", "isort", "tox"] -docs = ["Jinja2 (==3.0.3)", "Sphinx (==1.8.6)"] -mypy = ["mypy", "types-requests"] -test = ["coverage (>=5,<6)", "mock (==1.3.0)", "pytest (>=7,<8)", "pytest-mock (>=2,<3)", "pytest-xdist (>=1,<2)", "responses (==0.13.3)"] - -[[package]] -name = "pywin32" -version = "311" -description = "Python for Window Extensions" -optional = false -python-versions = "*" -groups = ["main"] -markers = "platform_system == \"Windows\" or sys_platform == \"win32\"" -files = [ - {file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"}, - {file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"}, - {file = "pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b"}, - {file = "pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151"}, - {file = "pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503"}, - {file = "pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2"}, - {file = "pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31"}, - {file = "pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067"}, - {file = "pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852"}, - {file = "pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d"}, - {file = "pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d"}, - {file = "pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a"}, - {file = "pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee"}, - {file = "pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87"}, - {file = "pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42"}, - {file = "pywin32-311-cp38-cp38-win32.whl", hash = "sha256:6c6f2969607b5023b0d9ce2541f8d2cbb01c4f46bc87456017cf63b73f1e2d8c"}, - {file = "pywin32-311-cp38-cp38-win_amd64.whl", hash = "sha256:c8015b09fb9a5e188f83b7b04de91ddca4658cee2ae6f3bc483f0b21a77ef6cd"}, - {file = "pywin32-311-cp39-cp39-win32.whl", hash = "sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b"}, - {file = "pywin32-311-cp39-cp39-win_amd64.whl", hash = "sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91"}, - {file = "pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d"}, -] - -[[package]] -name = "pywin32-ctypes" -version = "0.2.3" -description = "A (partial) reimplementation of pywin32 using ctypes/cffi" -optional = false -python-versions = ">=3.6" -groups = ["main", "dev"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755"}, - {file = "pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.2" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, -] - -[[package]] -name = "questionary" -version = "1.10.0" -description = "Python library to build pretty command line user prompts ⭐️" -optional = false -python-versions = ">=3.6,<4.0" -groups = ["main"] -files = [ - {file = "questionary-1.10.0-py3-none-any.whl", hash = "sha256:fecfcc8cca110fda9d561cb83f1e97ecbb93c613ff857f655818839dac74ce90"}, - {file = "questionary-1.10.0.tar.gz", hash = "sha256:600d3aefecce26d48d97eee936fdb66e4bc27f934c3ab6dd1e292c4f43946d90"}, -] - -[package.dependencies] -prompt_toolkit = ">=2.0,<4.0" - -[package.extras] -docs = ["Sphinx (>=3.3,<4.0)", "sphinx-autobuild (>=2020.9.1,<2021.0.0)", "sphinx-autodoc-typehints (>=1.11.1,<2.0.0)", "sphinx-copybutton (>=0.3.1,<0.4.0)", "sphinx-rtd-theme (>=0.5.0,<0.6.0)"] - -[[package]] -name = "readme-renderer" -version = "43.0" -description = "readme_renderer is a library for rendering readme descriptions for Warehouse" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "readme_renderer-43.0-py3-none-any.whl", hash = "sha256:19db308d86ecd60e5affa3b2a98f017af384678c63c88e5d4556a380e674f3f9"}, - {file = "readme_renderer-43.0.tar.gz", hash = "sha256:1818dd28140813509eeed8d62687f7cd4f7bad90d4db586001c5dc09d4fde311"}, -] - -[package.dependencies] -docutils = ">=0.13.1" -nh3 = ">=0.2.14" -Pygments = ">=2.5.1" - -[package.extras] -md = ["cmarkgfm (>=0.8.0)"] - -[[package]] -name = "requests" -version = "2.32.4" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev", "docs"] -files = [ - {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, - {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset_normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "requests-toolbelt" -version = "1.0.0" -description = "A utility belt for advanced users of python-requests" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["dev"] -files = [ - {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, - {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, -] - -[package.dependencies] -requests = ">=2.0.1,<3.0.0" - -[[package]] -name = "rfc3986" -version = "2.0.0" -description = "Validating URI References per RFC 3986" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd"}, - {file = "rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c"}, -] - -[package.extras] -idna2008 = ["idna"] - -[[package]] -name = "rich" -version = "14.0.0" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.8.0" -groups = ["main", "dev"] -files = [ - {file = "rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0"}, - {file = "rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - -[[package]] -name = "ruff" -version = "0.12.2" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be"}, - {file = "ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e"}, - {file = "ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc"}, - {file = "ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922"}, - {file = "ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b"}, - {file = "ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d"}, - {file = "ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1"}, - {file = "ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4"}, - {file = "ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9"}, - {file = "ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da"}, - {file = "ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce"}, - {file = "ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d"}, - {file = "ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04"}, - {file = "ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342"}, - {file = "ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a"}, - {file = "ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639"}, - {file = "ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12"}, - {file = "ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e"}, -] - -[[package]] -name = "secretstorage" -version = "3.3.3" -description = "Python bindings to FreeDesktop.org Secret Service API" -optional = false -python-versions = ">=3.6" -groups = ["main", "dev"] -markers = "sys_platform == \"linux\"" -files = [ - {file = "SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99"}, - {file = "SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77"}, -] - -[package.dependencies] -cryptography = ">=2.0" -jeepney = ">=0.6" - -[[package]] -name = "semver" -version = "2.13.0" -description = "Python helper for Semantic Versioning (http://semver.org/)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["dev"] -files = [ - {file = "semver-2.13.0-py2.py3-none-any.whl", hash = "sha256:ced8b23dceb22134307c1b8abfa523da14198793d9787ac838e70e29e77458d4"}, - {file = "semver-2.13.0.tar.gz", hash = "sha256:fa0fe2722ee1c3f57eac478820c3a5ae2f624af8264cbdf9000c980ff7f75e3f"}, -] - -[[package]] -name = "setuptools" -version = "80.4.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "setuptools-80.4.0-py3-none-any.whl", hash = "sha256:6cdc8cb9a7d590b237dbe4493614a9b75d0559b888047c1f67d49ba50fc3edb2"}, - {file = "setuptools-80.4.0.tar.gz", hash = "sha256:5a78f61820bc088c8e4add52932ae6b8cf423da2aff268c23f813cfbb13b4006"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] -core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] - -[[package]] -name = "shellingham" -version = "1.5.4" -description = "Tool to Detect Surrounding Shell" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, - {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, -] - -[[package]] -name = "smmap" -version = "5.0.2" -description = "A pure Python implementation of a sliding window memory map manager" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, - {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "snowballstemmer" -version = "3.0.1" -description = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*" -groups = ["dev", "docs"] -files = [ - {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}, - {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, -] - -[[package]] -name = "sortedcontainers" -version = "2.4.0" -description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, - {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, -] - -[[package]] -name = "soupsieve" -version = "2.7" -description = "A modern CSS selector implementation for Beautiful Soup." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4"}, - {file = "soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a"}, -] - -[[package]] -name = "sphinx" -version = "6.2.1" -description = "Python documentation generator" -optional = false -python-versions = ">=3.8" -groups = ["dev", "docs"] -files = [ - {file = "Sphinx-6.2.1.tar.gz", hash = "sha256:6d56a34697bb749ffa0152feafc4b19836c755d90a7c59b72bc7dfd371b9cc6b"}, - {file = "sphinx-6.2.1-py3-none-any.whl", hash = "sha256:97787ff1fa3256a3eef9eda523a63dbf299f7b47e053cfcf684a1c2a8380c912"}, -] - -[package.dependencies] -alabaster = ">=0.7,<0.8" -babel = ">=2.9" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.18.1,<0.20" -imagesize = ">=1.3" -Jinja2 = ">=3.0" -packaging = ">=21.0" -Pygments = ">=2.13" -requests = ">=2.25.0" -snowballstemmer = ">=2.0" -sphinxcontrib-applehelp = "*" -sphinxcontrib-devhelp = "*" -sphinxcontrib-htmlhelp = ">=2.0.0" -sphinxcontrib-jsmath = "*" -sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = ">=1.1.5" - -[package.extras] -docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] -test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] - -[[package]] -name = "sphinx-click" -version = "4.4.0" -description = "Sphinx extension that automatically documents click applications" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "sphinx-click-4.4.0.tar.gz", hash = "sha256:cc67692bd28f482c7f01531c61b64e9d2f069bfcf3d24cbbb51d4a84a749fa48"}, - {file = "sphinx_click-4.4.0-py3-none-any.whl", hash = "sha256:2821c10a68fc9ee6ce7c92fad26540d8d8c8f45e6d7258f0e4fb7529ae8fab49"}, -] - -[package.dependencies] -click = ">=7.0" -docutils = "*" -sphinx = ">=2.0" - -[[package]] -name = "sphinxcontrib-applehelp" -version = "2.0.0" -description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" -optional = false -python-versions = ">=3.9" -groups = ["dev", "docs"] -files = [ - {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, - {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, -] - -[package.extras] -lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] -standalone = ["Sphinx (>=5)"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-devhelp" -version = "2.0.0" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" -optional = false -python-versions = ">=3.9" -groups = ["dev", "docs"] -files = [ - {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, - {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, -] - -[package.extras] -lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] -standalone = ["Sphinx (>=5)"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-htmlhelp" -version = "2.1.0" -description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -optional = false -python-versions = ">=3.9" -groups = ["dev", "docs"] -files = [ - {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, - {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, -] - -[package.extras] -lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] -standalone = ["Sphinx (>=5)"] -test = ["html5lib", "pytest"] - -[[package]] -name = "sphinxcontrib-jsmath" -version = "1.0.1" -description = "A sphinx extension which renders display math in HTML via JavaScript" -optional = false -python-versions = ">=3.5" -groups = ["dev", "docs"] -files = [ - {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, - {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, -] - -[package.extras] -test = ["flake8", "mypy", "pytest"] - -[[package]] -name = "sphinxcontrib-qthelp" -version = "2.0.0" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" -optional = false -python-versions = ">=3.9" -groups = ["dev", "docs"] -files = [ - {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, - {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, -] - -[package.extras] -lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] -standalone = ["Sphinx (>=5)"] -test = ["defusedxml (>=0.7.1)", "pytest"] - -[[package]] -name = "sphinxcontrib-serializinghtml" -version = "2.0.0" -description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" -optional = false -python-versions = ">=3.9" -groups = ["dev", "docs"] -files = [ - {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, - {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, -] - -[package.extras] -lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] -standalone = ["Sphinx (>=5)"] -test = ["pytest"] - -[[package]] -name = "sphinxnotes-markdown-builder" -version = "0.5.7" -description = "sphinx builder that outputs markdown files, an active fork of clayrisser/sphinx-markdown-builder" -optional = false -python-versions = "*" -groups = ["docs"] -files = [ - {file = "sphinxnotes-markdown-builder-0.5.7.tar.gz", hash = "sha256:ad3e88fa1052d1a9bc4b75d7ae389ce51ffa896963bb19643e01b9120ca17ee9"}, - {file = "sphinxnotes_markdown_builder-0.5.7-py2.py3-none-any.whl", hash = "sha256:e1c49c31f72c36b29defc69fb05b7087b736355474b8806c814306ad3b42e2b8"}, -] - -[package.dependencies] -html2text = "*" -pydash = "*" -sphinx = "*" -unify = "*" -yapf = "*" - -[[package]] -name = "termcolor" -version = "3.1.0" -description = "ANSI color formatting for output in terminal" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "termcolor-3.1.0-py3-none-any.whl", hash = "sha256:591dd26b5c2ce03b9e43f391264626557873ce1d379019786f99b0c2bee140aa"}, - {file = "termcolor-3.1.0.tar.gz", hash = "sha256:6a6dd7fbee581909eeec6a756cff1d7f7c376063b14e4a298dc4980309e55970"}, -] - -[package.extras] -tests = ["pytest", "pytest-cov"] - -[[package]] -name = "textual" -version = "3.6.0" -description = "Modern Text User Interface framework" -optional = false -python-versions = "<4.0.0,>=3.8.1" -groups = ["main"] -files = [ - {file = "textual-3.6.0-py3-none-any.whl", hash = "sha256:8b2fafe17b1805fd608092ab2f99b6ddeaff1809f1d5de6820bf5db5b6c51c28"}, - {file = "textual-3.6.0.tar.gz", hash = "sha256:d86b666e34758392a4a1aefc4b781b17d0d001419d24e4d47c277f36c20b1222"}, -] - -[package.dependencies] -markdown-it-py = {version = ">=2.1.0", extras = ["linkify", "plugins"]} -platformdirs = ">=3.6.0,<5" -rich = ">=13.3.3" -typing-extensions = ">=4.4.0,<5.0.0" - -[package.extras] -syntax = ["tree-sitter (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-bash (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-css (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-go (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-html (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-java (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-javascript (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-json (>=0.24.0) ; python_version >= \"3.9\"", "tree-sitter-markdown (>=0.3.0) ; python_version >= \"3.9\"", "tree-sitter-python (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-regex (>=0.24.0) ; python_version >= \"3.9\"", "tree-sitter-rust (>=0.23.0,<=0.23.2) ; python_version >= \"3.9\"", "tree-sitter-sql (>=0.3.0,<0.3.8) ; python_version >= \"3.9\"", "tree-sitter-toml (>=0.6.0) ; python_version >= \"3.9\"", "tree-sitter-xml (>=0.7.0) ; python_version >= \"3.9\"", "tree-sitter-yaml (>=0.6.0) ; python_version >= \"3.9\""] - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["dev"] -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - -[[package]] -name = "tomli" -version = "2.2.1" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev", "docs"] -files = [ - {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, - {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, - {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, - {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, - {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, - {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, - {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, - {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, - {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, - {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, -] -markers = {main = "python_version == \"3.10\"", dev = "python_full_version <= \"3.11.0a6\"", docs = "python_version == \"3.10\""} - -[[package]] -name = "tomlkit" -version = "0.13.2" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, - {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, -] - -[[package]] -name = "tqdm" -version = "4.67.1" -description = "Fast, Extensible Progress Meter" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, - {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["nbval", "pytest (>=6)", "pytest-asyncio (>=0.24)", "pytest-cov", "pytest-timeout"] -discord = ["requests"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - -[[package]] -name = "twine" -version = "3.8.0" -description = "Collection of utilities for publishing packages on PyPI" -optional = false -python-versions = ">=3.6" -groups = ["dev"] -files = [ - {file = "twine-3.8.0-py3-none-any.whl", hash = "sha256:d0550fca9dc19f3d5e8eadfce0c227294df0a2a951251a4385797c8a6198b7c8"}, - {file = "twine-3.8.0.tar.gz", hash = "sha256:8efa52658e0ae770686a13b675569328f1fba9837e5de1867bfe5f46a9aefe19"}, -] - -[package.dependencies] -colorama = ">=0.4.3" -importlib-metadata = ">=3.6" -keyring = ">=15.1" -pkginfo = ">=1.8.1" -readme-renderer = ">=21.0" -requests = ">=2.20" -requests-toolbelt = ">=0.8.0,<0.9.0 || >0.9.0" -rfc3986 = ">=1.4.0" -tqdm = ">=4.14" -urllib3 = ">=1.26.0" - -[[package]] -name = "types-pyyaml" -version = "6.0.12.20250402" -description = "Typing stubs for PyYAML" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "types_pyyaml-6.0.12.20250402-py3-none-any.whl", hash = "sha256:652348fa9e7a203d4b0d21066dfb00760d3cbd5a15ebb7cf8d33c88a49546681"}, - {file = "types_pyyaml-6.0.12.20250402.tar.gz", hash = "sha256:d7c13c3e6d335b6af4b0122a01ff1d270aba84ab96d1a1a1063ecba3e13ec075"}, -] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -description = "Backported and Experimental Type Hints for Python 3.9+" -optional = false -python-versions = ">=3.9" -groups = ["main", "dev", "docs"] -files = [ - {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, - {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, -] - -[[package]] -name = "typing-inspection" -version = "0.4.2" -description = "Runtime typing introspection tools" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, - {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, -] - -[package.dependencies] -typing-extensions = ">=4.12.0" - -[[package]] -name = "typing-validation" -version = "1.2.12" -description = "A simple library for runtime type-checking." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "typing_validation-1.2.12-py3-none-any.whl", hash = "sha256:d68e22a41bf2b98ae91e5d6407db56e9ef83e9e5600164a7aff64aaa082fc232"}, - {file = "typing_validation-1.2.12.tar.gz", hash = "sha256:7ea9463a18bd04922e799cac1954f687e68e9564773f81db491536852ffe1d54"}, -] - -[package.dependencies] -typing_extensions = {version = ">=4.6.0", markers = "python_version < \"3.11\""} - -[package.extras] -dev = ["mypy", "pylint", "pytest", "pytest-cov", "rich"] - -[[package]] -name = "uc-micro-py" -version = "1.0.3" -description = "Micro subset of unicode data files for linkify-it-py projects." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "uc-micro-py-1.0.3.tar.gz", hash = "sha256:d321b92cff673ec58027c04015fcaa8bb1e005478643ff4a500882eaab88c48a"}, - {file = "uc_micro_py-1.0.3-py3-none-any.whl", hash = "sha256:db1dffff340817673d7b466ec86114a9dc0e9d4d9b5ba229d9d60e5c12600cd5"}, -] - -[package.extras] -test = ["coverage", "pytest", "pytest-cov"] - -[[package]] -name = "unify" -version = "0.5" -description = "Modifies strings to all use the same (single/double) quote where possible." -optional = false -python-versions = "*" -groups = ["docs"] -files = [ - {file = "unify-0.5.tar.gz", hash = "sha256:8ddce812b2457212b7598fe574c9e6eb3ad69710f445391338270c7f8a71723c"}, -] - -[package.dependencies] -untokenize = "*" - -[[package]] -name = "untokenize" -version = "0.1.1" -description = "Transforms tokens into original source code (while preserving whitespace)." -optional = false -python-versions = "*" -groups = ["docs"] -files = [ - {file = "untokenize-0.1.1.tar.gz", hash = "sha256:3865dbbbb8efb4bb5eaa72f1be7f3e0be00ea8b7f125c69cbd1f5fda926f37a2"}, -] - -[[package]] -name = "urllib3" -version = "2.6.3" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.9" -groups = ["main", "dev", "docs"] -files = [ - {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}, - {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}, -] - -[package.extras] -brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] - -[[package]] -name = "virtualenv" -version = "20.31.2" -description = "Virtual Python Environment builder" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11"}, - {file = "virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af"}, -] - -[package.dependencies] -distlib = ">=0.3.7,<1" -filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<5" - -[package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] - -[[package]] -name = "wcwidth" -version = "0.2.13" -description = "Measures the displayed width of unicode strings in a terminal" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, - {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, -] - -[[package]] -name = "wheel" -version = "0.45.1" -description = "A built-package format for Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248"}, - {file = "wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729"}, -] - -[package.extras] -test = ["pytest (>=6.0.0)", "setuptools (>=65)"] - -[[package]] -name = "yapf" -version = "0.43.0" -description = "A formatter for Python code" -optional = false -python-versions = ">=3.7" -groups = ["docs"] -files = [ - {file = "yapf-0.43.0-py3-none-any.whl", hash = "sha256:224faffbc39c428cb095818cf6ef5511fdab6f7430a10783fdfb292ccf2852ca"}, - {file = "yapf-0.43.0.tar.gz", hash = "sha256:00d3aa24bfedff9420b2e0d5d9f5ab6d9d4268e72afbf59bb3fa542781d5218e"}, -] - -[package.dependencies] -platformdirs = ">=3.5.1" -tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} - -[[package]] -name = "zipp" -version = "3.21.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -files = [ - {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, - {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, -] -markers = {main = "python_version < \"3.12\""} - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib-resources ; python_version < \"3.9\"", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] -type = ["pytest-mypy"] - -[metadata] -lock-version = "2.1" -python-versions = ">=3.10,<3.15" -content-hash = "5e34de85e47c53abbef92d89aa9c338bb4c010e57e7e94748ca22a5cb8627dfa" diff --git a/poetry.toml b/poetry.toml deleted file mode 100644 index ab1033bd3..000000000 --- a/poetry.toml +++ /dev/null @@ -1,2 +0,0 @@ -[virtualenvs] -in-project = true diff --git a/pyproject.toml b/pyproject.toml index d28ec3b04..64458cff9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,70 +1,71 @@ -[tool.poetry] +[project] name = "algokit" version = "2.10.2" description = "Algorand development kit command-line interface" -authors = ["Algorand Foundation "] -license = "MIT" +authors = [{name = "Algorand Foundation", email = "contact@algorand.foundation"}] +license = {text = "MIT"} readme = "README.md" +requires-python = ">=3.10,<3.15" +dependencies = [ + "click==8.1.8", # TODO: 8.2.0 upgrade requires refinements in click_invoker.py due to breaking changes + "httpx>=0.23.1,<=0.28.1", + "copier>=9.11.3,<10.0.0", + "questionary>=1.10.0,<2.0.0", + "pyclip>=0.7.0,<0.8.0", + "shellingham>=1.5.4,<2.0.0", + "tomli>=2.0.1,<3.0.0; python_version < '3.11'", + "python-dotenv>=1.0.0,<2.0.0", + "mslex>=1.1.0,<2.0.0", + "keyring==25.6.0", + # pyjwt is locked because it's explicitly vendored from auth0 repo, + # to reduce dependency on auth0 package that caused many adhoc transitive dependency errors. + # See header in src/algokit/core/_vendor/auth0/authentication/token_verifier.py + "pyjwt>=2.10.1,<3.0.0", + "cryptography>=46.0.5,<47.0.0", # pyjwt weak dependency, explicitly required in vendored file + "algokit-utils>=5.0.0a7,<6.0.0", + "multiformats==0.3.1", + "multiformats-config==0.3.1", # pinned in lockstep with multiformats + "jsondiff>=2.0.0,<3.0.0", + "requests>=2.31.0,<3.0.0", + "textual>=3.0.1,<4.0.0", + "prompt-toolkit==3.0.51", # dependency of questionary, pinned to avoid 3.0.52 breaking changes + "pywin32>=311,<312; sys_platform == 'win32'", # transitive dep of pyclip, pinned for Python 3.14 on Windows +] -[tool.poetry.dependencies] -python = ">=3.10,<3.15" -click = "8.1.8" # TODO: 8.2.0 upgrade requires refinements in click_invoker.py due to breaking changes -httpx = ">=0.23.1,<=0.28.1" -copier = "^9.11.3" # Using caret to allow patch updates. Major/minor updates should be tested before bumping. -questionary = "^1.10.0" -pyclip = "^0.7.0" -shellingham = "^1.5.4" -tomli = { version = "^2.0.1", python = "<3.11" } -python-dotenv = "^1.0.0" -mslex = "^1.1.0" -keyring = "25.6.0" -# pyjwt is locked to version ^2.10.1 because its explicitly -# vendored from auth0 repo, to reduce depedency on auth0 package that caused many adhoc transitive dependency errors in cli -# see header in src/algokit/core/_vendor/auth0/authentication/token_verifier.py -# this version has been tested to work with the vendored file -pyjwt = "^2.10.1" -cryptography = "^46.0.5" # pyjwt has a weak dependency on cryptography and explicitly requires it in the vendored file, hence the lock -algokit-utils = "^5.0.0a7" -multiformats = "0.3.1" -multiformats_config = "0.3.1" # pinned this to be in lockstep with multiformats -jsondiff = "^2.0.0" -requests = "^2.31.0" -textual = "^3.0.1" -prompt_toolkit = "3.0.51" # dependency of questionary, pinned to avoid 3.0.52 which has breaking changes -pywin32 = { version = "^311", markers = "sys_platform == 'win32'" } # transitive dep of pyclip, pinned to support Python 3.14 on Windows - -[tool.poetry.group.dev.dependencies] -pyinstaller = {version = "^6.10.0"} -pytest = "^8" -ruff = ">=0.1.6,<0.13.0" -pip-audit = "^2.4.7" -approvaltests = "^7.2.0" -pytest-mock = "^3.10.0" -mypy = "^1.0.0" -pytest-httpx = "^0.35.0" -python-semantic-release = "^7.32.2" -pytest-cov = "^4.0.0" -pre-commit = ">=2.20,<4.0" -sphinx = "^6.0.0" -sphinx-click = "^4.4.0" -poethepoet = ">=0.17.1,<0.37.0" -gfm-toc = "^0.0.7" -pytest-xdist = "^3.4.0" -pytest-sugar = "^1.0.0" -types-pyyaml = "^6.0.12.20250402" - -[tool.poetry.group.docs] -optional = true - -[tool.poetry.group.docs.dependencies] -sphinxnotes-markdown-builder = "^0.5.6" +[project.scripts] +algokit = "algokit.cli:algokit" [build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" +requires = ["hatchling"] +build-backend = "hatchling.build" -[tool.poetry.scripts] -algokit = "algokit.cli:algokit" +[tool.hatch.build.targets.wheel] +packages = ["src/algokit"] + +[dependency-groups] +dev = [ + "pyinstaller>=6.10.0,<7.0.0", + "pytest>=8,<9", + "ruff>=0.1.6,<0.13.0", + "pip-audit>=2.4.7,<3.0.0", + "approvaltests>=7.2.0,<8.0.0", + "pytest-mock>=3.10.0,<4.0.0", + "mypy>=1.0.0,<2.0.0", + "pytest-httpx>=0.35.0,<0.36.0", + "python-semantic-release>=7.32.2,<8.0.0", + "pytest-cov>=4.0.0,<5.0.0", + "pre-commit>=2.20,<4.0", + "sphinx>=6.0.0,<7.0.0", + "sphinx-click>=4.4.0,<5.0.0", + "poethepoet>=0.17.1,<0.37.0", + "gfm-toc>=0.0.7,<0.0.8", + "pytest-xdist>=3.4.0,<4.0.0", + "pytest-sugar>=1.0.0,<2.0.0", + "types-pyyaml>=6.0.12.20250402,<7.0.0", +] +docs = [ + "sphinxnotes-markdown-builder>=0.5.6,<0.6.0", +] [tool.poe.tasks] docs_generate = "sphinx-build -b markdown -E docs/sphinx docs/cli" @@ -198,9 +199,9 @@ module = ["approvaltests.*", "jsondiff.*"] ignore_missing_imports = true [tool.semantic_release] -version_toml = "pyproject.toml:tool.poetry.version" +version_toml = "pyproject.toml:project.version" remove_dist = false -build_command = "poetry build --format wheel" +build_command = "uv build --wheel" version_source = "tag" major_on_zero = true upload_to_repository = false diff --git a/scripts/install/install.ps1 b/scripts/install/install.ps1 new file mode 100644 index 000000000..fa2b565a5 --- /dev/null +++ b/scripts/install/install.ps1 @@ -0,0 +1,124 @@ +# AlgoKit CLI Installer for Windows (PowerShell) +# Usage: irm https://raw.githubusercontent.com/algorandfoundation/algokit-cli/main/scripts/install/install.ps1 | iex +[CmdletBinding()] +param() + +$ErrorActionPreference = "Stop" +$UV_INSTALL_URL = "https://astral.sh/uv/install.ps1" +$PYTHON_VERSION = "3.12" +$PACKAGE = "algokit" + +function Write-Log { + param([string]$Message, [string]$Level = "INFO") + $color = switch ($Level) { + "INFO" { "Green" } + "WARN" { "Yellow" } + "ERROR" { "Red" } + default { "White" } + } + Write-Host "[algokit] $Message" -ForegroundColor $color +} + +function Stop-WithError { + param([string]$Message) + Write-Log $Message "ERROR" + exit 1 +} + +function Install-UV { + if (Get-Command uv -ErrorAction SilentlyContinue) { + $uvVersion = (uv --version 2>$null) -replace 'uv ', '' -replace '\n', '' + Write-Log "uv found: uv $uvVersion" + return + } + + Write-Log "Installing uv..." + try { + $uvInstallerScript = [string](Invoke-RestMethod $UV_INSTALL_URL) + if ($uvInstallerScript.Length -lt 1000) { + Stop-WithError "uv installer appears corrupted (too small)." + } + Invoke-Expression $uvInstallerScript + } + catch { + Stop-WithError "Failed to install uv: $($_.Exception.Message)" + } + + $env:PATH = "$env:USERPROFILE\.cargo\bin;$env:USERPROFILE\.local\bin;$env:PATH" + + if (-not (Get-Command uv -ErrorAction SilentlyContinue)) { + Stop-WithError "uv installed but not found on PATH. Restart your shell and try again." + } + Write-Log "uv installed successfully." +} + +function Install-Python { + try { + $pythonList = uv python list 2>$null | Out-String + if ($pythonList -match "cpython-$PYTHON_VERSION") { + Write-Log "Python $PYTHON_VERSION found." + return + } + } + catch { + Write-Log "Could not query Python versions: $($_.Exception.Message)" "WARN" + } + + Write-Log "Installing Python $PYTHON_VERSION via uv..." + try { + uv python install $PYTHON_VERSION + Write-Log "Python $PYTHON_VERSION installed." + } + catch { + Stop-WithError "Failed to install Python $PYTHON_VERSION." + } +} + +function Install-AlgoKit { + Write-Log "Installing $PACKAGE..." + try { + uv tool install $PACKAGE + Write-Log "$PACKAGE installed successfully." + } + catch { + Stop-WithError "Failed to install ${PACKAGE}: $($_.Exception.Message)" + } + + $toolPath = Get-Command algokit -ErrorAction SilentlyContinue + if ($toolPath) { + $allToolPaths = @(Get-Command algokit -All -ErrorAction SilentlyContinue | ForEach-Object { $_.Source } | Where-Object { $_ }) + $version = algokit --version 2>$null + Write-Log "Installed: $version" + Write-Log "Run 'algokit --help' to get started." + + if ($allToolPaths.Count -gt 1) { + Write-Log "Multiple algokit executables were found on PATH." "WARN" + Write-Log "Active executable: $($toolPath.Source)" "WARN" + Write-Log "All PATH matches:" "WARN" + foreach ($path in $allToolPaths) { + Write-Log " - $path" "WARN" + } + Write-Log "If this is not the uv-managed executable, move $env:USERPROFILE\.local\bin earlier on PATH or remove legacy binary." "WARN" + Write-Log "Restart your shell and run: algokit --version" "WARN" + } + } + else { + Write-Log "$PACKAGE installed but not found on PATH. Restart your shell and try again." "WARN" + } +} + +try { + Write-Log "AlgoKit CLI Installer" + Write-Host "" + + Install-UV + Install-Python + Install-AlgoKit + + Write-Host "" + Write-Log "Done." +} +catch { + Write-Log "Unexpected error: $($_.Exception.Message)" "ERROR" + exit 1 +} diff --git a/scripts/install/install.sh b/scripts/install/install.sh new file mode 100755 index 000000000..ccfea490e --- /dev/null +++ b/scripts/install/install.sh @@ -0,0 +1,126 @@ +#!/usr/bin/env bash +# AlgoKit CLI Installer for Unix/macOS +# Usage: curl -fsSL https://raw.githubusercontent.com/algorandfoundation/algokit-cli/main/scripts/install/install.sh | bash +set -euo pipefail + +UV_INSTALL_URL="https://astral.sh/uv/install.sh" +PYTHON_VERSION="3.12" +PACKAGE="algokit" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BOLD='\033[1m' +NC='\033[0m' + +log() { printf "${GREEN}[algokit]${NC} %b\n" "$*"; } +warn() { printf "${YELLOW}[algokit]${NC} %b\n" "$*"; } +die() { printf "${RED}[algokit]${NC} %b\n" "$*" >&2; exit 1; } + +check_curl() { + command -v curl >/dev/null 2>&1 || die "curl is required but not installed." +} + +ensure_uv() { + if command -v uv >/dev/null 2>&1; then + log "uv found: $(uv --version 2>/dev/null || echo 'unknown')" + return 0 + fi + + log "Installing uv..." + + local temp_file + temp_file=$(mktemp) + trap 'rm -f "$temp_file"' EXIT + + curl -fsSL --connect-timeout 30 --max-time 300 "$UV_INSTALL_URL" > "$temp_file" \ + || die "Failed to download uv installer." + + [[ $(wc -c < "$temp_file") -ge 1000 ]] \ + || die "uv installer appears corrupted (too small)." + + bash "$temp_file" || die "uv installation failed." + rm -f "$temp_file" + trap - EXIT + + export PATH="$HOME/.cargo/bin:$HOME/.local/bin:$PATH" + + command -v uv >/dev/null 2>&1 \ + || die "uv installed but not found on PATH. Restart your shell and try again." + log "uv installed successfully." +} + +ensure_python() { + if uv python find "${PYTHON_VERSION}" >/dev/null 2>&1; then + log "Python ${PYTHON_VERSION} found." + return 0 + fi + + log "Installing Python ${PYTHON_VERSION} via uv..." + uv python install "$PYTHON_VERSION" \ + || die "Failed to install Python ${PYTHON_VERSION}." + log "Python ${PYTHON_VERSION} installed." +} + +install_algokit() { + log "Installing ${PACKAGE}..." + uv tool install "$PACKAGE" \ + || die "Failed to install ${PACKAGE}." + + if command -v algokit >/dev/null 2>&1; then + local active_algokit + active_algokit=$(command -v algokit) + local -a all_algokit_paths=() + local -a path_entries=() + local seen_paths=":" + local path_entry + IFS=: read -r -a path_entries <<< "$PATH" + for path_entry in "${path_entries[@]}"; do + [[ -z "$path_entry" ]] && continue + local candidate="$path_entry/algokit" + if [[ -f "$candidate" && -x "$candidate" ]]; then + case "$seen_paths" in + *":$candidate:"*) ;; + *) + seen_paths="${seen_paths}${candidate}:" + all_algokit_paths+=("$candidate") + ;; + esac + fi + done + + log "Installed: $(algokit --version 2>/dev/null || echo "${PACKAGE}")" + log "Run ${BOLD}algokit --help${NC} to get started." + + if [[ ${#all_algokit_paths[@]} -gt 1 ]]; then + warn "Multiple algokit executables were found on PATH." + warn "Active executable: ${active_algokit}" + warn "All PATH matches:" + local match_path + for match_path in "${all_algokit_paths[@]}"; do + warn " - ${match_path}" + done + warn "If this is not the uv-managed executable, move ~/.local/bin earlier on PATH or remove legacy binary." + warn "Restart your shell and run: algokit --version" + fi + else + warn "${PACKAGE} installed but not found on PATH." + warn "Add ~/.local/bin to your PATH:" + printf ' export PATH="$HOME/.local/bin:$PATH"\n' + fi +} + +main() { + log "AlgoKit CLI Installer" + echo "" + + check_curl + ensure_uv + ensure_python + install_algokit + + echo "" + log "Done." +} + +main "$@" diff --git a/src/algokit/cli/__init__.py b/src/algokit/cli/__init__.py index 2da233502..daf987abd 100644 --- a/src/algokit/cli/__init__.py +++ b/src/algokit/cli/__init__.py @@ -1,3 +1,8 @@ +import logging +import platform +import sys +from pathlib import Path + import click from algokit.cli.compile import compile_group @@ -17,6 +22,15 @@ from algokit.core.conf import PACKAGE_NAME from algokit.core.config_commands.version_prompt import do_version_prompt, skip_version_check_option from algokit.core.log_handlers import color_option, verbose_option +from algokit.core.utils import find_all_on_path, is_binary_mode + +_INSTALL_URL_BASE = "https://raw.githubusercontent.com/algorandfoundation/algokit-cli/main/scripts/install" +_INSTALL_URL_SH = f"{_INSTALL_URL_BASE}/install.sh" +_INSTALL_URL_PS1 = f"{_INSTALL_URL_BASE}/install.ps1" +_ADR_URL = ( + "https://github.com/algorandfoundation/algokit-cli/blob/main/" + "docs/architecture-decisions/2025-03-03_uv_distribution.md" +) HIDDEN_COMMANDS: dict[str, click.Command] = {"deploy": deploy_command, "bootstrap": bootstrap_group} @@ -54,6 +68,8 @@ def algokit(*, skip_version_check: bool) -> None: if not skip_version_check: do_version_prompt() + _check_binary_deprecation() + algokit.add_command(completions_group) algokit.add_command(config_group) @@ -67,3 +83,49 @@ def algokit(*, skip_version_check: bool) -> None: algokit.add_command(task_group) algokit.add_command(compile_group) algokit.add_command(project_group) + + +def _check_binary_deprecation() -> None: + if not is_binary_mode(): + return + + install_cmd = ( + f"irm {_INSTALL_URL_PS1} | iex" if platform.system() == "Windows" else f"curl -fsSL {_INSTALL_URL_SH} | bash" + ) + + logger = logging.getLogger(__name__) + logger.warning( + "\n" + " WARNING: AlgoKit binary installation is being phased out.\n" + " Starting from the next major version, AlgoKit will be distributed via uv.\n" + " To migrate now, run:\n" + "\n" + " %s\n" + "\n" + " For more information, see:\n" + " %s\n", + install_cmd, + _ADR_URL, + ) + + algokit_paths = find_all_on_path("algokit") + if len(algokit_paths) <= 1: + return + + active_path = algokit_paths[0] + current_binary_path = Path(sys.executable) + all_paths = "\n".join(f" - {path}" for path in algokit_paths) + + logger.warning( + "\n" + " WARNING: Multiple `algokit` executables were found on PATH.\n" + " Active executable: %s\n" + " Current binary: %s\n" + " All PATH matches:\n" + "%s\n" + " If this is not the uv-managed executable, move ~/.local/bin (or %%USERPROFILE%%\\.local\\bin)\n" + " earlier in PATH or remove the legacy binary. Then restart your shell and run `algokit --version`.\n", + active_path, + current_binary_path, + all_paths, + ) diff --git a/src/algokit/cli/doctor.py b/src/algokit/cli/doctor.py index d281abe14..2fd9e1ce5 100644 --- a/src/algokit/cli/doctor.py +++ b/src/algokit/cli/doctor.py @@ -86,19 +86,25 @@ def doctor_command(*, copy_to_clipboard: bool) -> None: # noqa: C901, PLR0912 ), "python": check_dependency(["python", "--version"], include_location=True), "python3": check_dependency(["python3", "--version"], include_location=True), + "uv": check_dependency( + ["uv", "--version"], + missing_help=[ + "uv is the recommended tool runner for AlgoKit;", + "install via https://docs.astral.sh/uv/", + ], + ), "pipx": check_dependency( ["pipx", "--version"], missing_help=[ - "pipx is required if poetry is not installed in order to install it automatically;", + "pipx can be used as a fallback tool runner if uv is not installed;", "install via https://pypa.github.io/pipx/", ], ), "poetry": check_dependency( ["poetry", "--version"], missing_help=[ - "Poetry is required for some Python-based templates;", - "install via `algokit project bootstrap` within project directory, or via:", - "https://python-poetry.org/docs/#installation", + "Poetry may be needed for older Python-based templates;", + "install via https://python-poetry.org/docs/#installation", ], ), "node": check_dependency( @@ -160,7 +166,7 @@ def doctor_command(*, copy_to_clipboard: bool) -> None: # noqa: C901, PLR0912 pyclip.copy("\n".join(output_lines)) - if any(not value.ok for value in service_outputs.values()): + if any(not value.ok for key, value in service_outputs.items() if key in critical_services): raise click.exceptions.Exit(code=1) diff --git a/src/algokit/cli/project/__init__.py b/src/algokit/cli/project/__init__.py index ddbf83826..da493463e 100644 --- a/src/algokit/cli/project/__init__.py +++ b/src/algokit/cli/project/__init__.py @@ -1,6 +1,3 @@ -import logging -import re - import click from algokit.cli.project.bootstrap import bootstrap_group @@ -8,9 +5,6 @@ from algokit.cli.project.link import link_command from algokit.cli.project.list import list_command from algokit.cli.project.run import run_group -from algokit.core import proc - -logger = logging.getLogger(__name__) @click.group( @@ -20,18 +14,6 @@ def project_group() -> None: """Provides a suite of commands for managing your AlgoKit project. This includes initializing project dependencies, deploying smart contracts, and executing predefined or custom commands within your project environment.""" - try: - poetry_version_result = proc.run( - ["poetry", "--version"], - ) - except Exception: - return - - if re.search(r"1\.\d+\.\d+", poetry_version_result.output): - logger.warning( - "You are using Poetry 1.x, which is deprecated. " - "Please upgrade to Poetry 2.x for better support and features." - ) project_group.add_command(deploy_command) diff --git a/src/algokit/core/compilers/python.py b/src/algokit/core/compilers/python.py index de3ad7879..955fbcedb 100644 --- a/src/algokit/core/compilers/python.py +++ b/src/algokit/core/compilers/python.py @@ -1,7 +1,7 @@ from collections.abc import Iterator from algokit.core.proc import run -from algokit.core.utils import extract_version_triple, find_valid_pipx_command +from algokit.core.utils import extract_version_triple, find_valid_tool_runner_command, get_tool_run_command def find_valid_puyapy_command(version: str | None) -> list[str]: @@ -11,7 +11,7 @@ def find_valid_puyapy_command(version: str | None) -> list[str]: def _find_puyapy_command_at_version(version: str) -> list[str]: """ Find puyapy command with a specific version. - If the puyapy version isn't installed, install it with pipx run. + If the puyapy version isn't installed, run it via uvx/pipx. """ for puyapy_command in _get_candidate_puyapy_commands(): try: @@ -24,24 +24,19 @@ def _find_puyapy_command_at_version(version: str) -> list[str]: ): return puyapy_command - pipx_command = find_valid_pipx_command( - "Unable to find pipx install so that the `PuyaPy` compiler can be run; " - "please install pipx via https://pypa.github.io/pipx/ " + tool_runner_command = find_valid_tool_runner_command( + "Unable to find uvx or pipx so that `PuyaPy` can be run; " + "please install uv via https://docs.astral.sh/uv/ " "and then try `algokit compile python ...` again." ) - return [ - *pipx_command, - "run", - f"--spec=puyapy=={version}", - "puyapy", - ] + return get_tool_run_command(tool_runner_command, spec=f"puyapy=={version}", binary="puyapy") def _find_puyapy_command() -> list[str]: """ Find puyapy command. - If puyapy isn't installed, install the latest version with pipx. + If puyapy isn't installed, run the latest version via uvx/pipx. """ for puyapy_command in _get_candidate_puyapy_commands(): try: @@ -52,21 +47,15 @@ def _find_puyapy_command() -> list[str]: if puyapy_help_result.exit_code == 0: return puyapy_command - pipx_command = find_valid_pipx_command( - "Unable to find pipx install so that the `PuyaPy` compiler can be run; " - "please install pipx via https://pypa.github.io/pipx/ " + tool_runner_command = find_valid_tool_runner_command( + "Unable to find uvx or pipx so that `PuyaPy` can be run; " + "please install uv via https://docs.astral.sh/uv/ " "and then try `algokit compile python ...` again." ) - return [ - *pipx_command, - "run", - "--spec=puyapy", - "puyapy", - ] + return get_tool_run_command(tool_runner_command, spec="puyapy", binary="puyapy") def _get_candidate_puyapy_commands() -> Iterator[list[str]]: - # when puyapy is installed at the project level + yield ["uv", "run", "puyapy"] yield ["poetry", "run", "puyapy"] - # when puyapy is installed at the global level yield ["puyapy"] diff --git a/src/algokit/core/config_commands/py_package_manager.py b/src/algokit/core/config_commands/py_package_manager.py index 7dcf3dbca..c73505d5b 100644 --- a/src/algokit/core/config_commands/py_package_manager.py +++ b/src/algokit/core/config_commands/py_package_manager.py @@ -46,10 +46,10 @@ def py_package_manager_configuration_command(*, package_manager: str | None) -> """Set the default Python package manager for use by AlgoKit CLI.""" if package_manager is None: - current_manager = get_py_package_manager() or PyPackageManager.POETRY + current_manager = get_py_package_manager() or PyPackageManager.UV choices = [ - f"poetry {'(active)' if current_manager == PyPackageManager.POETRY else ''}".strip(), f"uv {'(active)' if current_manager == PyPackageManager.UV else ''}".strip(), + f"poetry {'(active)' if current_manager == PyPackageManager.POETRY else ''}".strip(), ] manager = questionary.select( "Which Python package manager would you prefer `bootstrap` command to use by default?", choices=choices @@ -58,5 +58,8 @@ def py_package_manager_configuration_command(*, package_manager: str | None) -> raise click.ClickException("No valid Python package manager selected. Aborting...") package_manager = manager.split()[0].lower() + if package_manager is None: + raise click.ClickException("No valid Python package manager selected. Aborting...") + save_py_package_manager(package_manager) logger.info(f"Python package manager set to `{package_manager}`") diff --git a/src/algokit/core/config_commands/version_prompt.py b/src/algokit/core/config_commands/version_prompt.py index 75838da4f..417e2db25 100644 --- a/src/algokit/core/config_commands/version_prompt.py +++ b/src/algokit/core/config_commands/version_prompt.py @@ -22,7 +22,10 @@ "brew": "`brew upgrade algokit`", } UNKNOWN_DISTRIBUTION_METHOD_UPDATE_INSTRUCTION = "the tool used to install AlgoKit" -# TODO: Set this version as part of releasing the binary distributions. +# Sentinel version used by binary distributions (winget, brew, snap). +# Any version >= this value that is NOT running in binary mode is assumed +# to have been installed via uv. This should be replaced with a proper +# detection mechanism if the sentinel is ever changed. BINARY_DISTRIBUTION_RELEASE_VERSION = "99.99.99" @@ -47,11 +50,9 @@ def do_version_prompt() -> None: if distribution else UNKNOWN_DISTRIBUTION_METHOD_UPDATE_INSTRUCTION ) - # If you're not using the binary mode, then you've used pipx to install AlgoKit. - # One exception is that older versions of the brew package used pipx, - # however require updating via brew, so we show the default update instruction instead. + # If not using binary mode, it was installed via uv or pipx. elif current_version_sequence >= _get_version_sequence(BINARY_DISTRIBUTION_RELEASE_VERSION): - update_instruction = "`pipx upgrade algokit`" + update_instruction = "`uv tool upgrade algokit`" logger.info( f"You are using AlgoKit version {current_version}, however version {latest_version} is available. " @@ -97,7 +98,7 @@ def get_latest_version_or_cached() -> str | None: def get_latest_github_version() -> str: headers = {"ACCEPT": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28"} - response = httpx.get(LATEST_URL, headers=headers) + response = httpx.get(LATEST_URL, headers=headers, timeout=5) response.raise_for_status() json = response.json() diff --git a/src/algokit/core/dispenser.py b/src/algokit/core/dispenser.py index 58a021ac8..0821887e5 100644 --- a/src/algokit/core/dispenser.py +++ b/src/algokit/core/dispenser.py @@ -281,7 +281,7 @@ def set_dispenser_credentials(token_data: dict[str, str]) -> None: keyring.set_password( DISPENSER_KEYRING_NAMESPACE, DISPENSER_KEYRING_REFRESH_TOKEN_KEY, token_data.get("refresh_token", "") ) - keyring.set_password(DISPENSER_KEYRING_NAMESPACE, DISPENSER_KEYRING_USER_ID_KEY, decoded_id_token.get("sub")) + keyring.set_password(DISPENSER_KEYRING_NAMESPACE, DISPENSER_KEYRING_USER_ID_KEY, decoded_id_token.get("sub") or "") def clear_dispenser_credentials() -> None: diff --git a/src/algokit/core/project/bootstrap.py b/src/algokit/core/project/bootstrap.py index f3c51ef22..1b613665c 100644 --- a/src/algokit/core/project/bootstrap.py +++ b/src/algokit/core/project/bootstrap.py @@ -20,7 +20,14 @@ get_py_package_manager, save_py_package_manager, ) -from algokit.core.utils import find_valid_pipx_command, is_windows +from algokit.core.utils import ( + find_valid_tool_runner_command, + get_tool_install_command, + get_tool_run_command, + is_uv, + is_uvx, + is_windows, +) ENV_TEMPLATE_PATTERN = ".env*.template" MAX_BOOTSTRAP_DEPTH = 2 @@ -123,6 +130,9 @@ def _determine_python_package_manager(project_dir: Path) -> str: poetry_path = project_dir / "poetry.toml" pyproject_path = project_dir / "pyproject.toml" + if is_uv_project(project_dir): + return PyPackageManager.UV + if poetry_path.exists(): # Standalone poetry.toml suggests Poetry return PyPackageManager.POETRY @@ -134,11 +144,10 @@ def _determine_python_package_manager(project_dir: Path) -> str: # 4. Interactive prompt for first-time users manager = questionary.select( "Which Python package manager would you prefer `bootstrap` command to use?", - choices=[PyPackageManager.POETRY, PyPackageManager.UV], + choices=[PyPackageManager.UV, PyPackageManager.POETRY], ).ask() if manager is None: - # Default to Poetry if user cancels - manager = PyPackageManager.POETRY + manager = PyPackageManager.UV save_py_package_manager(manager) return str(manager) @@ -186,7 +195,7 @@ def _bootstrap_python_project(project_dir: Path, manager: str) -> None: if manager == PyPackageManager.UV: logger.debug("Running `algokit project bootstrap uv`") bootstrap_uv(project_dir) - else: # Default to Poetry for backward compatibility + else: logger.debug("Running `algokit project bootstrap poetry`") bootstrap_poetry(project_dir) @@ -430,6 +439,7 @@ def bootstrap_env(project_dir: Path, *, ci_mode: bool) -> None: def bootstrap_poetry(project_dir: Path) -> None: + tool_command: list[str] = [] try: proc.run( ["poetry", "--version"], @@ -438,26 +448,28 @@ def bootstrap_poetry(project_dir: Path) -> None: try_install_poetry = False except OSError: try_install_poetry = True - if try_install_poetry: logger.info("Poetry not found; attempting to install it...") + tool_command = find_valid_tool_runner_command( + "Unable to find uv or pipx so that poetry can be installed; " + "please install uv via https://docs.astral.sh/uv/ " + "and then try `algokit project bootstrap poetry` again." + ) + tool_name = "uv" if is_uvx(tool_command) or is_uv(tool_command) else "pipx" if not questionary_extensions.prompt_confirm( - "We couldn't find `poetry`; can we install it for you via pipx so we can install Python dependencies?", + f"We couldn't find `poetry`; can we install it for you via {tool_name} " + "so we can install Python dependencies?", default=True, ): raise click.ClickException( - "Unable to install poetry via pipx; please install poetry " + f"Unable to install poetry via {tool_name}; please install poetry " "manually via https://python-poetry.org/docs/ and try `algokit project bootstrap poetry` again." ) - pipx_command = find_valid_pipx_command( - "Unable to find pipx install so that poetry can be installed; " - "please install pipx via https://pypa.github.io/pipx/ " - "and then try `algokit project bootstrap poetry` again." - ) + install_cmd = get_tool_install_command(tool_command, package="poetry") proc.run( - [*pipx_command, "install", "poetry"], + install_cmd, bad_return_code_error_message=( - "Unable to install poetry via pipx; please install poetry " + f"Unable to install poetry via {tool_name}; please install poetry " "manually via https://python-poetry.org/docs/ and try `algokit project bootstrap poetry` again." ), ) @@ -465,14 +477,23 @@ def bootstrap_poetry(project_dir: Path) -> None: logger.info("Installing Python dependencies and setting up Python virtual environment via Poetry") try: proc.run(["poetry", "install"], stdout_log_level=logging.INFO, cwd=project_dir) - except OSError as e: + except OSError: if try_install_poetry: - raise click.ClickException( - "Unable to access Poetry on PATH after installing it via pipx; " - "check pipx installations are on your path by running `pipx ensurepath` " - "and try `algokit project bootstrap poetry` again." - ) from e - raise # unexpected error, we already ran without IOError before + tool_name = "uv" if is_uvx(tool_command) or is_uv(tool_command) else "pipx" + logger.info( + "Poetry is not available on PATH yet after installation; retrying via %s tool runner", tool_name + ) + fallback_cmd = [*get_tool_run_command(tool_command, spec="poetry", binary="poetry"), "install"] + try: + proc.run(fallback_cmd, stdout_log_level=logging.INFO, cwd=project_dir) + return + except Exception as fallback_error: + raise click.ClickException( + f"Unable to access Poetry on PATH after installing it via {tool_name}; " + "and fallback execution failed. Please restart your terminal and try " + "`algokit project bootstrap poetry` again." + ) from fallback_error + raise def bootstrap_npm(project_dir: Path, *, ci_mode: bool) -> None: @@ -542,90 +563,86 @@ def migrate_pyproject_to_uv(project_dir: Path) -> None: ) from e -def bootstrap_uv(project_dir: Path) -> None: # noqa: C901 +def _ensure_uv_installed() -> bool: + """Ensure uv is installed, prompting to install if missing. Returns True if freshly installed.""" try: proc.run( ["uv", "--version"], bad_return_code_error_message="uv --version failed, please check your uv install", ) - try_install_uv = False + return False except OSError: - try_install_uv = True + pass - if try_install_uv: - logger.info("UV not found; attempting to install it...") - if not questionary_extensions.prompt_confirm( - "We couldn't find `uv`; can we install it for you via curl so we can install Python dependencies?", - default=True, - ): - raise click.ClickException( - "Unable to install uv; please install uv " - "manually via https://github.com/astral-sh/uv and try `algokit project bootstrap uv` again." - ) + logger.info("UV not found; attempting to install it...") + if not questionary_extensions.prompt_confirm( + "We couldn't find `uv`; can we install it for you so we can install Python dependencies?", + default=True, + ): + raise click.ClickException( + "Unable to install uv; please install uv " + "manually via https://docs.astral.sh/uv/ and try `algokit project bootstrap uv` again." + ) - # Use the standalone installer as recommended in the UV docs - if is_windows(): - cmd = ["powershell", "-ExecutionPolicy", "ByPass", "-c", "irm https://astral.sh/uv/install.ps1 | iex"] - try: - proc.run( - cmd, - bad_return_code_error_message=( - "Unable to install uv; please install uv " - "manually via https://github.com/astral-sh/uv and try `algokit project bootstrap uv` again." - ), - ) - except Exception as e: - raise click.ClickException( - "Failed to install uv. Please install it manually via " - "https://github.com/astral-sh/uv and try `algokit project bootstrap uv` again." - ) from e - else: - # For Unix platforms, use proc.run with sh -c to handle the pipe safely - try: - proc.run( - ["sh", "-c", "curl -LsSf https://astral.sh/uv/install.sh | sh"], - bad_return_code_error_message=( - "Unable to install uv; please install uv " - "manually via https://github.com/astral-sh/uv and try `algokit project bootstrap uv` again." - ), - ) - except Exception as e: - raise click.ClickException( - "Failed to install uv. Please install it manually via " - "https://github.com/astral-sh/uv and try `algokit project bootstrap uv` again." - ) from e + install_error_message = ( + "Unable to install uv; please install uv " + "manually via https://docs.astral.sh/uv/ and try `algokit project bootstrap uv` again." + ) - # Check if pyproject.toml contains poetry configuration + if is_windows(): + cmd = ["powershell", "-ExecutionPolicy", "ByPass", "-c", "irm https://astral.sh/uv/install.ps1 | iex"] + else: + cmd = ["sh", "-c", "curl -LsSf https://astral.sh/uv/install.sh | sh"] + + try: + proc.run(cmd, bad_return_code_error_message=install_error_message) + except Exception as e: + raise click.ClickException(install_error_message) from e + + return True + + +def _maybe_migrate_poetry_project(project_dir: Path) -> None: + """If the project uses Poetry, offer to migrate to uv-compatible format.""" pyproject_path = project_dir / "pyproject.toml" - is_poetry_project = pyproject_path.exists() and "[tool.poetry]" in pyproject_path.read_text("utf-8") - if is_poetry_project: - if questionary_extensions.prompt_confirm( - "Would you like to attempt to migrate the pyproject configuration to uv compliant format?\n" - "⚠️ This will run a third-party tool (https://mkniewallner.github.io/migrate-to-uv/) " - "that will attempt to convert your poetry project to uv. " - "You are advised to double check the migrated file and it's recommended to run this " - "in a version controlled repository to revert changes if needed.", - default=False, - ): - migrate_pyproject_to_uv(project_dir) - else: - raise click.ClickException( - "This project is configured to use Poetry. Please use `algokit project bootstrap poetry`, " - "set poetry as default package manager via `algokit config py-package-manager`, " - "or modify your pyproject.toml to be compatible with UV." - ) + if not pyproject_path.exists(): + return + + if "[tool.poetry]" not in pyproject_path.read_text("utf-8"): + return + + if questionary_extensions.prompt_confirm( + "Would you like to attempt to migrate the pyproject configuration to uv compliant format?\n" + "\u26a0\ufe0f This will run a third-party tool (https://mkniewallner.github.io/migrate-to-uv/) " + "that will attempt to convert your poetry project to uv. " + "You are advised to double check the migrated file and it's recommended to run this " + "in a version controlled repository to revert changes if needed.", + default=False, + ): + migrate_pyproject_to_uv(project_dir) + else: + raise click.ClickException( + "This project is configured to use Poetry. Please use `algokit project bootstrap poetry`, " + "set poetry as default package manager via `algokit config py-package-manager`, " + "or modify your pyproject.toml to be compatible with UV." + ) + + +def bootstrap_uv(project_dir: Path) -> None: + freshly_installed = _ensure_uv_installed() + + _maybe_migrate_poetry_project(project_dir) logger.info("Installing Python dependencies and setting up Python virtual environment via UV") try: - # Sync will create/update the virtual environment and install dependencies proc.run(["uv", "sync"], stdout_log_level=logging.INFO, cwd=project_dir) except OSError as e: - if try_install_uv: + if freshly_installed: raise click.ClickException( "Unable to access UV on PATH after installing it; " "try restarting your terminal and running `algokit project bootstrap uv` again." ) from e - raise # unexpected error, we already ran without IOError before + raise def get_min_algokit_version(project_dir: Path) -> str | None: diff --git a/src/algokit/core/project/run.py b/src/algokit/core/project/run.py index dfdd7bb9b..05f89d9e2 100644 --- a/src/algokit/core/project/run.py +++ b/src/algokit/core/project/run.py @@ -1,6 +1,7 @@ import dataclasses import logging import os +import shutil from concurrent.futures import ThreadPoolExecutor from pathlib import Path from typing import Any @@ -19,6 +20,21 @@ logger = logging.getLogger("rich") +def _normalize_legacy_runner_command(command: list[str]) -> list[str]: + """Normalize legacy runner commands to supported equivalents.""" + if command[:2] == ["poetry", "run"] and command[2:]: + if shutil.which("poetry"): + return command + if shutil.which("uv"): + logger.debug("poetry not found, rewriting 'poetry run' -> 'uv run' for: %s", " ".join(command)) + return ["uv", "run", *command[2:]] + raise click.ClickException( + "Unable to run legacy `poetry run` command because neither `poetry` nor `uv` is installed. " + "Install uv via https://docs.astral.sh/uv/ and then try again." + ) + return command + + @dataclasses.dataclass(kw_only=True) class ProjectCommand: """Represents a command to be executed within a project context. @@ -188,7 +204,8 @@ def run_command( for index, cmd in enumerate(command.commands): try: - resolved_command = resolve_command_path(cmd) + normalized_command = _normalize_legacy_runner_command(cmd) + resolved_command = resolve_command_path(normalized_command) if index == len(command.commands) - 1 and extra_args: resolved_command.extend(extra_args) except click.ClickException as e: diff --git a/src/algokit/core/tasks/analyze.py b/src/algokit/core/tasks/analyze.py index ef63e2afd..2b8a9d523 100644 --- a/src/algokit/core/tasks/analyze.py +++ b/src/algokit/core/tasks/analyze.py @@ -8,7 +8,7 @@ from pydantic import BaseModel, Field from algokit.core.proc import RunResult, run -from algokit.core.utils import find_valid_pipx_command +from algokit.core.utils import find_valid_tool_runner_command, get_tool_install_command, is_uvx logger = logging.getLogger(__name__) @@ -97,19 +97,21 @@ def ensure_tealer_installed() -> None: except Exception as e: logger.debug(e) logger.info("Tealer not found; attempting to install it...") - pipx_command = find_valid_pipx_command( - "Unable to find pipx install so that `tealer` static analyzer can be installed; " - "please install pipx via https://pypa.github.io/pipx/ " + tool_runner_command = find_valid_tool_runner_command( + "Unable to find uvx or pipx so that `tealer` can be installed; " + "please install uv via https://docs.astral.sh/uv/ " "and then try `algokit task analyze ...` again." ) + install_cmd = get_tool_install_command(tool_runner_command, package=f"tealer=={TEALER_VERSION}") + tool_name = "uv" if is_uvx(tool_runner_command) else "pipx" run( - [*pipx_command, "install", f"tealer=={TEALER_VERSION}"], + install_cmd, bad_return_code_error_message=( - "Unable to install tealer via pipx; please install tealer " + f"Unable to install tealer via {tool_name}; please install tealer " "manually and try `algokit task analyze ...` again." ), ) - logger.info("Tealer installed successfully via pipx!") + logger.info("Tealer installed successfully via %s!", tool_name) def generate_tealer_command(cur_file: Path, report_output_path: Path, detectors_to_exclude: list[str]) -> list[str]: diff --git a/src/algokit/core/typed_client_generation.py b/src/algokit/core/typed_client_generation.py index 5864c1d39..eea4177e7 100644 --- a/src/algokit/core/typed_client_generation.py +++ b/src/algokit/core/typed_client_generation.py @@ -15,8 +15,10 @@ from algokit.core.utils import ( extract_semantic_version, extract_version_triple, - find_valid_pipx_command, + find_valid_tool_runner_command, get_npm_command, + get_tool_list_command, + get_tool_run_command, ) logger = logging.getLogger(__name__) @@ -216,14 +218,46 @@ def format_contract_name(self, contract_name: str) -> str: def find_project_generate_command(self, version: str | None) -> list[str] | None: """ Try find the generate command in the project. + Checks uv-based projects first, then falls back to Poetry. """ + # Try uv first (modern projects) + result = self._find_project_command_via_uv(version) + if result is not None: + return result + + # Fall back to Poetry (legacy projects) + return self._find_project_command_via_poetry(version) + + def _find_project_command_via_uv(self, version: str | None) -> list[str] | None: + """Check if the generator is installed in a uv-managed project.""" + try: + result = proc.run(["uv", "pip", "show", PYTHON_PYPI_PACKAGE]) + if result.exit_code == 0: + generate_command = ["uv", "run", PYTHON_GENERATE_COMMAND] + if version is not None: + for line in result.output.splitlines(): + if line.startswith("Version:"): + installed_version = extract_version_triple(line.split(":", 1)[1].strip()) + if extract_version_triple(version) == installed_version: + return generate_command + return None # version mismatch + else: + return generate_command + except OSError: + pass + except ValueError: + pass + + return None + + def _find_project_command_via_poetry(self, version: str | None) -> list[str] | None: + """Check if the generator is installed in a Poetry-managed project.""" try: # Use the tree output as it puts the package info on the first line of the output result = proc.run(["poetry", "show", PYTHON_PYPI_PACKAGE, "--tree"]) if result.exit_code == 0: generate_command = ["poetry", "run", PYTHON_GENERATE_COMMAND] if version is not None: - installed_version = None lines = result.output.splitlines() if len(lines) > 0: installed_version = extract_version_triple(lines[0]) @@ -238,12 +272,12 @@ def find_project_generate_command(self, version: str | None) -> list[str] | None return None - def find_global_generate_command(self, pipx_command: list[str], version: str | None) -> list[str] | None: + def find_global_generate_command(self, tool_command: list[str], version: str | None) -> list[str] | None: """ Try find the generate command installed globally. """ try: - result = proc.run([*pipx_command, "list", "--short"]) + result = proc.run(get_tool_list_command(tool_command)) if result.exit_code == 0: generate_command = [PYTHON_GENERATE_COMMAND] for line in result.output.splitlines(): @@ -267,7 +301,7 @@ def find_generate_command(self, version: str | None) -> list[str]: Find Python generator command. If a matching version is installed at a project level, use that. If a matching version is installed at a global level, use that. - Otherwise, run the matching version via pipx. + Otherwise, run via uvx/pipx. """ logger.debug("Searching for project installed client generator") @@ -275,25 +309,20 @@ def find_generate_command(self, version: str | None) -> list[str]: if project_result is not None: return project_result - pipx_command = find_valid_pipx_command( - f"Unable to find pipx install so that the `{PYTHON_PYPI_PACKAGE}` can be run; " - "please install pipx via https://pypa.github.io/pipx/ " + tool_command = find_valid_tool_runner_command( + f"Unable to find uvx or pipx so that `{PYTHON_PYPI_PACKAGE}` can be run; " + "please install uv via https://docs.astral.sh/uv/ " "and then try `algokit generate client ...` again." ) logger.debug("Searching for globally installed client generator") - global_result = self.find_global_generate_command(pipx_command, version) + global_result = self.find_global_generate_command(tool_command, version) if global_result is not None: return global_result - # when not installed, run via pipx - logger.debug("No matching installed client generator found, run client generator via pipx") - return [ - *pipx_command, - "run", - f"--spec={PYTHON_PYPI_PACKAGE}{f'=={version}' if version is not None else ''}", - PYTHON_GENERATE_COMMAND, - ] + spec = f"{PYTHON_PYPI_PACKAGE}{f'=={version}' if version is not None else ''}" + logger.debug("No matching installed client generator found, running via %s", tool_command[0]) + return get_tool_run_command(tool_command, spec=spec, binary=PYTHON_GENERATE_COMMAND) class TypeScriptClientGenerator(ClientGenerator, language="typescript", extension=".ts"): diff --git a/src/algokit/core/utils.py b/src/algokit/core/utils.py index cfff91090..e54f03aa0 100644 --- a/src/algokit/core/utils.py +++ b/src/algokit/core/utils.py @@ -103,30 +103,66 @@ def run_with_animation( return result -def find_valid_pipx_command(error_message: str) -> list[str]: - for pipx_command in get_candidate_pipx_commands(): +def find_valid_tool_runner_command(error_message: str) -> list[str]: + """Find uvx (preferred) or pipx command. Returns base command list.""" + # prefer uvx (uv's tool runner) + uvx_path = shutil.which("uvx") + if uvx_path: + return ["uvx"] + + uv_path = shutil.which("uv") + if uv_path: + return ["uv"] + + for pipx_command in _get_candidate_pipx_commands(): try: pipx_version_result = proc.run([*pipx_command, "--version"]) except OSError: - pass # in case of path/permission issues, go to next candidate + pass else: if pipx_version_result.exit_code == 0: return pipx_command - # If pipx isn't found in global path or python -m pipx then bail out - # this is an exceptional circumstance since pipx should always be present with algokit - # since it's installed with brew / winget as a dependency, and otherwise is used to install algokit raise click.ClickException(error_message) -def get_candidate_pipx_commands() -> Iterator[list[str]]: - # first try is pipx via PATH +def _get_candidate_pipx_commands() -> Iterator[list[str]]: yield ["pipx"] - # otherwise try getting an interpreter with pipx installed as a module, - # this won't work if pipx is installed in its own venv but worth a shot for python_path in get_python_paths(): yield [python_path, "-m", "pipx"] +def is_uvx(command: list[str]) -> bool: + """Check if the resolved tool runner is uvx.""" + return len(command) == 1 and command[0] == "uvx" + + +def is_uv(command: list[str]) -> bool: + return len(command) == 1 and command[0] == "uv" + + +def get_tool_run_command(base_command: list[str], *, spec: str, binary: str) -> list[str]: + """Build a command to run a tool via uvx or pipx.""" + if is_uvx(base_command): + return ["uvx", f"--from={spec}", binary] + if is_uv(base_command): + return ["uv", "tool", "run", f"--from={spec}", binary] + return [*base_command, "run", f"--spec={spec}", binary] + + +def get_tool_install_command(base_command: list[str], *, package: str) -> list[str]: + """Build a command to install a tool via uv or pipx.""" + if is_uvx(base_command) or is_uv(base_command): + return ["uv", "tool", "install", package] + return [*base_command, "install", package] + + +def get_tool_list_command(base_command: list[str]) -> list[str]: + """Build a command to list installed tools via uv or pipx.""" + if is_uvx(base_command) or is_uv(base_command): + return ["uv", "tool", "list"] + return [*base_command, "list", "--short"] + + def get_npm_command(error_message: str, *, is_npx: bool = False) -> list[str]: command = "npx" if is_npx else "npm" path = shutil.which(command) @@ -204,6 +240,37 @@ def is_windows() -> bool: return platform.system() == "Windows" +def find_all_on_path(command: str) -> list[Path]: + matches: list[Path] = [] + seen: set[str] = set() + + for path_entry in environ.get("PATH", "").split(os.pathsep): + if not path_entry: + continue + + match = shutil.which(command, path=path_entry) + if not match: + continue + + match_path = Path(match) + try: + canonical_path = match_path.resolve() + except OSError: + canonical_path = match_path.absolute() + + dedupe_key = str(canonical_path) + if is_windows(): + dedupe_key = dedupe_key.lower() + + if dedupe_key in seen: + continue + + seen.add(dedupe_key) + matches.append(match_path) + + return matches + + def is_wsl() -> bool: """ detects if Python is running in WSL diff --git a/tests/compile/test_python.py b/tests/compile/test_python.py index cf0610522..41c62aeeb 100644 --- a/tests/compile/test_python.py +++ b/tests/compile/test_python.py @@ -38,6 +38,7 @@ def output_path(cwd: Path) -> Path: def test_compile_py_help(mocker: MockerFixture) -> None: proc_mock = ProcMock() + proc_mock.should_bad_exit_on(["uv", "run", "puyapy", "--version"], exit_code=1, output=["uv: not found"]) proc_mock.set_output(["poetry", "run", "puyapy", "--version"], output=["puyapy 1.0.0"]) proc_mock.set_output(["poetry", "run", "puyapy", "-h"], output=["Puyapy help"]) @@ -50,15 +51,14 @@ def test_compile_py_help(mocker: MockerFixture) -> None: def test_puyapy_is_not_installed_anywhere(dummy_contract_path: Path, mocker: MockerFixture) -> None: proc_mock = ProcMock() + proc_mock.should_bad_exit_on(["uv", "run", "puyapy", "--version"], exit_code=1, output=["uv: not found"]) proc_mock.should_bad_exit_on(["poetry", "run", "puyapy", "--version"], exit_code=1, output=["Puyapy not found"]) proc_mock.should_bad_exit_on(["puyapy", "--version"], exit_code=1, output=["Puyapy not found"]) - proc_mock.set_output(["pipx", "--version"], ["1.0.0"]) - - proc_mock.set_output(["pipx", "install", "puya"], ["Puyapy is installed"]) - proc_mock.set_output(["puyapy", str(dummy_contract_path)], ["Done"]) + proc_mock.set_output(["uvx", "--from=puyapy", "puyapy", str(dummy_contract_path)], ["Done"]) mocker.patch("algokit.core.proc.Popen").side_effect = proc_mock.popen + mocker.patch("algokit.core.utils.shutil.which", return_value="/bin/uvx") result = invoke(f"compile python {_normalize_path(dummy_contract_path)}") @@ -71,13 +71,14 @@ def test_specificed_puyapy_version_is_not_installed(dummy_contract_path: Path, m target_version = "1.1.0" proc_mock = ProcMock() + proc_mock.should_bad_exit_on(["uv", "run", "puyapy", "--version"], exit_code=1, output=["uv: not found"]) proc_mock.set_output(["poetry", "run", "puyapy", "--version"], output=[f"puyapy {current_version}"]) proc_mock.should_bad_exit_on(["puyapy", "--version"], exit_code=1, output=["Puyapy not found"]) - proc_mock.set_output(["pipx", "--version"], ["1.0.0"]) - proc_mock.set_output(["pipx", "run", f"puya=={target_version}", str(dummy_contract_path)], ["Done"]) + proc_mock.set_output(["uvx", f"--from=puyapy=={target_version}", "puyapy", str(dummy_contract_path)], ["Done"]) mocker.patch("algokit.core.proc.Popen").side_effect = proc_mock.popen + mocker.patch("algokit.core.utils.shutil.which", return_value="/bin/uvx") result = invoke(f"compile --version {target_version} py {_normalize_path(dummy_contract_path)}") @@ -87,6 +88,7 @@ def test_specificed_puyapy_version_is_not_installed(dummy_contract_path: Path, m def test_puyapy_is_installed_in_project(dummy_contract_path: Path, mocker: MockerFixture) -> None: proc_mock = ProcMock() + proc_mock.should_bad_exit_on(["uv", "run", "puyapy", "--version"], exit_code=1, output=["uv: not found"]) proc_mock.set_output(["poetry", "run", "puyapy", "--version"], output=["puyapy 1.0.0"]) proc_mock.set_output(["poetry", "run", "puyapy", str(dummy_contract_path)], ["Done"]) @@ -101,6 +103,7 @@ def test_puyapy_is_installed_in_project(dummy_contract_path: Path, mocker: Mocke def test_puyapy_is_installed_globally(dummy_contract_path: Path, mocker: MockerFixture) -> None: proc_mock = ProcMock() + proc_mock.should_bad_exit_on(["uv", "run", "puyapy", "--version"], exit_code=1, output=["uv: not found"]) proc_mock.should_bad_exit_on(["poetry", "run", "puyapy", "--version"], exit_code=1, output=["Puyapy not found"]) proc_mock.set_output(["puyapy", "--version"], output=["puyapy 1.0.0"]) diff --git a/tests/compile/test_python.test_compile_py_help.approved.txt b/tests/compile/test_python.test_compile_py_help.approved.txt index 4239a0ef4..40045bd3b 100644 --- a/tests/compile/test_python.test_compile_py_help.approved.txt +++ b/tests/compile/test_python.test_compile_py_help.approved.txt @@ -1,3 +1,5 @@ +DEBUG: Running 'uv run puyapy --version' in '{current_working_directory}' +DEBUG: uv: uv: not found DEBUG: Running 'poetry run puyapy --version' in '{current_working_directory}' DEBUG: poetry: puyapy 1.0.0 DEBUG: Running 'poetry run puyapy -h' in '{current_working_directory}' diff --git a/tests/compile/test_python.test_puyapy_is_installed_globally.approved.txt b/tests/compile/test_python.test_puyapy_is_installed_globally.approved.txt index e08133acc..a539deec5 100644 --- a/tests/compile/test_python.test_puyapy_is_installed_globally.approved.txt +++ b/tests/compile/test_python.test_puyapy_is_installed_globally.approved.txt @@ -1,3 +1,5 @@ +DEBUG: Running 'uv run puyapy --version' in '{current_working_directory}' +DEBUG: uv: uv: not found DEBUG: Running 'poetry run puyapy --version' in '{current_working_directory}' DEBUG: poetry: Puyapy not found DEBUG: Running 'puyapy --version' in '{current_working_directory}' diff --git a/tests/compile/test_python.test_puyapy_is_installed_in_project.approved.txt b/tests/compile/test_python.test_puyapy_is_installed_in_project.approved.txt index ec7a6523a..840564fba 100644 --- a/tests/compile/test_python.test_puyapy_is_installed_in_project.approved.txt +++ b/tests/compile/test_python.test_puyapy_is_installed_in_project.approved.txt @@ -1,3 +1,5 @@ +DEBUG: Running 'uv run puyapy --version' in '{current_working_directory}' +DEBUG: uv: uv: not found DEBUG: Running 'poetry run puyapy --version' in '{current_working_directory}' DEBUG: poetry: puyapy 1.0.0 DEBUG: Running 'poetry run puyapy {current_working_directory}/tests/compile/dummy_contract.py' in '{current_working_directory}' diff --git a/tests/compile/test_python.test_puyapy_is_not_installed_anywhere.approved.txt b/tests/compile/test_python.test_puyapy_is_not_installed_anywhere.approved.txt index d512daa25..a80ae7dbf 100644 --- a/tests/compile/test_python.test_puyapy_is_not_installed_anywhere.approved.txt +++ b/tests/compile/test_python.test_puyapy_is_not_installed_anywhere.approved.txt @@ -1,11 +1,9 @@ +DEBUG: Running 'uv run puyapy --version' in '{current_working_directory}' +DEBUG: uv: uv: not found DEBUG: Running 'poetry run puyapy --version' in '{current_working_directory}' DEBUG: poetry: Puyapy not found DEBUG: Running 'puyapy --version' in '{current_working_directory}' DEBUG: puyapy: Puyapy not found -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: 1.0.0 -DEBUG: Running 'pipx run --spec=puyapy puyapy {current_working_directory}/tests/compile/dummy_contract.py' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -STDOUT -STDERR +DEBUG: Running 'uvx --from=puyapy puyapy {current_working_directory}/tests/compile/dummy_contract.py' in '{current_working_directory}' +DEBUG: uvx: Done +Done diff --git a/tests/compile/test_python.test_specificed_puyapy_version_is_not_installed.approved.txt b/tests/compile/test_python.test_specificed_puyapy_version_is_not_installed.approved.txt index 83e05df4e..df96629f9 100644 --- a/tests/compile/test_python.test_specificed_puyapy_version_is_not_installed.approved.txt +++ b/tests/compile/test_python.test_specificed_puyapy_version_is_not_installed.approved.txt @@ -1,11 +1,9 @@ +DEBUG: Running 'uv run puyapy --version' in '{current_working_directory}' +DEBUG: uv: uv: not found DEBUG: Running 'poetry run puyapy --version' in '{current_working_directory}' DEBUG: poetry: puyapy 1.0.0 DEBUG: Running 'puyapy --version' in '{current_working_directory}' DEBUG: puyapy: Puyapy not found -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: 1.0.0 -DEBUG: Running 'pipx run --spec=puyapy==1.1.0 puyapy {current_working_directory}/tests/compile/dummy_contract.py' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -STDOUT -STDERR +DEBUG: Running 'uvx --from=puyapy==1.1.0 puyapy {current_working_directory}/tests/compile/dummy_contract.py' in '{current_working_directory}' +DEBUG: uvx: Done +Done diff --git a/tests/doctor/test_doctor.py b/tests/doctor/test_doctor.py index 68503d5af..322a1dc18 100644 --- a/tests/doctor/test_doctor.py +++ b/tests/doctor/test_doctor.py @@ -54,6 +54,7 @@ def _mock_happy_values(proc_mock: ProcMock) -> None: proc_mock.set_output(["git", "--version"], ["git version 2.37.1 (Apple Git-137.1)"]) proc_mock.set_output(["python", "--version"], ["Python 3.10.0"]) proc_mock.set_output(["python3", "--version"], ["Python 3.11.0"]) + proc_mock.set_output(["uv", "--version"], ["uv 0.6.0"]) proc_mock.set_output(["pipx", "--version"], ["1.1.0"]) proc_mock.set_output(["poetry", "--version"], ["blah blah", "", "Poetry (version 1.2.2)"]) proc_mock.set_output(["node", "--version"], ["v18.12.1"]) @@ -148,6 +149,7 @@ def test_doctor_with_docker_compose_version_unparseable(proc_mock: ProcMock) -> ["git", "--version"], ["python", "--version"], ["python3", "--version"], + ["uv", "--version"], ["pipx", "--version"], ["poetry", "--version"], ["node", "--version"], @@ -221,7 +223,7 @@ def test_npm_permission_denied(proc_mock: ProcMock) -> None: result = invoke("doctor") - assert result.exit_code == 1 + assert result.exit_code == 0 verify(result.output, scrubber=make_output_scrubber()) diff --git a/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[linux].approved.txt b/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[linux].approved.txt index e78b2d5d7..40e788e84 100644 --- a/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[linux].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[linux].approved.txt @@ -8,9 +8,10 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: I AM A TEAPOT DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: I AM A TEAPOT +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: I AM A TEAPOT DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: I AM A TEAPOT -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: I AM A TEAPOT DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: I AM A TEAPOT @@ -30,6 +31,8 @@ python: Command exited with code: -1 I AM A TEAPOT python3: Command exited with code: -1 I AM A TEAPOT +uv: Command exited with code: -1 + I AM A TEAPOT pipx: Command exited with code: -1 I AM A TEAPOT poetry: Command exited with code: -1 diff --git a/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[macOS].approved.txt b/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[macOS].approved.txt index 452c66ea4..e13eca0ac 100644 --- a/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[macOS].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[macOS].approved.txt @@ -8,9 +8,10 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: I AM A TEAPOT DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: I AM A TEAPOT +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: I AM A TEAPOT DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: I AM A TEAPOT -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: I AM A TEAPOT DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: I AM A TEAPOT @@ -32,6 +33,8 @@ python: Command exited with code: -1 I AM A TEAPOT python3: Command exited with code: -1 I AM A TEAPOT +uv: Command exited with code: -1 + I AM A TEAPOT pipx: Command exited with code: -1 I AM A TEAPOT poetry: Command exited with code: -1 diff --git a/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[windows].approved.txt b/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[windows].approved.txt index f08da2249..296929287 100644 --- a/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[windows].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_all_commands_bad_exit[windows].approved.txt @@ -8,9 +8,10 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: I AM A TEAPOT DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: I AM A TEAPOT +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: I AM A TEAPOT DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: I AM A TEAPOT -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: I AM A TEAPOT DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: I AM A TEAPOT @@ -32,6 +33,8 @@ python: Command exited with code: -1 I AM A TEAPOT python3: Command exited with code: -1 I AM A TEAPOT +uv: Command exited with code: -1 + I AM A TEAPOT pipx: Command exited with code: -1 I AM A TEAPOT poetry: Command exited with code: -1 diff --git a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[linux].approved.txt b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[linux].approved.txt index e42f875ac..554df8f38 100644 --- a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[linux].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[linux].approved.txt @@ -8,9 +8,10 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: Command not found DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: Command not found +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: Command not found DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: Command not found -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Command not found DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: Command not found @@ -27,13 +28,15 @@ git: Command not found! Git required to run `algokit init`; install via https://github.com/git-guides/install-git python: Command not found! python3: Command not found! +uv: Command not found! + uv is the recommended tool runner for AlgoKit; + install via https://docs.astral.sh/uv/ pipx: Command not found! - pipx is required if poetry is not installed in order to install it automatically; + pipx can be used as a fallback tool runner if uv is not installed; install via https://pypa.github.io/pipx/ poetry: Command not found! - Poetry is required for some Python-based templates; - install via `algokit project bootstrap` within project directory, or via: - https://python-poetry.org/docs/#installation + Poetry may be needed for older Python-based templates; + install via https://python-poetry.org/docs/#installation node: Command not found! Node.js is required for some Node.js-based templates; install via `algokit project bootstrap` within project directory, or via: diff --git a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[macOS].approved.txt b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[macOS].approved.txt index bb19a1e32..1f48feb23 100644 --- a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[macOS].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[macOS].approved.txt @@ -8,9 +8,10 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: Command not found DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: Command not found +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: Command not found DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: Command not found -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Command not found DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: Command not found @@ -29,13 +30,15 @@ git: Command not found! Git required to run `algokit init`; install via https://github.com/git-guides/install-git python: Command not found! python3: Command not found! +uv: Command not found! + uv is the recommended tool runner for AlgoKit; + install via https://docs.astral.sh/uv/ pipx: Command not found! - pipx is required if poetry is not installed in order to install it automatically; + pipx can be used as a fallback tool runner if uv is not installed; install via https://pypa.github.io/pipx/ poetry: Command not found! - Poetry is required for some Python-based templates; - install via `algokit project bootstrap` within project directory, or via: - https://python-poetry.org/docs/#installation + Poetry may be needed for older Python-based templates; + install via https://python-poetry.org/docs/#installation node: Command not found! Node.js is required for some Node.js-based templates; install via `algokit project bootstrap` within project directory, or via: diff --git a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[windows].approved.txt b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[windows].approved.txt index bd58ce708..09ec30e9e 100644 --- a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[windows].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[windows].approved.txt @@ -8,9 +8,10 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: Command not found DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: Command not found +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: Command not found DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: Command not found -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Command not found DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: Command not found @@ -30,13 +31,15 @@ git: Command not found! or via https://github.com/git-guides/install-git#install-git-on-windows python: Command not found! python3: Command not found! +uv: Command not found! + uv is the recommended tool runner for AlgoKit; + install via https://docs.astral.sh/uv/ pipx: Command not found! - pipx is required if poetry is not installed in order to install it automatically; + pipx can be used as a fallback tool runner if uv is not installed; install via https://pypa.github.io/pipx/ poetry: Command not found! - Poetry is required for some Python-based templates; - install via `algokit project bootstrap` within project directory, or via: - https://python-poetry.org/docs/#installation + Poetry may be needed for older Python-based templates; + install via https://python-poetry.org/docs/#installation node: Command not found! Node.js is required for some Node.js-based templates; install via `algokit project bootstrap` within project directory, or via: diff --git a/tests/doctor/test_doctor.test_doctor_successful[linux].approved.txt b/tests/doctor/test_doctor.test_doctor_successful[linux].approved.txt index 8288c32b1..62b6c0bd9 100644 --- a/tests/doctor/test_doctor.test_doctor_successful[linux].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_successful[linux].approved.txt @@ -8,12 +8,12 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: Python 3.10.0 DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm --version' in '{current_working_directory}' @@ -27,6 +27,7 @@ docker compose: 2.12.2 git: 2.37.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_doctor_successful[macOS].approved.txt b/tests/doctor/test_doctor.test_doctor_successful[macOS].approved.txt index 07262e72e..fcf0cffd2 100644 --- a/tests/doctor/test_doctor.test_doctor_successful[macOS].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_successful[macOS].approved.txt @@ -8,12 +8,12 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: Python 3.10.0 DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm --version' in '{current_working_directory}' @@ -30,6 +30,7 @@ docker compose: 2.12.2 git: 2.37.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_doctor_successful[windows].approved.txt b/tests/doctor/test_doctor.test_doctor_successful[windows].approved.txt index f1b84287a..e57fe39bc 100644 --- a/tests/doctor/test_doctor.test_doctor_successful[windows].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_successful[windows].approved.txt @@ -8,12 +8,12 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: Python 3.10.0 DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm.cmd --version' in '{current_working_directory}' @@ -29,6 +29,7 @@ docker compose: 2.12.2 git: 2.37.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_doctor_with_copy.approved.txt b/tests/doctor/test_doctor.test_doctor_with_copy.approved.txt index 07262e72e..fcf0cffd2 100644 --- a/tests/doctor/test_doctor.test_doctor_with_copy.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_with_copy.approved.txt @@ -8,12 +8,12 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: Python 3.10.0 DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm --version' in '{current_working_directory}' @@ -30,6 +30,7 @@ docker compose: 2.12.2 git: 2.37.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_gitpod.approved.txt b/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_gitpod.approved.txt index c8d076d9f..6b74929c9 100644 --- a/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_gitpod.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_gitpod.approved.txt @@ -8,12 +8,12 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: Python 3.10.0 DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm --version' in '{current_working_directory}' @@ -30,6 +30,7 @@ docker compose: 2.10.0-gitpod.0 git: 2.37.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_unparseable.approved.txt b/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_unparseable.approved.txt index 05b43bcd1..5f57d6968 100644 --- a/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_unparseable.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_unparseable.approved.txt @@ -9,12 +9,12 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: Python 3.10.0 DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm --version' in '{current_working_directory}' @@ -34,6 +34,7 @@ docker compose: {"version": "TEAPOT"} git: 2.37.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_warning.approved.txt b/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_warning.approved.txt index b48ee2e16..a8ad1b08e 100644 --- a/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_warning.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_warning.approved.txt @@ -8,12 +8,12 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: Python 3.10.0 DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm --version' in '{current_working_directory}' @@ -32,6 +32,7 @@ docker compose: 2.1.3 git: 2.37.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_doctor_with_weird_values_on_mac.approved.txt b/tests/doctor/test_doctor.test_doctor_with_weird_values_on_mac.approved.txt index cc7820a12..488fbf0f7 100644 --- a/tests/doctor/test_doctor.test_doctor_with_weird_values_on_mac.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_with_weird_values_on_mac.approved.txt @@ -8,12 +8,12 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: Python 3.10.0 DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm --version' in '{current_working_directory}' @@ -29,6 +29,7 @@ docker compose: 2.12.2 git: 2.37.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_doctor_with_weird_values_on_windows.approved.txt b/tests/doctor/test_doctor.test_doctor_with_weird_values_on_windows.approved.txt index fc6cf3da3..c4b7f4f02 100644 --- a/tests/doctor/test_doctor.test_doctor_with_weird_values_on_windows.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_with_weird_values_on_windows.approved.txt @@ -8,12 +8,12 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: Python 3.10.0 DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm.cmd --version' in '{current_working_directory}' @@ -30,6 +30,7 @@ docker compose: 2.12.2 git: 2.31.0.windows.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_new_algokit_version_available.approved.txt b/tests/doctor/test_doctor.test_new_algokit_version_available.approved.txt index d56dee2e5..f699bca80 100644 --- a/tests/doctor/test_doctor.test_new_algokit_version_available.approved.txt +++ b/tests/doctor/test_doctor.test_new_algokit_version_available.approved.txt @@ -8,12 +8,12 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: Python 3.10.0 DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm --version' in '{current_working_directory}' @@ -30,6 +30,7 @@ docker compose: 2.12.2 git: 2.37.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_npm_permission_denied.approved.txt b/tests/doctor/test_doctor.test_npm_permission_denied.approved.txt index 103704a6c..ae6419819 100644 --- a/tests/doctor/test_doctor.test_npm_permission_denied.approved.txt +++ b/tests/doctor/test_doctor.test_npm_permission_denied.approved.txt @@ -8,12 +8,12 @@ DEBUG: Running 'python --version' in '{current_working_directory}' DEBUG: python: Python 3.10.0 DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm --version' in '{current_working_directory}' @@ -30,6 +30,7 @@ docker compose: 2.12.2 git: 2.37.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_unexpected_exception_locating_executable.approved.txt b/tests/doctor/test_doctor.test_unexpected_exception_locating_executable.approved.txt index dd9d4a17c..60384a82b 100644 --- a/tests/doctor/test_doctor.test_unexpected_exception_locating_executable.approved.txt +++ b/tests/doctor/test_doctor.test_unexpected_exception_locating_executable.approved.txt @@ -10,12 +10,12 @@ DEBUG: Failed to locate python: OH NO DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 DEBUG: Failed to locate python3: OH NO +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm --version' in '{current_working_directory}' @@ -32,6 +32,7 @@ docker compose: 2.12.2 git: 2.37.1 python: 3.10.0f (location: unknown) python3: 3.11.0f (location: unknown) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/doctor/test_doctor.test_unparseable_python_version.approved.txt b/tests/doctor/test_doctor.test_unparseable_python_version.approved.txt index 368395e5b..73c311da8 100644 --- a/tests/doctor/test_doctor.test_unparseable_python_version.approved.txt +++ b/tests/doctor/test_doctor.test_unparseable_python_version.approved.txt @@ -10,12 +10,12 @@ DEBUG: python: 1-2-3 DEBUG: python: abc DEBUG: Running 'python3 --version' in '{current_working_directory}' DEBUG: python3: Python 3.11.0 +DEBUG: Running 'uv --version' in '{current_working_directory}' +DEBUG: uv: uv 0.6.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: blah blah DEBUG: poetry: -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Running 'node --version' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm --version' in '{current_working_directory}' @@ -32,6 +32,7 @@ docker compose: 2.12.2 git: 2.37.1 python: 1-2-3 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) +uv: 0.6.0 pipx: 1.1.0 poetry: 1.2.2 node: 18.12.1 diff --git a/tests/explore/test_explore.py b/tests/explore/test_explore.py index 87678f0b2..e20e0ee5e 100644 --- a/tests/explore/test_explore.py +++ b/tests/explore/test_explore.py @@ -16,7 +16,7 @@ def test_explore(command: str, mocker: MockerFixture) -> None: assert result.exit_code == 0 verify( - get_combined_verify_output(result.output, "launch args", launch_mock.call_args), + get_combined_verify_output(result.output, "launch args", str(launch_mock.call_args)), options=NamerFactory.with_parameters(command or "localnet"), ) diff --git a/tests/generate/test_generate_client.py b/tests/generate/test_generate_client.py index 99273297d..d283ff93c 100644 --- a/tests/generate/test_generate_client.py +++ b/tests/generate/test_generate_client.py @@ -36,7 +36,7 @@ def _get_npm_command() -> str: def _get_python_generate_command(version: str | None, application_json: Path, expected_output_path: Path) -> str: return ( - f"pipx run --spec={PYTHON_PYPI_PACKAGE}{f'=={version}' if version is not None else ''} " + f"uvx --from={PYTHON_PYPI_PACKAGE}{f'=={version}' if version is not None else ''} " f"algokitgen-py -a {application_json} -o {expected_output_path}" ) @@ -86,6 +86,7 @@ def which_mock(mocker: MockerFixture) -> WhichMock: which_mock.add("npx") which_mock.add("npm") which_mock.add("pipx") + which_mock.add("uvx") mocker.patch("algokit.core.typed_client_generation.shutil.which").side_effect = which_mock.which return which_mock @@ -122,17 +123,19 @@ def test_generate_client_python( expected_output_path: Path, request: pytest.FixtureRequest, ) -> None: + proc_mock.should_bad_exit_on(["uv", "pip", "show", PYTHON_PYPI_PACKAGE]) proc_mock.should_bad_exit_on(["poetry", "show", PYTHON_PYPI_PACKAGE, "--tree"]) - proc_mock.should_bad_exit_on(["pipx", "list", "--short"]) + proc_mock.should_bad_exit_on(["uv", "tool", "list"]) result = invoke(f"generate client {application_json.name} {options}", cwd=application_json.parent) assert result.exit_code == 0 + option_args = options.split() verify( _normalize_output(result.output), namer=PyTestNamer(request), - options=NamerFactory.with_parameters(*options.split()), + options=NamerFactory.with_parameters(*option_args), ) - version = options.split()[-1] if "--version" in options or "-v" in options else None + version = option_args[-1] if "--version" in options or "-v" in options else None assert len(proc_mock.called) == 4 # noqa: PLR2004 assert " ".join(proc_mock.called[3].command).startswith( _get_python_generate_command(version, application_json, expected_output_path) @@ -154,9 +157,10 @@ def test_python_generator_is_installed_in_project(application_json: Path, proc_m @pytest.mark.usefixtures("proc_mock") def test_python_generator_is_installed_globally(application_json: Path, proc_mock: ProcMock) -> None: + proc_mock.should_bad_exit_on(["uv", "pip", "show", PYTHON_PYPI_PACKAGE]) proc_mock.should_bad_exit_on(["poetry", "show", PYTHON_PYPI_PACKAGE, "--tree"]) proc_mock.set_output( - ["pipx", "list", "--short"], + ["uv", "tool", "list"], output=["algokit 1.13.0", "poetry 1.6.1", f"{PYTHON_PYPI_PACKAGE} 1.1.2"], ) @@ -168,12 +172,13 @@ def test_python_generator_is_installed_globally(application_json: Path, proc_moc @pytest.mark.usefixtures("proc_mock") def test_python_generator_version_is_not_installed_anywhere(application_json: Path, proc_mock: ProcMock) -> None: + proc_mock.should_bad_exit_on(["uv", "pip", "show", PYTHON_PYPI_PACKAGE]) proc_mock.set_output( ["poetry", "show", PYTHON_PYPI_PACKAGE, "--tree"], output=[f"{PYTHON_PYPI_PACKAGE} 1.1.2 Algorand typed client Generator", "└── algokit-utils 2.2.1"], ) proc_mock.set_output( - ["pipx", "list", "--short"], + ["uv", "tool", "list"], output=["algokit 1.13.0", "poetry 1.6.1", f"{PYTHON_PYPI_PACKAGE} 1.1.2"], ) @@ -187,8 +192,10 @@ def test_python_generator_version_is_not_installed_anywhere(application_json: Pa @pytest.mark.usefixtures("proc_mock") def test_pipx_missing(application_json: Path, mocker: MockerFixture, proc_mock: ProcMock) -> None: + proc_mock.should_bad_exit_on(["uv", "pip", "show", PYTHON_PYPI_PACKAGE]) proc_mock.should_bad_exit_on(["poetry", "show", PYTHON_PYPI_PACKAGE, "--tree"]) - mocker.patch("algokit.core.utils.get_candidate_pipx_commands", return_value=[]) + mocker.patch("algokit.core.utils.shutil.which", return_value=None) + mocker.patch("algokit.core.utils._get_candidate_pipx_commands", return_value=[]) result = invoke(f"generate client -o client.py -l python {application_json.name}", cwd=application_json.parent) assert result.exit_code == 1 @@ -204,8 +211,9 @@ def test_pipx_missing(application_json: Path, mocker: MockerFixture, proc_mock: def test_generate_client_python_arc32_filename( proc_mock: ProcMock, arc32_json: Path, options: str, expected_output_path: Path ) -> None: + proc_mock.should_bad_exit_on(["uv", "pip", "show", PYTHON_PYPI_PACKAGE]) proc_mock.should_bad_exit_on(["poetry", "show", PYTHON_PYPI_PACKAGE, "--tree"]) - proc_mock.should_bad_exit_on(["pipx", "list", "--short"]) + proc_mock.should_bad_exit_on(["uv", "tool", "list"]) result = invoke(f"generate client {options} {arc32_json.name}", cwd=arc32_json.parent) @@ -227,8 +235,9 @@ def test_generate_client_python_arc56_filename( options: str, expected_output_path: Path, ) -> None: + proc_mock.should_bad_exit_on(["uv", "pip", "show", PYTHON_PYPI_PACKAGE]) proc_mock.should_bad_exit_on(["poetry", "show", PYTHON_PYPI_PACKAGE, "--tree"]) - proc_mock.should_bad_exit_on(["pipx", "list", "--short"]) + proc_mock.should_bad_exit_on(["uv", "tool", "list"]) result = invoke(f"generate client {options} {arc56_json.name}", cwd=arc56_json.parent) @@ -252,8 +261,9 @@ def test_generate_client_python_multiple_app_specs_in_directory( options: str, expected_output_path: Path, ) -> None: + proc_mock.should_bad_exit_on(["uv", "pip", "show", PYTHON_PYPI_PACKAGE]) proc_mock.should_bad_exit_on(["poetry", "show", PYTHON_PYPI_PACKAGE, "--tree"]) - proc_mock.should_bad_exit_on(["pipx", "list", "--short"]) + proc_mock.should_bad_exit_on(["uv", "tool", "list"]) result = invoke(f"generate client {options} .", cwd=arc56_json.parent) @@ -295,12 +305,13 @@ def test_generate_client_typescript( result = invoke(f"generate client {application_json.name} {options}", cwd=application_json.parent) assert result.exit_code == 0 + option_args = options.split() verify( _normalize_output(result.output), namer=PyTestNamer(request), - options=NamerFactory.with_parameters(*options.split()), + options=NamerFactory.with_parameters(*option_args), ) - version = options.split()[-1] if "--version" in options or "-v" in options else "latest" + version = option_args[-1] if "--version" in options or "-v" in options else "latest" assert len(proc_mock.called) == 3 # noqa: PLR2004 assert " ".join(proc_mock.called[2].command).startswith( _get_typescript_generate_command(version, application_json, expected_output_path) diff --git a/tests/generate/test_generate_client.test_generate_client_no_app_spec_found.approved.txt b/tests/generate/test_generate_client.test_generate_client_no_app_spec_found.approved.txt index 1ce175b48..a2e5aa1eb 100644 --- a/tests/generate/test_generate_client.test_generate_client_no_app_spec_found.approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_no_app_spec_found.approved.txt @@ -1,5 +1,5 @@ DEBUG: Searching for project installed client generator -DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR Error: No app specs found diff --git a/tests/generate/test_generate_client.test_generate_client_output_path_is_dir.approved.txt b/tests/generate/test_generate_client.test_generate_client_output_path_is_dir.approved.txt index 1f0b38813..1ce0f0aee 100644 --- a/tests/generate/test_generate_client.test_generate_client_output_path_is_dir.approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_output_path_is_dir.approved.txt @@ -1,5 +1,5 @@ DEBUG: Searching for project installed client generator -DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR ERROR: Could not output to hello_world_app.py as it already exists and is a directory diff --git a/tests/generate/test_generate_client.test_generate_client_python[--output {contract_name}.py-hello_world_app.py].approved.txt b/tests/generate/test_generate_client.test_generate_client_python[--output {contract_name}.py-hello_world_app.py].approved.txt index 13b76eaa3..1bc267577 100644 --- a/tests/generate/test_generate_client.test_generate_client_python[--output {contract_name}.py-hello_world_app.py].approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_python[--output {contract_name}.py-hello_world_app.py].approved.txt @@ -1,18 +1,18 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: No matching installed client generator found, run client generator via pipx +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +DEBUG: No matching installed client generator found, running via uvx Generating Python client code for application specified in {current_working_directory}/application.json and writing to hello_world_app.py -DEBUG: Running 'pipx run --spec=algokit-client-generator algokitgen-py -a {current_working_directory}/application.json -o hello_world_app.py' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +DEBUG: Running 'uvx --from=algokit-client-generator algokitgen-py -a {current_working_directory}/application.json -o hello_world_app.py' in '{current_working_directory}' +DEBUG: uvx: STDOUT +DEBUG: uvx: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_generate_client_python[-l python -v 1.1.0-hello_world_app_client.py].approved.txt b/tests/generate/test_generate_client.test_generate_client_python[-l python -v 1.1.0-hello_world_app_client.py].approved.txt index e2d9e0751..14f40dda0 100644 --- a/tests/generate/test_generate_client.test_generate_client_python[-l python -v 1.1.0-hello_world_app_client.py].approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_python[-l python -v 1.1.0-hello_world_app_client.py].approved.txt @@ -1,18 +1,18 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: No matching installed client generator found, run client generator via pipx +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +DEBUG: No matching installed client generator found, running via uvx Generating Python client code for application specified in {current_working_directory}/application.json and writing to hello_world_app_client.py -DEBUG: Running 'pipx run --spec=algokit-client-generator==1.1.0 algokitgen-py -a {current_working_directory}/application.json -o hello_world_app_client.py' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +DEBUG: Running 'uvx --from=algokit-client-generator==1.1.0 algokitgen-py -a {current_working_directory}/application.json -o hello_world_app_client.py' in '{current_working_directory}' +DEBUG: uvx: STDOUT +DEBUG: uvx: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_generate_client_python[-l python-hello_world_app_client.py].approved.txt b/tests/generate/test_generate_client.test_generate_client_python[-l python-hello_world_app_client.py].approved.txt index 588fc447f..4d1e277e4 100644 --- a/tests/generate/test_generate_client.test_generate_client_python[-l python-hello_world_app_client.py].approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_python[-l python-hello_world_app_client.py].approved.txt @@ -1,18 +1,18 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: No matching installed client generator found, run client generator via pipx +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +DEBUG: No matching installed client generator found, running via uvx Generating Python client code for application specified in {current_working_directory}/application.json and writing to hello_world_app_client.py -DEBUG: Running 'pipx run --spec=algokit-client-generator algokitgen-py -a {current_working_directory}/application.json -o hello_world_app_client.py' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +DEBUG: Running 'uvx --from=algokit-client-generator algokitgen-py -a {current_working_directory}/application.json -o hello_world_app_client.py' in '{current_working_directory}' +DEBUG: uvx: STDOUT +DEBUG: uvx: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_generate_client_python[-o client.py --language python --version 1.1.2-client.py].approved.txt b/tests/generate/test_generate_client.test_generate_client_python[-o client.py --language python --version 1.1.2-client.py].approved.txt index fc72588b4..55b6fd063 100644 --- a/tests/generate/test_generate_client.test_generate_client_python[-o client.py --language python --version 1.1.2-client.py].approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_python[-o client.py --language python --version 1.1.2-client.py].approved.txt @@ -1,18 +1,18 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: No matching installed client generator found, run client generator via pipx +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +DEBUG: No matching installed client generator found, running via uvx Generating Python client code for application specified in {current_working_directory}/application.json and writing to client.py -DEBUG: Running 'pipx run --spec=algokit-client-generator==1.1.2 algokitgen-py -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +DEBUG: Running 'uvx --from=algokit-client-generator==1.1.2 algokitgen-py -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}' +DEBUG: uvx: STDOUT +DEBUG: uvx: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_generate_client_python[-o client.py -p --mode minimal-client.py].approved.txt b/tests/generate/test_generate_client.test_generate_client_python[-o client.py -p --mode minimal-client.py].approved.txt index 695a8ca57..25f514e20 100644 --- a/tests/generate/test_generate_client.test_generate_client_python[-o client.py -p --mode minimal-client.py].approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_python[-o client.py -p --mode minimal-client.py].approved.txt @@ -1,18 +1,18 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: No matching installed client generator found, run client generator via pipx +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +DEBUG: No matching installed client generator found, running via uvx Generating Python client code for application specified in {current_working_directory}/application.json and writing to client.py -DEBUG: Running 'pipx run --spec=algokit-client-generator algokitgen-py -a {current_working_directory}/application.json -o client.py -p --mode minimal' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +DEBUG: Running 'uvx --from=algokit-client-generator algokitgen-py -a {current_working_directory}/application.json -o client.py -p --mode minimal' in '{current_working_directory}' +DEBUG: uvx: STDOUT +DEBUG: uvx: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_generate_client_python[-o client.py-client.py].approved.txt b/tests/generate/test_generate_client.test_generate_client_python[-o client.py-client.py].approved.txt index 05a1fb6cb..9cc91cf10 100644 --- a/tests/generate/test_generate_client.test_generate_client_python[-o client.py-client.py].approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_python[-o client.py-client.py].approved.txt @@ -1,18 +1,18 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: No matching installed client generator found, run client generator via pipx +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +DEBUG: No matching installed client generator found, running via uvx Generating Python client code for application specified in {current_working_directory}/application.json and writing to client.py -DEBUG: Running 'pipx run --spec=algokit-client-generator algokitgen-py -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +DEBUG: Running 'uvx --from=algokit-client-generator algokitgen-py -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}' +DEBUG: uvx: STDOUT +DEBUG: uvx: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_generate_client_python[-o client.ts --language python-client.ts].approved.txt b/tests/generate/test_generate_client.test_generate_client_python[-o client.ts --language python-client.ts].approved.txt index ce6a82e6f..6c10188a3 100644 --- a/tests/generate/test_generate_client.test_generate_client_python[-o client.ts --language python-client.ts].approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_python[-o client.ts --language python-client.ts].approved.txt @@ -1,18 +1,18 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: No matching installed client generator found, run client generator via pipx +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +DEBUG: No matching installed client generator found, running via uvx Generating Python client code for application specified in {current_working_directory}/application.json and writing to client.ts -DEBUG: Running 'pipx run --spec=algokit-client-generator algokitgen-py -a {current_working_directory}/application.json -o client.ts' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +DEBUG: Running 'uvx --from=algokit-client-generator algokitgen-py -a {current_working_directory}/application.json -o client.ts' in '{current_working_directory}' +DEBUG: uvx: STDOUT +DEBUG: uvx: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_generate_client_python_arc32_filename.-o.client.py.approved.txt b/tests/generate/test_generate_client.test_generate_client_python_arc32_filename.-o.client.py.approved.txt index c5c7930f5..15a9d72d5 100644 --- a/tests/generate/test_generate_client.test_generate_client_python_arc32_filename.-o.client.py.approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_python_arc32_filename.-o.client.py.approved.txt @@ -1,18 +1,18 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: No matching installed client generator found, run client generator via pipx +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +DEBUG: No matching installed client generator found, running via uvx Generating Python client code for application specified in {current_working_directory}/app.arc32.json and writing to client.py -DEBUG: Running 'pipx run --spec=algokit-client-generator algokitgen-py -a {current_working_directory}/app.arc32.json -o client.py' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +DEBUG: Running 'uvx --from=algokit-client-generator algokitgen-py -a {current_working_directory}/app.arc32.json -o client.py' in '{current_working_directory}' +DEBUG: uvx: STDOUT +DEBUG: uvx: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_generate_client_python_arc56_filename.-o.client.py.approved.txt b/tests/generate/test_generate_client.test_generate_client_python_arc56_filename.-o.client.py.approved.txt index 0025cbc82..60b666f16 100644 --- a/tests/generate/test_generate_client.test_generate_client_python_arc56_filename.-o.client.py.approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_python_arc56_filename.-o.client.py.approved.txt @@ -1,18 +1,18 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: No matching installed client generator found, run client generator via pipx +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +DEBUG: No matching installed client generator found, running via uvx Generating Python client code for application specified in {current_working_directory}/app.arc56.json and writing to client.py -DEBUG: Running 'pipx run --spec=algokit-client-generator algokitgen-py -a {current_working_directory}/app.arc56.json -o client.py' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +DEBUG: Running 'uvx --from=algokit-client-generator algokitgen-py -a {current_working_directory}/app.arc56.json -o client.py' in '{current_working_directory}' +DEBUG: uvx: STDOUT +DEBUG: uvx: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_generate_client_python_multiple_app_specs_in_directory.-o.client.py.approved.txt b/tests/generate/test_generate_client.test_generate_client_python_multiple_app_specs_in_directory.-o.client.py.approved.txt index 0025cbc82..60b666f16 100644 --- a/tests/generate/test_generate_client.test_generate_client_python_multiple_app_specs_in_directory.-o.client.py.approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_python_multiple_app_specs_in_directory.-o.client.py.approved.txt @@ -1,18 +1,18 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: No matching installed client generator found, run client generator via pipx +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +DEBUG: No matching installed client generator found, running via uvx Generating Python client code for application specified in {current_working_directory}/app.arc56.json and writing to client.py -DEBUG: Running 'pipx run --spec=algokit-client-generator algokitgen-py -a {current_working_directory}/app.arc56.json -o client.py' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +DEBUG: Running 'uvx --from=algokit-client-generator algokitgen-py -a {current_working_directory}/app.arc56.json -o client.py' in '{current_working_directory}' +DEBUG: uvx: STDOUT +DEBUG: uvx: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_generate_client_recursive.approved.txt b/tests/generate/test_generate_client.test_generate_client_recursive.approved.txt index 45f41d9a4..782ab9916 100644 --- a/tests/generate/test_generate_client.test_generate_client_recursive.approved.txt +++ b/tests/generate/test_generate_client.test_generate_client_recursive.approved.txt @@ -1,22 +1,22 @@ DEBUG: Searching for project installed client generator -DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR Generating Python client code for application specified in {current_working_directory}/dir1/application.json and writing to {current_working_directory}/dir1/output.py -DEBUG: Running 'poetry run algokitgen-py -a {current_working_directory}/dir1/application.json -o {current_working_directory}/dir1/output.py' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR +DEBUG: Running 'uv run algokitgen-py -a {current_working_directory}/dir1/application.json -o {current_working_directory}/dir1/output.py' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR STDOUT STDERR Generating Python client code for application specified in {current_working_directory}/dir2/application.json and writing to {current_working_directory}/dir2/output.py -DEBUG: Running 'poetry run algokitgen-py -a {current_working_directory}/dir2/application.json -o {current_working_directory}/dir2/output.py' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR +DEBUG: Running 'uv run algokitgen-py -a {current_working_directory}/dir2/application.json -o {current_working_directory}/dir2/output.py' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR STDOUT STDERR Generating Python client code for application specified in {current_working_directory}/dir2/sub_dir/application.json and writing to {current_working_directory}/dir2/sub_dir/output.py -DEBUG: Running 'poetry run algokitgen-py -a {current_working_directory}/dir2/sub_dir/application.json -o {current_working_directory}/dir2/sub_dir/output.py' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR +DEBUG: Running 'uv run algokitgen-py -a {current_working_directory}/dir2/sub_dir/application.json -o {current_working_directory}/dir2/sub_dir/output.py' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_pipx_missing.approved.txt b/tests/generate/test_generate_client.test_pipx_missing.approved.txt index ba509bec1..4cf17f0c2 100644 --- a/tests/generate/test_generate_client.test_pipx_missing.approved.txt +++ b/tests/generate/test_generate_client.test_pipx_missing.approved.txt @@ -1,5 +1,8 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -Error: Unable to find pipx install so that the `algokit-client-generator` can be run; please install pipx via https://pypa.github.io/pipx/ and then try `algokit generate client ...` again. +Error: Unable to find uvx or pipx so that `algokit-client-generator` can be run; please install uv via https://docs.astral.sh/uv/ and then try `algokit generate client ...` again. diff --git a/tests/generate/test_generate_client.test_python_generator_is_installed_globally.approved.txt b/tests/generate/test_generate_client.test_python_generator_is_installed_globally.approved.txt index 13318dab0..9f716597e 100644 --- a/tests/generate/test_generate_client.test_python_generator_is_installed_globally.approved.txt +++ b/tests/generate/test_generate_client.test_python_generator_is_installed_globally.approved.txt @@ -1,15 +1,15 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: algokit 1.13.0 -DEBUG: pipx: poetry 1.6.1 -DEBUG: pipx: algokit-client-generator 1.1.2 +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: algokit 1.13.0 +DEBUG: uv: poetry 1.6.1 +DEBUG: uv: algokit-client-generator 1.1.2 Generating Python client code for application specified in {current_working_directory}/application.json and writing to client.py DEBUG: Running 'algokitgen-py -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}' DEBUG: algokitgen-py: STDOUT diff --git a/tests/generate/test_generate_client.test_python_generator_is_installed_in_project.approved.txt b/tests/generate/test_generate_client.test_python_generator_is_installed_in_project.approved.txt index 6193cbe6e..b78b253a0 100644 --- a/tests/generate/test_generate_client.test_python_generator_is_installed_in_project.approved.txt +++ b/tests/generate/test_generate_client.test_python_generator_is_installed_in_project.approved.txt @@ -1,10 +1,10 @@ DEBUG: Searching for project installed client generator -DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' -DEBUG: poetry: algokit-client-generator 1.1.2 Algorand typed client Generator -DEBUG: poetry: └── algokit-utils 2.2.1 +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR Generating Python client code for application specified in {current_working_directory}/application.json and writing to client.py -DEBUG: Running 'poetry run algokitgen-py -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR +DEBUG: Running 'uv run algokitgen-py -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR STDOUT STDERR diff --git a/tests/generate/test_generate_client.test_python_generator_version_is_not_installed_anywhere.approved.txt b/tests/generate/test_generate_client.test_python_generator_version_is_not_installed_anywhere.approved.txt index c5d101d51..d335b6ab8 100644 --- a/tests/generate/test_generate_client.test_python_generator_version_is_not_installed_anywhere.approved.txt +++ b/tests/generate/test_generate_client.test_python_generator_version_is_not_installed_anywhere.approved.txt @@ -1,19 +1,19 @@ DEBUG: Searching for project installed client generator +DEBUG: Running 'uv pip show algokit-client-generator' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR DEBUG: Running 'poetry show algokit-client-generator --tree' in '{current_working_directory}' DEBUG: poetry: algokit-client-generator 1.1.2 Algorand typed client Generator DEBUG: poetry: └── algokit-utils 2.2.1 -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR DEBUG: Searching for globally installed client generator -DEBUG: Running 'pipx list --short' in '{current_working_directory}' -DEBUG: pipx: algokit 1.13.0 -DEBUG: pipx: poetry 1.6.1 -DEBUG: pipx: algokit-client-generator 1.1.2 -DEBUG: No matching installed client generator found, run client generator via pipx +DEBUG: Running 'uv tool list' in '{current_working_directory}' +DEBUG: uv: algokit 1.13.0 +DEBUG: uv: poetry 1.6.1 +DEBUG: uv: algokit-client-generator 1.1.2 +DEBUG: No matching installed client generator found, running via uvx Generating Python client code for application specified in {current_working_directory}/application.json and writing to client.py -DEBUG: Running 'pipx run --spec=algokit-client-generator==1.2.0 algokitgen-py -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +DEBUG: Running 'uvx --from=algokit-client-generator==1.2.0 algokitgen-py -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}' +DEBUG: uvx: STDOUT +DEBUG: uvx: STDERR STDOUT STDERR diff --git a/tests/init/test_init_with_bootstrap.test_init_bootstrap_broken_poetry.approved.txt b/tests/init/test_init_with_bootstrap.test_init_bootstrap_broken_poetry.approved.txt index aa5649515..0d35c9972 100644 --- a/tests/init/test_init_with_bootstrap.test_init_bootstrap_broken_poetry.approved.txt +++ b/tests/init/test_init_with_bootstrap.test_init_bootstrap_broken_poetry.approved.txt @@ -32,7 +32,6 @@ DEBUG: Checking {current_working_directory}/myapp for bootstrapping needs DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Running `algokit project bootstrap poetry` -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR ERROR: Received an error while attempting bootstrap: poetry --version failed, please check your poetry install diff --git a/tests/portability/test_pyinstaller_binary.py b/tests/portability/test_pyinstaller_binary.py index 9474c37e1..aa6cc7a3e 100644 --- a/tests/portability/test_pyinstaller_binary.py +++ b/tests/portability/test_pyinstaller_binary.py @@ -89,10 +89,20 @@ def test_algokit_init_and_project_run(tmp_path_factory: pytest.TempPathFactory) logger.info(f"Command {init_command} returned {init_result.stdout}") assert init_result.returncode == 0, f"Init command failed with {init_result.stderr}" - # Run algokit project run build + # Add a deterministic project command to avoid template-specific dependency failures + project_config_path = cwd / "playground" / "projects" / "playground" / ".algokit.toml" + project_config_path.write_text( + project_config_path.read_text(encoding="utf-8") + + "\n[project.run.binary_smoke]\n" + + 'commands = ["python --version"]\n' + + 'description = "Binary smoke test"\n', + encoding="utf-8", + ) + + # Run algokit project run for the deterministic command build_cwd = cwd / "playground" build_cwd.mkdir(exist_ok=True) - build_command = [algokit, "-v", "project", "run", "build", "--", "hello_world"] + build_command = [algokit, "-v", "project", "run", "binary_smoke"] build_result = subprocess.run(build_command, capture_output=True, text=True, check=False, cwd=build_cwd) logger.info(f"Command {build_command} returned {build_result.stdout}") assert build_result.returncode == 0, f"Build command failed with {build_result.stderr}" diff --git a/tests/project/bootstrap/test_bootstrap.test_bootstrap_help.approved.txt b/tests/project/bootstrap/test_bootstrap.test_bootstrap_help.approved.txt index 83e1abc62..f7dcf305a 100644 --- a/tests/project/bootstrap/test_bootstrap.test_bootstrap_help.approved.txt +++ b/tests/project/bootstrap/test_bootstrap.test_bootstrap_help.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) Usage: algokit project bootstrap [OPTIONS] COMMAND [ARGS]... Expedited initial setup for any developer by installing and configuring diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_algokit_min_version.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_algokit_min_version.approved.txt index a8d986221..2e16ac99a 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_algokit_min_version.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_algokit_min_version.approved.txt @@ -1,4 +1,2 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml Error: This template requires AlgoKit version 999.99.99 or higher, but you have AlgoKit version {current_version}. Please update AlgoKit. diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_algokit_min_version_ignore_error.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_algokit_min_version_ignore_error.approved.txt index 9c7ec47f9..3c45df043 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_algokit_min_version_ignore_error.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_algokit_min_version_ignore_error.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml WARNING: This template requires AlgoKit version 999.99.99 or higher, but you have AlgoKit version {current_version}. Please update AlgoKit. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_empty.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_empty.approved.txt index 27ff2d24d..9291edade 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_empty.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_empty.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_env.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_env.approved.txt index fabdf2088..988c91f10 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_env.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_env.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[linux].approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[linux].approved.txt index edfd6524b..7e4a158bc 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[linux].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[linux].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[macOS].approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[macOS].approved.txt index edfd6524b..7e4a158bc 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[macOS].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[macOS].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[windows].approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[windows].approved.txt index 7c6af915d..d74851dc8 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[windows].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_npm[windows].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_poetry.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_poetry.approved.txt index 504098c8d..6dabf3ee6 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_poetry.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_poetry.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml @@ -9,7 +6,6 @@ DEBUG: Checking {current_working_directory} for bootstrapping needs DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Running `algokit project bootstrap poetry` -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_poetry_via_pyproject.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_poetry_via_pyproject.approved.txt index 10f7ef6e0..398522684 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_poetry_via_pyproject.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_poetry_via_pyproject.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml @@ -9,7 +6,6 @@ DEBUG: Checking {current_working_directory} for bootstrapping needs DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Running `algokit project bootstrap poetry` -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_filter.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_filter.approved.txt index cabcc7483..a9a0491e8 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_filter.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_filter.approved.txt @@ -12,7 +12,6 @@ DEBUG: {current_working_directory}/artifacts/project1/.env doesn't exist yet DEBUG: {current_working_directory}/artifacts/project1/.env.template exists Copying {current_working_directory}/artifacts/project1/.env.template to {current_working_directory}/artifacts/project1/.env and prompting for empty values DEBUG: Running `algokit bootstrap poetry` -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_name_filter.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_name_filter.approved.txt index 9c8b6daa8..b9854e7db 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_name_filter.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_name_filter.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No 'min_version' specified in .algokit.toml file. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml @@ -16,7 +13,6 @@ DEBUG: {current_working_directory}/artifacts/project_1/.env.template exists Copying {current_working_directory}/artifacts/project_1/.env.template to {current_working_directory}/artifacts/project_1/.env and prompting for empty values DEBUG: Attempting to load project config from {current_working_directory}/artifacts/project_1/.algokit.toml DEBUG: Running `algokit project bootstrap poetry` -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_name_filter_not_found.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_name_filter_not_found.approved.txt index 798b5d67d..45d7103af 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_name_filter_not_found.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_name_filter_not_found.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No 'min_version' specified in .algokit.toml file. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_type_filter.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_type_filter.approved.txt index ca2a113e8..5277accbb 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_type_filter.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_type_filter.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No 'min_version' specified in .algokit.toml file. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_type_filter_not_found.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_type_filter_not_found.approved.txt index 13f1384cf..2cf95a3d2 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_type_filter_not_found.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_projects_type_filter_not_found.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No 'min_version' specified in .algokit.toml file. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_skip_dirs.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_skip_dirs.approved.txt index c289e4bfc..ef2d1ae37 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_skip_dirs.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_skip_dirs.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_sub_dir.approved.txt b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_sub_dir.approved.txt index 9ca6f0ff5..c4e9f6585 100644 --- a/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_sub_dir.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_all.test_bootstrap_all_sub_dir.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml @@ -19,7 +16,6 @@ Copying {current_working_directory}/live_dir/.env.template to {current_working_d DEBUG: Attempting to load project config from {current_working_directory}/live_dir/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Running `algokit project bootstrap poetry` -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry diff --git a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_different_prompt_scenarios.approved.txt b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_different_prompt_scenarios.approved.txt index f40dc64cb..ea196028e 100644 --- a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_different_prompt_scenarios.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_different_prompt_scenarios.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: {current_working_directory}/.env doesn't exist yet diff --git a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_exists.approved.txt b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_exists.approved.txt index d20f2d4b2..4287df7f0 100644 --- a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_exists.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_exists.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. .env already exists; skipping bootstrap of .env diff --git a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_missing_template_exists.approved.txt b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_missing_template_exists.approved.txt index 0a4679082..49e3f94c2 100644 --- a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_missing_template_exists.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_missing_template_exists.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: {current_working_directory}/.env doesn't exist yet diff --git a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_with_values.approved.txt b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_with_values.approved.txt index 9021db23b..d3b043434 100644 --- a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_with_values.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_dotenv_with_values.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: {current_working_directory}/.env doesn't exist yet diff --git a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_multiple_templates.approved.txt b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_multiple_templates.approved.txt index 131cacedd..3ae31ea5b 100644 --- a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_multiple_templates.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_multiple_templates.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: {current_working_directory}/.env.localnet doesn't exist yet diff --git a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_no_files.approved.txt b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_no_files.approved.txt index afc931625..243e68837 100644 --- a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_no_files.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_env_no_files.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. No .env or .env.{network_name}.template files found; nothing to do here, skipping bootstrap. diff --git a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.approved.txt b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.approved.txt index d20f2d4b2..4287df7f0 100644 --- a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. .env already exists; skipping bootstrap of .env diff --git a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.localnet.approved.txt b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.localnet.approved.txt index 42de608ee..64291a773 100644 --- a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.localnet.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.localnet.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. .env.localnet already exists; skipping bootstrap of .env.localnet diff --git a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.localnet.template.approved.txt b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.localnet.template.approved.txt index 61ffa8565..6405284cd 100644 --- a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.localnet.template.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.localnet.template.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: {current_working_directory}/.env.localnet doesn't exist yet diff --git a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.template.approved.txt b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.template.approved.txt index 749d0e0aa..d855a6927 100644 --- a/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.template.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_env.test_bootstrap_network_prefixed_envs..env.template.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: {current_working_directory}/.env doesn't exist yet diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[linux].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[linux].approved.txt index 552beb18e..efe0520d4 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[linux].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[linux].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[macOS].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[macOS].approved.txt index 552beb18e..efe0520d4 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[macOS].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[macOS].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[windows].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[windows].approved.txt index 93394f053..fd6a9cffd 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[windows].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_with_lock_file[windows].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[linux].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[linux].approved.txt index ec456b8b6..7f2ef9676 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[linux].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[linux].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[macOS].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[macOS].approved.txt index ec456b8b6..7f2ef9676 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[macOS].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[macOS].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[windows].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[windows].approved.txt index ec456b8b6..7f2ef9676 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[windows].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_ci_mode_without_lock_file[windows].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[linux].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[linux].approved.txt index b0f7caa94..730e00366 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[linux].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[linux].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[macOS].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[macOS].approved.txt index b0f7caa94..730e00366 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[macOS].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[macOS].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[windows].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[windows].approved.txt index 19190f6be..142f4ef0d 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[windows].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_happy_path[windows].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[linux].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[linux].approved.txt index bcfd8490a..437d6c53d 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[linux].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[linux].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[macOS].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[macOS].approved.txt index bcfd8490a..437d6c53d 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[macOS].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[macOS].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[windows].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[windows].approved.txt index 56da8a11a..72b8ec579 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[windows].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm[windows].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing npm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[linux].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[linux].approved.txt index d1ece60bf..019f040ee 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[linux].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[linux].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. {current_working_directory}/package.json doesn't exist; nothing to do here, skipping bootstrap of npm diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[macOS].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[macOS].approved.txt index d1ece60bf..019f040ee 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[macOS].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[macOS].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. {current_working_directory}/package.json doesn't exist; nothing to do here, skipping bootstrap of npm diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[windows].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[windows].approved.txt index d1ece60bf..019f040ee 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[windows].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_npm_and_package_file[windows].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. {current_working_directory}/package.json doesn't exist; nothing to do here, skipping bootstrap of npm diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[linux].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[linux].approved.txt index d1ece60bf..019f040ee 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[linux].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[linux].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. {current_working_directory}/package.json doesn't exist; nothing to do here, skipping bootstrap of npm diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[macOS].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[macOS].approved.txt index d1ece60bf..019f040ee 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[macOS].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[macOS].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. {current_working_directory}/package.json doesn't exist; nothing to do here, skipping bootstrap of npm diff --git a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[windows].approved.txt b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[windows].approved.txt index d1ece60bf..019f040ee 100644 --- a/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[windows].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_npm.test_bootstrap_npm_without_package_file[windows].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. {current_working_directory}/package.json doesn't exist; nothing to do here, skipping bootstrap of npm diff --git a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[linux].approved.txt b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[linux].approved.txt index 13ead76b9..0f55a004f 100644 --- a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[linux].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[linux].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[macOS].approved.txt b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[macOS].approved.txt index 13ead76b9..0f55a004f 100644 --- a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[macOS].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[macOS].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[windows].approved.txt b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[windows].approved.txt index af965933d..4ecfa422d 100644 --- a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[windows].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_bootstrap_respects_configured_package_managers[windows].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml diff --git a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[linux].approved.txt b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[linux].approved.txt index 8a9cbccb4..24b2e3c06 100644 --- a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[linux].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[linux].approved.txt @@ -1,4 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml @@ -8,7 +7,6 @@ DEBUG: Checking {current_working_directory} for bootstrapping needs DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Using Python package manager from .algokit.toml: poetry DEBUG: Running `algokit project bootstrap poetry` -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry diff --git a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[macOS].approved.txt b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[macOS].approved.txt index 8a9cbccb4..24b2e3c06 100644 --- a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[macOS].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[macOS].approved.txt @@ -1,4 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml @@ -8,7 +7,6 @@ DEBUG: Checking {current_working_directory} for bootstrapping needs DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Using Python package manager from .algokit.toml: poetry DEBUG: Running `algokit project bootstrap poetry` -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry diff --git a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[windows].approved.txt b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[windows].approved.txt index 828aa8237..f1df2071b 100644 --- a/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[windows].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_package_manager_selection.test_project_override_takes_precedence_over_user_preference[windows].approved.txt @@ -1,4 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml @@ -8,7 +7,6 @@ DEBUG: Checking {current_working_directory} for bootstrapping needs DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Using Python package manager from .algokit.toml: poetry DEBUG: Running `algokit project bootstrap poetry` -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry diff --git a/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_ci_mode_without_lock_file.approved.txt b/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_ci_mode_without_lock_file.approved.txt index f5cafd3c0..dce0707bc 100644 --- a/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_ci_mode_without_lock_file.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_ci_mode_without_lock_file.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing pnpm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[linux].approved.txt b/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[linux].approved.txt index 67b6a805e..7300a0bd9 100644 --- a/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[linux].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[linux].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing pnpm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[macOS].approved.txt b/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[macOS].approved.txt index 67b6a805e..7300a0bd9 100644 --- a/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[macOS].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[macOS].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing pnpm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[windows].approved.txt b/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[windows].approved.txt index 7524bbe36..0590a94bb 100644 --- a/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[windows].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_happy_path[windows].approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. Installing pnpm dependencies diff --git a/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_without_package_file.approved.txt b/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_without_package_file.approved.txt index bf03c5b82..f9e9d15a3 100644 --- a/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_without_package_file.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_pnpm.test_bootstrap_pnpm_without_package_file.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. {current_working_directory}/package.json doesn't exist; nothing to do here, skipping bootstrap of pnpm diff --git a/tests/project/bootstrap/test_bootstrap_poetry.py b/tests/project/bootstrap/test_bootstrap_poetry.py index 604a7087c..24a373e22 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.py +++ b/tests/project/bootstrap/test_bootstrap_poetry.py @@ -36,6 +36,11 @@ def which(cmd: str) -> str | None: return mock +@pytest.fixture(autouse=True) +def uvx_which_mock(mocker: MockerFixture) -> None: + mocker.patch("algokit.core.utils.shutil.which", side_effect=lambda cmd: "/bin/uvx" if cmd == "uvx" else None) + + def test_base_python_path(python_base_executable: str) -> None: """When running in a venv (expected test mode), we should be able to resolve to base python. Otherwise, they should be the same""" @@ -63,7 +68,7 @@ def test_bootstrap_poetry_without_poetry(proc_mock: ProcMock, mock_questionary_i def test_bootstrap_poetry_without_poetry_failed_install(proc_mock: ProcMock, mock_questionary_input: PipeInput) -> None: proc_mock.should_fail_on("poetry --version") - proc_mock.should_bad_exit_on("pipx install poetry") + proc_mock.should_bad_exit_on("uv tool install poetry") # Yes, install poetry mock_questionary_input.send_text("Y") @@ -83,8 +88,8 @@ def test_bootstrap_poetry_without_poetry_failed_poetry_path( result = invoke("project bootstrap poetry") - assert result.exit_code == 1 - verify(result.output) + assert result.exit_code == 0 + assert any(call.command == ["uvx", "--from=poetry", "poetry", "install"] for call in proc_mock.called) @pytest.mark.parametrize( @@ -105,7 +110,6 @@ def test_bootstrap_poetry_without_poetry_or_pipx_path( mock_questionary_input: PipeInput, ) -> None: proc_mock.should_fail_on("poetry --version") - proc_mock.should_fail_on("pipx --version") # Yes, install poetry mock_questionary_input.send_text("Y") @@ -120,8 +124,7 @@ def test_bootstrap_poetry_without_poetry_or_pipx_path_failed_install( proc_mock: ProcMock, python_base_executable: str, mock_questionary_input: PipeInput ) -> None: proc_mock.should_fail_on("poetry --version") - proc_mock.should_fail_on("pipx --version") - proc_mock.should_bad_exit_on(f"{python_base_executable} -m pipx install poetry") + proc_mock.should_bad_exit_on("uv tool install poetry") # Yes, install poetry mock_questionary_input.send_text("Y") @@ -133,27 +136,29 @@ def test_bootstrap_poetry_without_poetry_or_pipx_path_failed_install( @pytest.mark.usefixtures("system_python_paths") def test_bootstrap_poetry_without_poetry_or_pipx_path_failed_poetry_path( - proc_mock: ProcMock, python_base_executable: str, mock_questionary_input: PipeInput + proc_mock: ProcMock, mock_questionary_input: PipeInput ) -> None: proc_mock.should_fail_on("poetry --version") - proc_mock.should_fail_on("pipx --version") proc_mock.should_fail_on("poetry install") # Yes, install poetry mock_questionary_input.send_text("Y") result = invoke("project bootstrap poetry") - assert result.exit_code == 1 - verify(result.output.replace(python_base_executable, "{python_base_executable}")) + assert result.exit_code == 0 + assert any(call.command == ["uvx", "--from=poetry", "poetry", "install"] for call in proc_mock.called) @pytest.mark.usefixtures("system_python_paths") def test_bootstrap_poetry_without_poetry_or_pipx_path_or_pipx_module( - proc_mock: ProcMock, python_base_executable: str, mock_questionary_input: PipeInput + proc_mock: ProcMock, + python_base_executable: str, + mock_questionary_input: PipeInput, + mocker: MockerFixture, ) -> None: proc_mock.should_fail_on("poetry --version") - proc_mock.should_fail_on("pipx --version") - proc_mock.should_bad_exit_on(f"{python_base_executable} -m pipx --version") + mocker.patch("algokit.core.utils.shutil.which", return_value=None) + mocker.patch("algokit.core.utils._get_candidate_pipx_commands", return_value=[]) # Yes, install poetry mock_questionary_input.send_text("Y") @@ -161,3 +166,17 @@ def test_bootstrap_poetry_without_poetry_or_pipx_path_or_pipx_module( assert result.exit_code == 1 verify(result.output.replace(python_base_executable, "{python_base_executable}")) + + +def test_bootstrap_poetry_without_poetry_with_uv_no_uvx_uses_runner_fallback( + proc_mock: ProcMock, mock_questionary_input: PipeInput, mocker: MockerFixture +) -> None: + proc_mock.should_fail_on("poetry --version") + proc_mock.should_fail_on("poetry install") + mocker.patch("algokit.core.utils.shutil.which", side_effect=lambda cmd: "/bin/uv" if cmd == "uv" else None) + mock_questionary_input.send_text("Y") + + result = invoke("project bootstrap poetry") + + assert result.exit_code == 0 + assert any(call.command == ["uv", "tool", "run", "--from=poetry", "poetry", "install"] for call in proc_mock.called) diff --git a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_with_poetry.approved.txt b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_with_poetry.approved.txt index 66cee1a4c..8787f5107 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_with_poetry.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_with_poetry.approved.txt @@ -1,9 +1,5 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: poetry: STDOUT DEBUG: poetry: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry diff --git a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry.approved.txt b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry.approved.txt index bb9bfde37..ba751635f 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry.approved.txt @@ -1,15 +1,10 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. -DEBUG: Running 'poetry --version' in '{current_working_directory}' Poetry not found; attempting to install it... -? We couldn't find `poetry`; can we install it for you via pipx so we can install Python dependencies? (Y/n) -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: Running 'pipx install poetry' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +? We couldn't find `poetry`; can we install it for you via uv so we can install Python dependencies? (Y/n) +DEBUG: Running 'uv tool install poetry' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry DEBUG: Running 'poetry install' in '{current_working_directory}' poetry: STDOUT diff --git a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_failed_install.approved.txt b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_failed_install.approved.txt index 5b8c87d8b..7f229299d 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_failed_install.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_failed_install.approved.txt @@ -1,13 +1,8 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. -DEBUG: Running 'poetry --version' in '{current_working_directory}' Poetry not found; attempting to install it... -? We couldn't find `poetry`; can we install it for you via pipx so we can install Python dependencies? (Y/n) -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: Running 'pipx install poetry' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -Error: Unable to install poetry via pipx; please install poetry manually via https://python-poetry.org/docs/ and try `algokit project bootstrap poetry` again. +? We couldn't find `poetry`; can we install it for you via uv so we can install Python dependencies? (Y/n) +DEBUG: Running 'uv tool install poetry' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +Error: Unable to install poetry via uv; please install poetry manually via https://python-poetry.org/docs/ and try `algokit project bootstrap poetry` again. diff --git a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_failed_poetry_path.approved.txt b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_failed_poetry_path.approved.txt index 0da47061e..89fd34f7a 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_failed_poetry_path.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_failed_poetry_path.approved.txt @@ -1,15 +1,10 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. -DEBUG: Running 'poetry --version' in '{current_working_directory}' Poetry not found; attempting to install it... -? We couldn't find `poetry`; can we install it for you via pipx so we can install Python dependencies? (Y/n) -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR -DEBUG: Running 'pipx install poetry' in '{current_working_directory}' -DEBUG: pipx: STDOUT -DEBUG: pipx: STDERR +? We couldn't find `poetry`; can we install it for you via uv so we can install Python dependencies? (Y/n) +DEBUG: Running 'uv tool install poetry' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry DEBUG: Running 'poetry install' in '{current_working_directory}' -Error: Unable to access Poetry on PATH after installing it via pipx; check pipx installations are on your path by running `pipx ensurepath` and try `algokit project bootstrap poetry` again. +Error: Unable to access Poetry on PATH after installing it via uv; check installations are on your path and try `algokit project bootstrap poetry` again. diff --git a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[no_system_pythons].approved.txt b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[no_system_pythons].approved.txt index 07f664f4e..ba751635f 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[no_system_pythons].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[no_system_pythons].approved.txt @@ -1,16 +1,10 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. -DEBUG: Running 'poetry --version' in '{current_working_directory}' Poetry not found; attempting to install it... -? We couldn't find `poetry`; can we install it for you via pipx so we can install Python dependencies? (Y/n) -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: Running '{python_base_executable} -m pipx --version' in '{current_working_directory}' -DEBUG: {python_base_executable}: STDOUT -DEBUG: {python_base_executable}: STDERR -DEBUG: Running '{python_base_executable} -m pipx install poetry' in '{current_working_directory}' -DEBUG: {python_base_executable}: STDOUT -DEBUG: {python_base_executable}: STDERR +? We couldn't find `poetry`; can we install it for you via uv so we can install Python dependencies? (Y/n) +DEBUG: Running 'uv tool install poetry' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry DEBUG: Running 'poetry install' in '{current_working_directory}' poetry: STDOUT diff --git a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python3_only].approved.txt b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python3_only].approved.txt index 5c1017c74..ba751635f 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python3_only].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python3_only].approved.txt @@ -1,16 +1,10 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. -DEBUG: Running 'poetry --version' in '{current_working_directory}' Poetry not found; attempting to install it... -? We couldn't find `poetry`; can we install it for you via pipx so we can install Python dependencies? (Y/n) -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: Running '/bin/python3 -m pipx --version' in '{current_working_directory}' -DEBUG: /bin/python3: STDOUT -DEBUG: /bin/python3: STDERR -DEBUG: Running '/bin/python3 -m pipx install poetry' in '{current_working_directory}' -DEBUG: /bin/python3: STDOUT -DEBUG: /bin/python3: STDERR +? We couldn't find `poetry`; can we install it for you via uv so we can install Python dependencies? (Y/n) +DEBUG: Running 'uv tool install poetry' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry DEBUG: Running 'poetry install' in '{current_working_directory}' poetry: STDOUT diff --git a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python_and_python3].approved.txt b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python_and_python3].approved.txt index 5c1017c74..ba751635f 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python_and_python3].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python_and_python3].approved.txt @@ -1,16 +1,10 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. -DEBUG: Running 'poetry --version' in '{current_working_directory}' Poetry not found; attempting to install it... -? We couldn't find `poetry`; can we install it for you via pipx so we can install Python dependencies? (Y/n) -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: Running '/bin/python3 -m pipx --version' in '{current_working_directory}' -DEBUG: /bin/python3: STDOUT -DEBUG: /bin/python3: STDERR -DEBUG: Running '/bin/python3 -m pipx install poetry' in '{current_working_directory}' -DEBUG: /bin/python3: STDOUT -DEBUG: /bin/python3: STDERR +? We couldn't find `poetry`; can we install it for you via uv so we can install Python dependencies? (Y/n) +DEBUG: Running 'uv tool install poetry' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry DEBUG: Running 'poetry install' in '{current_working_directory}' poetry: STDOUT diff --git a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python_only].approved.txt b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python_only].approved.txt index bbd7a3a53..ba751635f 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python_only].approved.txt +++ b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path[python_only].approved.txt @@ -1,16 +1,10 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. -DEBUG: Running 'poetry --version' in '{current_working_directory}' Poetry not found; attempting to install it... -? We couldn't find `poetry`; can we install it for you via pipx so we can install Python dependencies? (Y/n) -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: Running '/bin/python -m pipx --version' in '{current_working_directory}' -DEBUG: /bin/python: STDOUT -DEBUG: /bin/python: STDERR -DEBUG: Running '/bin/python -m pipx install poetry' in '{current_working_directory}' -DEBUG: /bin/python: STDOUT -DEBUG: /bin/python: STDERR +? We couldn't find `poetry`; can we install it for you via uv so we can install Python dependencies? (Y/n) +DEBUG: Running 'uv tool install poetry' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry DEBUG: Running 'poetry install' in '{current_working_directory}' poetry: STDOUT diff --git a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_failed_install.approved.txt b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_failed_install.approved.txt index 1251fcd24..7f229299d 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_failed_install.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_failed_install.approved.txt @@ -1,14 +1,8 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. -DEBUG: Running 'poetry --version' in '{current_working_directory}' Poetry not found; attempting to install it... -? We couldn't find `poetry`; can we install it for you via pipx so we can install Python dependencies? (Y/n) -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: Running '{python_base_executable} -m pipx --version' in '{current_working_directory}' -DEBUG: {python_base_executable}: STDOUT -DEBUG: {python_base_executable}: STDERR -DEBUG: Running '{python_base_executable} -m pipx install poetry' in '{current_working_directory}' -DEBUG: {python_base_executable}: STDOUT -DEBUG: {python_base_executable}: STDERR -Error: Unable to install poetry via pipx; please install poetry manually via https://python-poetry.org/docs/ and try `algokit project bootstrap poetry` again. +? We couldn't find `poetry`; can we install it for you via uv so we can install Python dependencies? (Y/n) +DEBUG: Running 'uv tool install poetry' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR +Error: Unable to install poetry via uv; please install poetry manually via https://python-poetry.org/docs/ and try `algokit project bootstrap poetry` again. diff --git a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_failed_poetry_path.approved.txt b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_failed_poetry_path.approved.txt index 82625fab7..89fd34f7a 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_failed_poetry_path.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_failed_poetry_path.approved.txt @@ -1,16 +1,10 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. -DEBUG: Running 'poetry --version' in '{current_working_directory}' Poetry not found; attempting to install it... -? We couldn't find `poetry`; can we install it for you via pipx so we can install Python dependencies? (Y/n) -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: Running '{python_base_executable} -m pipx --version' in '{current_working_directory}' -DEBUG: {python_base_executable}: STDOUT -DEBUG: {python_base_executable}: STDERR -DEBUG: Running '{python_base_executable} -m pipx install poetry' in '{current_working_directory}' -DEBUG: {python_base_executable}: STDOUT -DEBUG: {python_base_executable}: STDERR +? We couldn't find `poetry`; can we install it for you via uv so we can install Python dependencies? (Y/n) +DEBUG: Running 'uv tool install poetry' in '{current_working_directory}' +DEBUG: uv: STDOUT +DEBUG: uv: STDERR Installing Python dependencies and setting up Python virtual environment via Poetry DEBUG: Running 'poetry install' in '{current_working_directory}' -Error: Unable to access Poetry on PATH after installing it via pipx; check pipx installations are on your path by running `pipx ensurepath` and try `algokit project bootstrap poetry` again. +Error: Unable to access Poetry on PATH after installing it via uv; check installations are on your path and try `algokit project bootstrap poetry` again. diff --git a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_or_pipx_module.approved.txt b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_or_pipx_module.approved.txt index f1201201e..a37ca5c78 100644 --- a/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_or_pipx_module.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_poetry.test_bootstrap_poetry_without_poetry_or_pipx_path_or_pipx_module.approved.txt @@ -1,11 +1,4 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. -DEBUG: Running 'poetry --version' in '{current_working_directory}' Poetry not found; attempting to install it... -? We couldn't find `poetry`; can we install it for you via pipx so we can install Python dependencies? (Y/n) -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: Running '{python_base_executable} -m pipx --version' in '{current_working_directory}' -DEBUG: {python_base_executable}: STDOUT -DEBUG: {python_base_executable}: STDERR -Error: Unable to find pipx install so that poetry can be installed; please install pipx via https://pypa.github.io/pipx/ and then try `algokit project bootstrap poetry` again. +Error: Unable to find uv or pipx so that poetry can be installed; please install uv via https://docs.astral.sh/uv/ and then try `algokit project bootstrap poetry` again. diff --git a/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_happy_path.approved.txt b/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_happy_path.approved.txt index 34d260806..16cef2c08 100644 --- a/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_happy_path.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_happy_path.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Running 'uv --version' in '{current_working_directory}' diff --git a/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_poetry_project_migration_declined.approved.txt b/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_poetry_project_migration_declined.approved.txt index 40257d5fc..b3d018adb 100644 --- a/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_poetry_project_migration_declined.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_poetry_project_migration_declined.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Running 'uv --version' in '{current_working_directory}' diff --git a/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_user_declines_install.approved.txt b/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_user_declines_install.approved.txt index 0f618260c..207d73f5e 100644 --- a/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_user_declines_install.approved.txt +++ b/tests/project/bootstrap/test_bootstrap_uv.test_bootstrap_uv_user_declines_install.approved.txt @@ -1,8 +1,5 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Running 'uv --version' in '{current_working_directory}' UV not found; attempting to install it... -Error: Unable to install uv; please install uv manually via https://github.com/astral-sh/uv and try `algokit project bootstrap uv` again. +Error: Unable to install uv; please install uv manually via https://docs.astral.sh/uv/ and try `algokit project bootstrap uv` again. diff --git a/tests/project/deploy/test_deploy.py b/tests/project/deploy/test_deploy.py index 47c905745..a3acc2896 100644 --- a/tests/project/deploy/test_deploy.py +++ b/tests/project/deploy/test_deploy.py @@ -230,8 +230,8 @@ def test_algokit_env_and_name_correct_set( result = invoke(["project", "deploy", "localnet"], cwd=cwd) - assert proc_mock.called[1].env - passed_env_vars = proc_mock.called[1].env + assert proc_mock.called[0].env + passed_env_vars = proc_mock.called[0].env assert passed_env_vars["ENV_A"] == "ENVIRON_ENV_A" # os.environ is highest loading priority assert passed_env_vars["ENV_B"] == "LOCALNET_ENV_B" # then .env.{name} @@ -262,8 +262,8 @@ def test_algokit_deploy_only_base_deploy_config( result = invoke(["project", "deploy"], cwd=cwd) assert result.exit_code == 0 - assert proc_mock.called[1].env - passed_env_vars = proc_mock.called[1].env + assert proc_mock.called[0].env + passed_env_vars = proc_mock.called[0].env assert passed_env_vars["ENV_A"] == "GENERIC_ENV_A" @@ -367,8 +367,8 @@ def test_secrets_prompting_via_stdin( assert result.exit_code == 0 # ensure success # assert that entered value is passed to proc run - assert proc_mock.called[1].env - called_env = proc_mock.called[1].env + assert proc_mock.called[0].env + called_env = proc_mock.called[0].env assert "DEPLOYER_MNEMONIC" in called_env assert called_env["DEPLOYER_MNEMONIC"] == "secret_value" @@ -462,8 +462,8 @@ def test_deploy_dispenser_alias( which_mock.add("command_a") result = invoke(["project", "deploy", f"--{alias}", alias], cwd=cwd) - assert proc_mock.called[1].env - passed_env_vars = proc_mock.called[1].env + assert proc_mock.called[0].env + passed_env_vars = proc_mock.called[0].env assert passed_env_vars[env_var_name] == dummy_account_mnemonic @@ -487,7 +487,7 @@ def test_deploy_with_extra_args(tmp_path_factory: TempPathFactory, proc_mock: Pr result = invoke(["project", "deploy", "--", *extra_args], cwd=cwd) assert result.exit_code == 0 - assert proc_mock.called[1].command == [cmd_resolved, *sanitize_extra_args(extra_args)] + assert proc_mock.called[0].command == [cmd_resolved, *sanitize_extra_args(extra_args)] verify(result.output) @@ -505,5 +505,5 @@ def test_deploy_with_extra_args_and_custom_command( result = invoke(["project", "deploy", "localnet", "--command", custom_command, "--", *extra_args], cwd=cwd) assert result.exit_code == 0 - assert proc_mock.called[1].command == [cmd_resolved, *sanitize_extra_args(extra_args)] + assert proc_mock.called[0].command == [cmd_resolved, *sanitize_extra_args(extra_args)] verify(result.output) diff --git a/tests/project/deploy/test_deploy.test_algokit_config_empty_array.approved.txt b/tests/project/deploy/test_deploy.test_algokit_config_empty_array.approved.txt index 31022d5da..1495b327c 100644 --- a/tests/project/deploy/test_deploy.test_algokit_config_empty_array.approved.txt +++ b/tests/project/deploy/test_deploy.test_algokit_config_empty_array.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_algokit_config_invalid_syntax.approved.txt b/tests/project/deploy/test_deploy.test_algokit_config_invalid_syntax.approved.txt index 32597854e..b654dce55 100644 --- a/tests/project/deploy/test_deploy.test_algokit_config_invalid_syntax.approved.txt +++ b/tests/project/deploy/test_deploy.test_algokit_config_invalid_syntax.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Error parsing .algokit.toml file: Invalid statement (at line 1, column 1) DEBUG: Deploying from project directory: {current_working_directory} diff --git a/tests/project/deploy/test_deploy.test_algokit_config_name_no_base.approved.txt b/tests/project/deploy/test_deploy.test_algokit_config_name_no_base.approved.txt index da3b57909..daa8240f0 100644 --- a/tests/project/deploy/test_deploy.test_algokit_config_name_no_base.approved.txt +++ b/tests/project/deploy/test_deploy.test_algokit_config_name_no_base.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_algokit_config_name_overrides.approved.txt b/tests/project/deploy/test_deploy.test_algokit_config_name_overrides.approved.txt index de7054716..ad845aec3 100644 --- a/tests/project/deploy/test_deploy.test_algokit_config_name_overrides.approved.txt +++ b/tests/project/deploy/test_deploy.test_algokit_config_name_overrides.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_algokit_deploy_only_base_deploy_config.approved.txt b/tests/project/deploy/test_deploy.test_algokit_deploy_only_base_deploy_config.approved.txt index 547013284..45dd697d5 100644 --- a/tests/project/deploy/test_deploy.test_algokit_deploy_only_base_deploy_config.approved.txt +++ b/tests/project/deploy/test_deploy.test_algokit_deploy_only_base_deploy_config.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_algokit_env_and_name_correct_set.approved.txt b/tests/project/deploy/test_deploy.test_algokit_env_and_name_correct_set.approved.txt index 559486337..317ee393b 100644 --- a/tests/project/deploy/test_deploy.test_algokit_env_and_name_correct_set.approved.txt +++ b/tests/project/deploy/test_deploy.test_algokit_env_and_name_correct_set.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_algokit_env_name_missing.approved.txt b/tests/project/deploy/test_deploy.test_algokit_env_name_missing.approved.txt index 44371e6ce..dccb0a3aa 100644 --- a/tests/project/deploy/test_deploy.test_algokit_env_name_missing.approved.txt +++ b/tests/project/deploy/test_deploy.test_algokit_env_name_missing.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_ci_flag_interactivity_mode_via_cli.approved.txt b/tests/project/deploy/test_deploy.test_ci_flag_interactivity_mode_via_cli.approved.txt index f9791ed35..295beb6d4 100644 --- a/tests/project/deploy/test_deploy.test_ci_flag_interactivity_mode_via_cli.approved.txt +++ b/tests/project/deploy/test_deploy.test_ci_flag_interactivity_mode_via_cli.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_ci_flag_interactivity_mode_via_env.approved.txt b/tests/project/deploy/test_deploy.test_ci_flag_interactivity_mode_via_env.approved.txt index f9791ed35..295beb6d4 100644 --- a/tests/project/deploy/test_deploy.test_ci_flag_interactivity_mode_via_env.approved.txt +++ b/tests/project/deploy/test_deploy.test_ci_flag_interactivity_mode_via_env.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_command_bad_exit_code.approved.txt b/tests/project/deploy/test_deploy.test_command_bad_exit_code.approved.txt index d1e5cf2f8..4c4a813d9 100644 --- a/tests/project/deploy/test_deploy.test_command_bad_exit_code.approved.txt +++ b/tests/project/deploy/test_deploy.test_command_bad_exit_code.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Deploying from project directory: {current_working_directory} diff --git a/tests/project/deploy/test_deploy.test_command_invocation_and_command_splitting.approved.txt b/tests/project/deploy/test_deploy.test_command_invocation_and_command_splitting.approved.txt index b522b7495..c4d0b879c 100644 --- a/tests/project/deploy/test_deploy.test_command_invocation_and_command_splitting.approved.txt +++ b/tests/project/deploy/test_deploy.test_command_invocation_and_command_splitting.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_command_not_executable.approved.txt b/tests/project/deploy/test_deploy.test_command_not_executable.approved.txt index 6b87cc56d..c2037a580 100644 --- a/tests/project/deploy/test_deploy.test_command_not_executable.approved.txt +++ b/tests/project/deploy/test_deploy.test_command_not_executable.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Deploying from project directory: {current_working_directory} diff --git a/tests/project/deploy/test_deploy.test_command_not_found_and_no_config.approved.txt b/tests/project/deploy/test_deploy.test_command_not_found_and_no_config.approved.txt index 441f56e9f..8a4f6acaf 100644 --- a/tests/project/deploy/test_deploy.test_command_not_found_and_no_config.approved.txt +++ b/tests/project/deploy/test_deploy.test_command_not_found_and_no_config.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Deploying from project directory: {current_working_directory} diff --git a/tests/project/deploy/test_deploy.test_command_splitting_from_config.approved.txt b/tests/project/deploy/test_deploy.test_command_splitting_from_config.approved.txt index b522b7495..c4d0b879c 100644 --- a/tests/project/deploy/test_deploy.test_command_splitting_from_config.approved.txt +++ b/tests/project/deploy/test_deploy.test_command_splitting_from_config.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_command_without_splitting_from_config.approved.txt b/tests/project/deploy/test_deploy.test_command_without_splitting_from_config.approved.txt index b522b7495..c4d0b879c 100644 --- a/tests/project/deploy/test_deploy.test_command_without_splitting_from_config.approved.txt +++ b/tests/project/deploy/test_deploy.test_command_without_splitting_from_config.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_deploy_custom_project_dir.approved.txt b/tests/project/deploy/test_deploy.test_deploy_custom_project_dir.approved.txt index d245548c8..a1273934e 100644 --- a/tests/project/deploy/test_deploy.test_deploy_custom_project_dir.approved.txt +++ b/tests/project/deploy/test_deploy.test_deploy_custom_project_dir.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Deploying from project directory: {current_working_directory}/custom_folder diff --git a/tests/project/deploy/test_deploy.test_deploy_dispenser_alias.deployer.approved.txt b/tests/project/deploy/test_deploy.test_deploy_dispenser_alias.deployer.approved.txt index c3f7ce561..08270d6af 100644 --- a/tests/project/deploy/test_deploy.test_deploy_dispenser_alias.deployer.approved.txt +++ b/tests/project/deploy/test_deploy.test_deploy_dispenser_alias.deployer.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_deploy_dispenser_alias.dispenser.approved.txt b/tests/project/deploy/test_deploy.test_deploy_dispenser_alias.dispenser.approved.txt index e8c123df2..0bd44db08 100644 --- a/tests/project/deploy/test_deploy.test_deploy_dispenser_alias.dispenser.approved.txt +++ b/tests/project/deploy/test_deploy.test_deploy_dispenser_alias.dispenser.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_deploy_shutil_command_not_found.approved.txt b/tests/project/deploy/test_deploy.test_deploy_shutil_command_not_found.approved.txt index d0fa1b670..b3c6a6b70 100644 --- a/tests/project/deploy/test_deploy.test_deploy_shutil_command_not_found.approved.txt +++ b/tests/project/deploy/test_deploy.test_deploy_shutil_command_not_found.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_deploy_with_extra_args.approved.txt b/tests/project/deploy/test_deploy.test_deploy_with_extra_args.approved.txt index f1c80d1f4..b06334c1c 100644 --- a/tests/project/deploy/test_deploy.test_deploy_with_extra_args.approved.txt +++ b/tests/project/deploy/test_deploy.test_deploy_with_extra_args.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/deploy/test_deploy.test_deploy_with_extra_args_and_custom_command.approved.txt b/tests/project/deploy/test_deploy.test_deploy_with_extra_args_and_custom_command.approved.txt index 38ee155d9..26e687c11 100644 --- a/tests/project/deploy/test_deploy.test_deploy_with_extra_args_and_custom_command.approved.txt +++ b/tests/project/deploy/test_deploy.test_deploy_with_extra_args_and_custom_command.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Deploying from project directory: {current_working_directory} diff --git a/tests/project/deploy/test_deploy.test_secrets_prompting_via_stdin.approved.txt b/tests/project/deploy/test_deploy.test_secrets_prompting_via_stdin.approved.txt index 547013284..45dd697d5 100644 --- a/tests/project/deploy/test_deploy.test_secrets_prompting_via_stdin.approved.txt +++ b/tests/project/deploy/test_deploy.test_secrets_prompting_via_stdin.approved.txt @@ -1,6 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: STDOUT -DEBUG: poetry: STDERR DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: Deploying from project directory: {current_working_directory} DEBUG: Loading deploy command from project config diff --git a/tests/project/list/test_list.test_list_command_from_empty_folder.approved.txt b/tests/project/list/test_list.test_list_command_from_empty_folder.approved.txt index d1a7e0133..9e2695dcf 100644 --- a/tests/project/list/test_list.test_list_command_from_empty_folder.approved.txt +++ b/tests/project/list/test_list.test_list_command_from_empty_folder.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from /.algokit.toml diff --git a/tests/project/list/test_list.test_list_command_no_args.approved.txt b/tests/project/list/test_list.test_list_command_no_args.approved.txt index d1a7e0133..9e2695dcf 100644 --- a/tests/project/list/test_list.test_list_command_no_args.approved.txt +++ b/tests/project/list/test_list.test_list_command_no_args.approved.txt @@ -1,5 +1,3 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. DEBUG: Attempting to load project config from /.algokit.toml diff --git a/tests/project/run/test_run.py b/tests/project/run/test_run.py index fb08ba21b..7f083b182 100644 --- a/tests/project/run/test_run.py +++ b/tests/project/run/test_run.py @@ -355,6 +355,24 @@ def test_run_command_from_standalone_resolution_error( verify(_format_output(result.output)) +def test_run_command_from_standalone_poetry_run_falls_back_to_uv( + tmp_path_factory: pytest.TempPathFactory, + which_mock: WhichMock, + proc_mock: ProcMock, +) -> None: + cwd = tmp_path_factory.mktemp("cwd") / "algokit_project" + cwd.mkdir() + + uv_path = which_mock.add("uv") + proc_mock.set_output([uv_path, "run", "echo", "hello"], ["hello"]) + _create_project_config(cwd, "contract", "contract_project", "poetry run echo hello", "Runs hello") + + result = invoke("project run hello", cwd=cwd) + + assert result.exit_code == 0 + assert proc_mock.called[0].command == [uv_path, "run", "echo", "hello"] + + def test_run_command_from_standalone_execution_error(tmp_path_factory: pytest.TempPathFactory) -> None: """ Verifies the behavior when a command execution error occurs within a standalone project. diff --git a/tests/tasks/test_analyze.py b/tests/tasks/test_analyze.py index 6db1f628e..f9fed5bfc 100644 --- a/tests/tasks/test_analyze.py +++ b/tests/tasks/test_analyze.py @@ -235,7 +235,8 @@ def test_analyze_diff_flag_missing_old_report( def test_analyze_error_no_pipx(cwd: Path, mocker: MockerFixture, proc_mock: ProcMock) -> None: proc_mock.should_fail_on("tealer --version") - mocker.patch("algokit.core.utils.get_candidate_pipx_commands", return_value=[]) + mocker.patch("algokit.core.utils.shutil.which", return_value=None) + mocker.patch("algokit.core.utils._get_candidate_pipx_commands", return_value=[]) teal_file = cwd / "dummy.teal" teal_file.touch() diff --git a/tests/tasks/test_analyze.test_analyze_error_no_pipx.approved.txt b/tests/tasks/test_analyze.test_analyze_error_no_pipx.approved.txt index b3cad5c68..45b27efec 100644 --- a/tests/tasks/test_analyze.test_analyze_error_no_pipx.approved.txt +++ b/tests/tasks/test_analyze.test_analyze_error_no_pipx.approved.txt @@ -1,4 +1,4 @@ DEBUG: Running 'tealer --version' in '{current_working_directory}' DEBUG: No such file or directory: tealer Tealer not found; attempting to install it... -Error: Unable to find pipx install so that `tealer` static analyzer can be installed; please install pipx via https://pypa.github.io/pipx/ and then try `algokit task analyze ...` again. +Error: Unable to find uvx or pipx so that `tealer` can be installed; please install uv via https://docs.astral.sh/uv/ and then try `algokit task analyze ...` again. diff --git a/tests/test_utils_path_resolution.py b/tests/test_utils_path_resolution.py new file mode 100644 index 000000000..a93ee0a46 --- /dev/null +++ b/tests/test_utils_path_resolution.py @@ -0,0 +1,68 @@ +import logging +import os +import stat +import sys +from pathlib import Path +from typing import TYPE_CHECKING + +from pytest_mock import MockerFixture + +from algokit.cli import _check_binary_deprecation +from algokit.core.utils import find_all_on_path + +if TYPE_CHECKING: + from _pytest.logging import LogCaptureFixture + from _pytest.monkeypatch import MonkeyPatch + + +def _make_executable(path: Path) -> Path: + executable_path = path.with_suffix(".exe") if os.name == "nt" else path + executable_path.write_text("#!/usr/bin/env sh\n", encoding="utf-8") + executable_path.chmod(executable_path.stat().st_mode | stat.S_IXUSR) + return executable_path + + +def test_find_all_on_path_returns_matches_in_path_order(tmp_path: Path, monkeypatch: "MonkeyPatch") -> None: + legacy_dir = tmp_path / "legacy-bin" + uv_dir = tmp_path / "uv-bin" + legacy_dir.mkdir() + uv_dir.mkdir() + + legacy_algokit = _make_executable(legacy_dir / "algokit") + uv_algokit = _make_executable(uv_dir / "algokit") + + monkeypatch.setenv("PATH", f"{legacy_dir}{os.pathsep}{uv_dir}") + + paths = find_all_on_path("algokit") + + assert [path.resolve() for path in paths] == [legacy_algokit.resolve(), uv_algokit.resolve()] + + +def test_find_all_on_path_deduplicates_repeated_entries(tmp_path: Path, monkeypatch: "MonkeyPatch") -> None: + tools_dir = tmp_path / "tools" + tools_dir.mkdir() + + algokit = _make_executable(tools_dir / "algokit") + + monkeypatch.setenv("PATH", f"{tools_dir}{os.pathsep}{tools_dir}") + + paths = find_all_on_path("algokit") + + assert [path.resolve() for path in paths] == [algokit.resolve()] + + +def test_check_binary_deprecation_warns_when_multiple_algokit_are_on_path( + caplog: "LogCaptureFixture", mocker: MockerFixture, monkeypatch: "MonkeyPatch" +) -> None: + mocker.patch("algokit.cli.is_binary_mode", return_value=True) + first_algokit_path = Path("/usr/local/bin/algokit") + second_algokit_path = Path("/home/user/.local/bin/algokit") + mocker.patch("algokit.cli.find_all_on_path", return_value=[first_algokit_path, second_algokit_path]) + monkeypatch.setattr(sys, "executable", str(first_algokit_path)) + + with caplog.at_level(logging.WARNING): + _check_binary_deprecation() + + assert "Multiple `algokit` executables were found on PATH." in caplog.text + assert str(first_algokit_path) in caplog.text + assert str(second_algokit_path) in caplog.text diff --git a/tests/utils/approvals.py b/tests/utils/approvals.py index a5fa6e7c3..3ba31a2f7 100644 --- a/tests/utils/approvals.py +++ b/tests/utils/approvals.py @@ -23,7 +23,7 @@ def normalize_path(content: str, path: str, token: str) -> str: ) -def _normalize_platform_differences(data: str, poetry_version: str = "99.99.99") -> str: +def _normalize_platform_differences(data: str) -> str: """Normalize platform-specific and version-specific differences.""" result = data @@ -39,10 +39,9 @@ def _normalize_platform_differences(data: str, poetry_version: str = "99.99.99") r"DEBUG: git: Stopping at filesystem boundary \(GIT_DISCOVERY_ACROSS_FILESYSTEM not set\)\.\n", "", result ) - # Normalize Poetry version output to avoid test failures on version updates - result = re.sub( - r"DEBUG: poetry: Poetry \(version \d+\.\d+\.\d+\)", f"DEBUG: poetry: Poetry (version {poetry_version})", result - ) + # Strip poetry version output entirely — poetry may or may not be installed + result = re.sub(r"DEBUG: poetry: Poetry \(version \d+\.\d+\.\d+\)\n?", "", result) + result = re.sub(r"DEBUG: Running 'poetry --version'[^\n]*\n?", "", result) # Normalize msgpack/Python TypeError messages for 'in' operator # C-extension msgpack (Python 3.10-3.13) says "is not a container or iterable" @@ -78,7 +77,6 @@ def verify( *, options: approvaltests.Options | None = None, scrubber: Scrubber | None = None, - poetry_version: str = "99.99.99", **kwargs: Any, ) -> None: options = options or approvaltests.Options() @@ -87,8 +85,7 @@ def verify( kwargs.setdefault("encoding", "utf-8") normalised_data = str(data).replace("\r\n", "\n") - # Apply global platform/version normalization with configurable poetry version - normalised_data = _normalize_platform_differences(normalised_data, poetry_version) + normalised_data = _normalize_platform_differences(normalised_data) approvaltests.verify( data=normalised_data, diff --git a/tests/version_check/test_version_check.test_version_check_queries_github_when_cache_out_of_date.approved.txt b/tests/version_check/test_version_check.test_version_check_queries_github_when_cache_out_of_date.approved.txt index 0405965f9..f17d9698e 100644 --- a/tests/version_check/test_version_check.test_version_check_queries_github_when_cache_out_of_date.approved.txt +++ b/tests/version_check/test_version_check.test_version_check_queries_github_when_cache_out_of_date.approved.txt @@ -2,7 +2,5 @@ DEBUG: 1234.56.78 found in cache {app_state}/last-version-check HTTP Request: GET https://api.github.com/repos/algorandfoundation/algokit-cli/releases/latest "HTTP/1.1 200 OK" DEBUG: Latest version tag: v{new_version} You are using AlgoKit version {current_version}, however version {new_version} is available. Please update using the tool used to install AlgoKit. -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. diff --git a/tests/version_check/test_version_check.test_version_check_queries_github_when_no_cache.approved.txt b/tests/version_check/test_version_check.test_version_check_queries_github_when_no_cache.approved.txt index 2cbd0ad23..5a16229b3 100644 --- a/tests/version_check/test_version_check.test_version_check_queries_github_when_no_cache.approved.txt +++ b/tests/version_check/test_version_check.test_version_check_queries_github_when_no_cache.approved.txt @@ -2,7 +2,5 @@ DEBUG: {app_state}/last-version-check inaccessible HTTP Request: GET https://api.github.com/repos/algorandfoundation/algokit-cli/releases/latest "HTTP/1.1 200 OK" DEBUG: Latest version tag: v{new_version} You are using AlgoKit version {current_version}, however version {new_version} is available. Please update using the tool used to install AlgoKit. -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. diff --git a/tests/version_check/test_version_check.test_version_check_respects_disable_config.approved.txt b/tests/version_check/test_version_check.test_version_check_respects_disable_config.approved.txt index ea96feeae..57893de50 100644 --- a/tests/version_check/test_version_check.test_version_check_respects_disable_config.approved.txt +++ b/tests/version_check/test_version_check.test_version_check_respects_disable_config.approved.txt @@ -1,5 +1,3 @@ DEBUG: Version prompt disabled -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. diff --git a/tests/version_check/test_version_check.test_version_check_respects_skip_option.approved.txt b/tests/version_check/test_version_check.test_version_check_respects_skip_option.approved.txt index f1eeca807..4e14461c8 100644 --- a/tests/version_check/test_version_check.test_version_check_respects_skip_option.approved.txt +++ b/tests/version_check/test_version_check.test_version_check_respects_skip_option.approved.txt @@ -1,4 +1,2 @@ -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. diff --git a/tests/version_check/test_version_check.test_version_check_uses_cache.approved.txt b/tests/version_check/test_version_check.test_version_check_uses_cache.approved.txt index e0df934a3..ce57ae483 100644 --- a/tests/version_check/test_version_check.test_version_check_uses_cache.approved.txt +++ b/tests/version_check/test_version_check.test_version_check_uses_cache.approved.txt @@ -1,6 +1,4 @@ DEBUG: 1234.56.78 found in cache {app_state}/last-version-check You are using AlgoKit version {current_version}, however version 1234.56.78 is available. Please update using the tool used to install AlgoKit. -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Poetry (version 99.99.99) DEBUG: Attempting to load project config from {current_working_directory}/.algokit.toml DEBUG: No .algokit.toml file found in the project directory. diff --git a/uv.lock b/uv.lock new file mode 100644 index 000000000..3d7709192 --- /dev/null +++ b/uv.lock @@ -0,0 +1,2819 @@ +version = 1 +revision = 3 +requires-python = ">=3.10, <3.15" + +[[package]] +name = "alabaster" +version = "0.7.16" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/3e/13dd8e5ed9094e734ac430b5d0eb4f2bb001708a8b7856cbf8e084e001ba/alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65", size = 23776, upload-time = "2024-01-10T00:56:10.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/34/d4e1c02d3bee589efb5dfa17f88ea08bdb3e3eac12bc475462aec52ed223/alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92", size = 13511, upload-time = "2024-01-10T00:56:08.388Z" }, +] + +[[package]] +name = "algokit" +version = "2.10.2" +source = { editable = "." } +dependencies = [ + { name = "algokit-utils" }, + { name = "click" }, + { name = "copier" }, + { name = "cryptography" }, + { name = "httpx" }, + { name = "jsondiff" }, + { name = "keyring" }, + { name = "mslex" }, + { name = "multiformats" }, + { name = "multiformats-config" }, + { name = "prompt-toolkit" }, + { name = "pyclip" }, + { name = "pyjwt" }, + { name = "python-dotenv" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "questionary" }, + { name = "requests" }, + { name = "shellingham" }, + { name = "textual" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] + +[package.dev-dependencies] +dev = [ + { name = "approvaltests" }, + { name = "gfm-toc" }, + { name = "mypy" }, + { name = "pip-audit" }, + { name = "poethepoet" }, + { name = "pre-commit" }, + { name = "pyinstaller" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "pytest-httpx" }, + { name = "pytest-mock" }, + { name = "pytest-sugar" }, + { name = "pytest-xdist" }, + { name = "python-semantic-release" }, + { name = "ruff" }, + { name = "sphinx" }, + { name = "sphinx-click" }, + { name = "types-pyyaml" }, +] +docs = [ + { name = "sphinxnotes-markdown-builder" }, +] + +[package.metadata] +requires-dist = [ + { name = "algokit-utils", specifier = ">=5.0.0a7,<6.0.0" }, + { name = "click", specifier = "==8.1.8" }, + { name = "copier", specifier = ">=9.11.3,<10.0.0" }, + { name = "cryptography", specifier = ">=46.0.5,<47.0.0" }, + { name = "httpx", specifier = ">=0.23.1,<=0.28.1" }, + { name = "jsondiff", specifier = ">=2.0.0,<3.0.0" }, + { name = "keyring", specifier = "==25.6.0" }, + { name = "mslex", specifier = ">=1.1.0,<2.0.0" }, + { name = "multiformats", specifier = "==0.3.1" }, + { name = "multiformats-config", specifier = "==0.3.1" }, + { name = "prompt-toolkit", specifier = "==3.0.51" }, + { name = "pyclip", specifier = ">=0.7.0,<0.8.0" }, + { name = "pyjwt", specifier = ">=2.10.1,<3.0.0" }, + { name = "python-dotenv", specifier = ">=1.0.0,<2.0.0" }, + { name = "pywin32", marker = "sys_platform == 'win32'", specifier = ">=311,<312" }, + { name = "questionary", specifier = ">=1.10.0,<2.0.0" }, + { name = "requests", specifier = ">=2.31.0,<3.0.0" }, + { name = "shellingham", specifier = ">=1.5.4,<2.0.0" }, + { name = "textual", specifier = ">=3.0.1,<4.0.0" }, + { name = "tomli", marker = "python_full_version < '3.11'", specifier = ">=2.0.1,<3.0.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "approvaltests", specifier = ">=7.2.0,<8.0.0" }, + { name = "gfm-toc", specifier = ">=0.0.7,<0.0.8" }, + { name = "mypy", specifier = ">=1.0.0,<2.0.0" }, + { name = "pip-audit", specifier = ">=2.4.7,<3.0.0" }, + { name = "poethepoet", specifier = ">=0.17.1,<0.37.0" }, + { name = "pre-commit", specifier = ">=2.20,<4.0" }, + { name = "pyinstaller", specifier = ">=6.10.0,<7.0.0" }, + { name = "pytest", specifier = ">=8,<9" }, + { name = "pytest-cov", specifier = ">=4.0.0,<5.0.0" }, + { name = "pytest-httpx", specifier = ">=0.35.0,<0.36.0" }, + { name = "pytest-mock", specifier = ">=3.10.0,<4.0.0" }, + { name = "pytest-sugar", specifier = ">=1.0.0,<2.0.0" }, + { name = "pytest-xdist", specifier = ">=3.4.0,<4.0.0" }, + { name = "python-semantic-release", specifier = ">=7.32.2,<8.0.0" }, + { name = "ruff", specifier = ">=0.1.6,<0.13.0" }, + { name = "sphinx", specifier = ">=6.0.0,<7.0.0" }, + { name = "sphinx-click", specifier = ">=4.4.0,<5.0.0" }, + { name = "types-pyyaml", specifier = ">=6.0.12.20250402,<7.0.0" }, +] +docs = [{ name = "sphinxnotes-markdown-builder", specifier = ">=0.5.6,<0.6.0" }] + +[[package]] +name = "algokit-utils" +version = "5.0.0a17" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "msgpack" }, + { name = "msgpack-types" }, + { name = "pycryptodomex" }, + { name = "pynacl" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/06/dc995bfddff9bf64e67f9b74b6bced79e404f3f87a4948d85de7e6516045/algokit_utils-5.0.0a17.tar.gz", hash = "sha256:378773ec6d24a9838c7be90b79810359544848d9a7ddafd38655e9a468809bd3", size = 217266, upload-time = "2026-02-20T20:40:24.165Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/19/d4f4be3aae15294f8ab90e07be71abe82a10da862b4544878a005a6fcd68/algokit_utils-5.0.0a17-py3-none-any.whl", hash = "sha256:4c896e8cdfaedc32b67ff0bce6981d999e4da5319fe0aafcc749e16a820c0fdc", size = 337339, upload-time = "2026-02-20T20:40:22.708Z" }, +] + +[[package]] +name = "allpairspy" +version = "2.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ea/9e/a5a536c22f56cdbbb0236889cff33915e20fb93a0526887367b38e91122e/allpairspy-2.5.1.tar.gz", hash = "sha256:f69d31a3b56eee119d1ec6063e9c732dd44fbba352ef738cb22d9699fc4009fe", size = 14281, upload-time = "2023-07-08T09:08:54.049Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/1a/fedf0f2ff77ec65e599112b2d5402fee5c166d9378b51760b696bd8cde1d/allpairspy-2.5.1-py3-none-any.whl", hash = "sha256:3f97cbac2bbee86f4bfceffd0fd91dca740a120c78e9368af2bad81a2b3426e2", size = 8965, upload-time = "2023-07-08T09:08:51.994Z" }, +] + +[[package]] +name = "altgraph" +version = "0.17.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/f8/97fdf103f38fed6792a1601dbc16cc8aac56e7459a9fff08c812d8ae177a/altgraph-0.17.5.tar.gz", hash = "sha256:c87b395dd12fabde9c99573a9749d67da8d29ef9de0125c7f536699b4a9bc9e7", size = 48428, upload-time = "2025-11-21T20:35:50.583Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/ba/000a1996d4308bc65120167c21241a3b205464a2e0b58deda26ae8ac21d1/altgraph-0.17.5-py2.py3-none-any.whl", hash = "sha256:f3a22400bce1b0c701683820ac4f3b159cd301acab067c51c653e06961600597", size = 21228, upload-time = "2025-11-21T20:35:49.444Z" }, +] + +[[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, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "anyio" +version = "4.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" }, +] + +[[package]] +name = "approval-utilities" +version = "7.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/60/4c/fcf3bbd765b99086cdd58ab93378363195f6ec985e542d52aedb41b101bb/approval_utilities-7.4.0.tar.gz", hash = "sha256:8e0b146716db2f7d95d01726947438904760a6cb005aa391cee6f7a623d627ee", size = 16445, upload-time = "2022-12-11T19:10:40.624Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/9c/01596fbd22d57f5b75f7a203c9a25a9f94753da6c85ede8fb97ed8d7232f/approval_utilities-7.4.0-py3-none-any.whl", hash = "sha256:d11f545ad318f3520e997657aaeb6511521a4d0b647a0868037ca817af7c73b3", size = 17136, upload-time = "2022-12-11T19:10:39.068Z" }, +] + +[[package]] +name = "approvaltests" +version = "7.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "allpairspy" }, + { name = "approval-utilities" }, + { name = "beautifulsoup4" }, + { name = "empty-files" }, + { name = "mrjob" }, + { name = "pyperclip" }, + { name = "pytest" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/44/c7/3a85d9a136b27922a51c4aba505cbca26ffdb9f860ea93e3f5ae4eda3e5c/approvaltests-7.4.0.tar.gz", hash = "sha256:e09b2f2af6cd049d71a3dcdc7b3bb4c2cd887cc5eb4b1294b557675360c5f90d", size = 35166, upload-time = "2022-12-11T19:10:44.306Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/34/58af7f3e316be630a1568ae40a1117a22d6298fb59a707c0470c7593bc26/approvaltests-7.4.0-py3-none-any.whl", hash = "sha256:64e8798f843f44ffd047935f18e8ec850caf9d4f924b9b24456008102cbb6aca", size = 59778, upload-time = "2022-12-11T19:10:42.67Z" }, +] + +[[package]] +name = "babel" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, +] + +[[package]] +name = "backports-tarfile" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", size = 86406, upload-time = "2024-05-28T17:01:54.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181, upload-time = "2024-05-28T17:01:53.112Z" }, +] + +[[package]] +name = "bases" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, + { name = "typing-validation" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/8d/105bca352e2fc5f1ee07f425ec296aa680525aac7f197ef135ea057902ac/bases-0.3.0.tar.gz", hash = "sha256:70f04a4a45d63245787f9e89095ca11042685b6b64b542ad916575ba3ccd1570", size = 789978, upload-time = "2023-12-18T16:57:17.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b4/15/7bcf28a3f971e1b0523fab46ae3ca935a589249544187558e5a8e70af393/bases-0.3.0-py3-none-any.whl", hash = "sha256:a2fef3366f3e522ff473d2e95c21523fe8e44251038d5c6150c01481585ebf5b", size = 36053, upload-time = "2023-12-18T16:57:14.253Z" }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, +] + +[[package]] +name = "boolean-py" +version = "5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c4/cf/85379f13b76f3a69bca86b60237978af17d6aa0bc5998978c3b8cf05abb2/boolean_py-5.0.tar.gz", hash = "sha256:60cbc4bad079753721d32649545505362c754e121570ada4658b852a3a318d95", size = 37047, upload-time = "2025-04-03T10:39:49.734Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/ca/78d423b324b8d77900030fa59c4aa9054261ef0925631cd2501dd015b7b7/boolean_py-5.0-py3-none-any.whl", hash = "sha256:ef28a70bd43115208441b53a045d1549e2f0ec6e3d08a9d142cbc41c1938e8d9", size = 26577, upload-time = "2025-04-03T10:39:48.449Z" }, +] + +[[package]] +name = "cachecontrol" +version = "0.14.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "msgpack" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2d/f6/c972b32d80760fb79d6b9eeb0b3010a46b89c0b23cf6329417ff7886cd22/cachecontrol-0.14.4.tar.gz", hash = "sha256:e6220afafa4c22a47dd0badb319f84475d79108100d04e26e8542ef7d3ab05a1", size = 16150, upload-time = "2025-11-14T04:32:13.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/79/c45f2d53efe6ada1110cf6f9fca095e4ff47a0454444aefdde6ac4789179/cachecontrol-0.14.4-py3-none-any.whl", hash = "sha256:b7ac014ff72ee199b5f8af1de29d60239954f223e948196fa3d84adaffc71d2b", size = 22247, upload-time = "2025-11-14T04:32:11.733Z" }, +] + +[package.optional-dependencies] +filecache = [ + { name = "filelock" }, +] + +[[package]] +name = "certifi" +version = "2026.2.25" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" }, +] + +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44", size = 184283, upload-time = "2025-09-08T23:22:08.01Z" }, + { url = "https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49", size = 180504, upload-time = "2025-09-08T23:22:10.637Z" }, + { url = "https://files.pythonhosted.org/packages/50/bd/b1a6362b80628111e6653c961f987faa55262b4002fcec42308cad1db680/cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", size = 208811, upload-time = "2025-09-08T23:22:12.267Z" }, + { url = "https://files.pythonhosted.org/packages/4f/27/6933a8b2562d7bd1fb595074cf99cc81fc3789f6a6c05cdabb46284a3188/cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", size = 216402, upload-time = "2025-09-08T23:22:13.455Z" }, + { url = "https://files.pythonhosted.org/packages/05/eb/b86f2a2645b62adcfff53b0dd97e8dfafb5c8aa864bd0d9a2c2049a0d551/cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", size = 203217, upload-time = "2025-09-08T23:22:14.596Z" }, + { url = "https://files.pythonhosted.org/packages/9f/e0/6cbe77a53acf5acc7c08cc186c9928864bd7c005f9efd0d126884858a5fe/cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4", size = 203079, upload-time = "2025-09-08T23:22:15.769Z" }, + { url = "https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", size = 216475, upload-time = "2025-09-08T23:22:17.427Z" }, + { url = "https://files.pythonhosted.org/packages/21/7a/13b24e70d2f90a322f2900c5d8e1f14fa7e2a6b3332b7309ba7b2ba51a5a/cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", size = 218829, upload-time = "2025-09-08T23:22:19.069Z" }, + { url = "https://files.pythonhosted.org/packages/60/99/c9dc110974c59cc981b1f5b66e1d8af8af764e00f0293266824d9c4254bc/cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", size = 211211, upload-time = "2025-09-08T23:22:20.588Z" }, + { url = "https://files.pythonhosted.org/packages/49/72/ff2d12dbf21aca1b32a40ed792ee6b40f6dc3a9cf1644bd7ef6e95e0ac5e/cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", size = 218036, upload-time = "2025-09-08T23:22:22.143Z" }, + { url = "https://files.pythonhosted.org/packages/e2/cc/027d7fb82e58c48ea717149b03bcadcbdc293553edb283af792bd4bcbb3f/cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a", size = 172184, upload-time = "2025-09-08T23:22:23.328Z" }, + { url = "https://files.pythonhosted.org/packages/33/fa/072dd15ae27fbb4e06b437eb6e944e75b068deb09e2a2826039e49ee2045/cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739", size = 182790, upload-time = "2025-09-08T23:22:24.752Z" }, + { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" }, + { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, + { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, + { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" }, + { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" }, + { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" }, + { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, + { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, + { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" }, + { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" }, + { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, + { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, + { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, + { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, + { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, + { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, + { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, + { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, + { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + +[[package]] +name = "cfgv" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/b8/6d51fc1d52cbd52cd4ccedd5b5b2f0f6a11bbf6765c782298b0f3e808541/charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d", size = 209709, upload-time = "2025-10-14T04:40:11.385Z" }, + { url = "https://files.pythonhosted.org/packages/5c/af/1f9d7f7faafe2ddfb6f72a2e07a548a629c61ad510fe60f9630309908fef/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8", size = 148814, upload-time = "2025-10-14T04:40:13.135Z" }, + { url = "https://files.pythonhosted.org/packages/79/3d/f2e3ac2bbc056ca0c204298ea4e3d9db9b4afe437812638759db2c976b5f/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad", size = 144467, upload-time = "2025-10-14T04:40:14.728Z" }, + { url = "https://files.pythonhosted.org/packages/ec/85/1bf997003815e60d57de7bd972c57dc6950446a3e4ccac43bc3070721856/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8", size = 162280, upload-time = "2025-10-14T04:40:16.14Z" }, + { url = "https://files.pythonhosted.org/packages/3e/8e/6aa1952f56b192f54921c436b87f2aaf7c7a7c3d0d1a765547d64fd83c13/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d", size = 159454, upload-time = "2025-10-14T04:40:17.567Z" }, + { url = "https://files.pythonhosted.org/packages/36/3b/60cbd1f8e93aa25d1c669c649b7a655b0b5fb4c571858910ea9332678558/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313", size = 153609, upload-time = "2025-10-14T04:40:19.08Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/6a13396948b8fd3c4b4fd5bc74d045f5637d78c9675585e8e9fbe5636554/charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e", size = 151849, upload-time = "2025-10-14T04:40:20.607Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7a/59482e28b9981d105691e968c544cc0df3b7d6133152fb3dcdc8f135da7a/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93", size = 151586, upload-time = "2025-10-14T04:40:21.719Z" }, + { url = "https://files.pythonhosted.org/packages/92/59/f64ef6a1c4bdd2baf892b04cd78792ed8684fbc48d4c2afe467d96b4df57/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0", size = 145290, upload-time = "2025-10-14T04:40:23.069Z" }, + { url = "https://files.pythonhosted.org/packages/6b/63/3bf9f279ddfa641ffa1962b0db6a57a9c294361cc2f5fcac997049a00e9c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84", size = 163663, upload-time = "2025-10-14T04:40:24.17Z" }, + { url = "https://files.pythonhosted.org/packages/ed/09/c9e38fc8fa9e0849b172b581fd9803bdf6e694041127933934184e19f8c3/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e", size = 151964, upload-time = "2025-10-14T04:40:25.368Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d1/d28b747e512d0da79d8b6a1ac18b7ab2ecfd81b2944c4c710e166d8dd09c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db", size = 161064, upload-time = "2025-10-14T04:40:26.806Z" }, + { url = "https://files.pythonhosted.org/packages/bb/9a/31d62b611d901c3b9e5500c36aab0ff5eb442043fb3a1c254200d3d397d9/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6", size = 155015, upload-time = "2025-10-14T04:40:28.284Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f3/107e008fa2bff0c8b9319584174418e5e5285fef32f79d8ee6a430d0039c/charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f", size = 99792, upload-time = "2025-10-14T04:40:29.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/66/e396e8a408843337d7315bab30dbf106c38966f1819f123257f5520f8a96/charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d", size = 107198, upload-time = "2025-10-14T04:40:30.644Z" }, + { url = "https://files.pythonhosted.org/packages/b5/58/01b4f815bf0312704c267f2ccb6e5d42bcc7752340cd487bc9f8c3710597/charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69", size = 100262, upload-time = "2025-10-14T04:40:32.108Z" }, + { url = "https://files.pythonhosted.org/packages/ed/27/c6491ff4954e58a10f69ad90aca8a1b6fe9c5d3c6f380907af3c37435b59/charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", size = 206988, upload-time = "2025-10-14T04:40:33.79Z" }, + { url = "https://files.pythonhosted.org/packages/94/59/2e87300fe67ab820b5428580a53cad894272dbb97f38a7a814a2a1ac1011/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", size = 147324, upload-time = "2025-10-14T04:40:34.961Z" }, + { url = "https://files.pythonhosted.org/packages/07/fb/0cf61dc84b2b088391830f6274cb57c82e4da8bbc2efeac8c025edb88772/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", size = 142742, upload-time = "2025-10-14T04:40:36.105Z" }, + { url = "https://files.pythonhosted.org/packages/62/8b/171935adf2312cd745d290ed93cf16cf0dfe320863ab7cbeeae1dcd6535f/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", size = 160863, upload-time = "2025-10-14T04:40:37.188Z" }, + { url = "https://files.pythonhosted.org/packages/09/73/ad875b192bda14f2173bfc1bc9a55e009808484a4b256748d931b6948442/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", size = 157837, upload-time = "2025-10-14T04:40:38.435Z" }, + { url = "https://files.pythonhosted.org/packages/6d/fc/de9cce525b2c5b94b47c70a4b4fb19f871b24995c728e957ee68ab1671ea/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", size = 151550, upload-time = "2025-10-14T04:40:40.053Z" }, + { url = "https://files.pythonhosted.org/packages/55/c2/43edd615fdfba8c6f2dfbd459b25a6b3b551f24ea21981e23fb768503ce1/charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", size = 149162, upload-time = "2025-10-14T04:40:41.163Z" }, + { url = "https://files.pythonhosted.org/packages/03/86/bde4ad8b4d0e9429a4e82c1e8f5c659993a9a863ad62c7df05cf7b678d75/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", size = 150019, upload-time = "2025-10-14T04:40:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/1f/86/a151eb2af293a7e7bac3a739b81072585ce36ccfb4493039f49f1d3cae8c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", size = 143310, upload-time = "2025-10-14T04:40:43.439Z" }, + { url = "https://files.pythonhosted.org/packages/b5/fe/43dae6144a7e07b87478fdfc4dbe9efd5defb0e7ec29f5f58a55aeef7bf7/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", size = 162022, upload-time = "2025-10-14T04:40:44.547Z" }, + { url = "https://files.pythonhosted.org/packages/80/e6/7aab83774f5d2bca81f42ac58d04caf44f0cc2b65fc6db2b3b2e8a05f3b3/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", size = 149383, upload-time = "2025-10-14T04:40:46.018Z" }, + { url = "https://files.pythonhosted.org/packages/4f/e8/b289173b4edae05c0dde07f69f8db476a0b511eac556dfe0d6bda3c43384/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", size = 159098, upload-time = "2025-10-14T04:40:47.081Z" }, + { url = "https://files.pythonhosted.org/packages/d8/df/fe699727754cae3f8478493c7f45f777b17c3ef0600e28abfec8619eb49c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", size = 152991, upload-time = "2025-10-14T04:40:48.246Z" }, + { url = "https://files.pythonhosted.org/packages/1a/86/584869fe4ddb6ffa3bd9f491b87a01568797fb9bd8933f557dba9771beaf/charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", size = 99456, upload-time = "2025-10-14T04:40:49.376Z" }, + { url = "https://files.pythonhosted.org/packages/65/f6/62fdd5feb60530f50f7e38b4f6a1d5203f4d16ff4f9f0952962c044e919a/charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", size = 106978, upload-time = "2025-10-14T04:40:50.844Z" }, + { url = "https://files.pythonhosted.org/packages/7a/9d/0710916e6c82948b3be62d9d398cb4fcf4e97b56d6a6aeccd66c4b2f2bd5/charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", size = 99969, upload-time = "2025-10-14T04:40:52.272Z" }, + { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, + { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, + { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, + { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, + { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, + { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, + { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, + { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, + { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, + { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, + { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, + { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, + { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, + { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, + { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, + { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, + { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, + { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, + { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, + { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +] + +[[package]] +name = "click" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, +] + +[[package]] +name = "click-log" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/32/32/228be4f971e4bd556c33d52a22682bfe318ffe57a1ddb7a546f347a90260/click-log-0.4.0.tar.gz", hash = "sha256:3970f8570ac54491237bcdb3d8ab5e3eef6c057df29f8c3d1151a51a9c23b975", size = 9985, upload-time = "2022-03-13T11:10:15.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/5a/4f025bc751087833686892e17e7564828e409c43b632878afeae554870cd/click_log-0.4.0-py2.py3-none-any.whl", hash = "sha256:a43e394b528d52112af599f2fc9e4b7cf3c15f94e53581f74fa6867e68c91756", size = 4273, upload-time = "2022-03-13T11:10:17.594Z" }, +] + +[[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, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "copier" +version = "9.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, + { name = "dunamai" }, + { name = "funcy" }, + { name = "jinja2" }, + { name = "jinja2-ansible-filters" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "plumbum" }, + { name = "pydantic" }, + { name = "pygments" }, + { name = "pyyaml" }, + { name = "questionary" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6b/e0/5187c63a9020e84cfbb3cc52b52d7fc15aab73fd1e9106ae33167116a3f9/copier-9.12.0.tar.gz", hash = "sha256:87986637205a0443dbf7e5946502e5c71962a559c25f436642a08203cf61ef54", size = 611292, upload-time = "2026-02-21T13:32:40.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/22/6d9cfea622a064d17f406bbea1dd37f95ac75094d44e23447df934661add/copier-9.12.0-py3-none-any.whl", hash = "sha256:a1bc84dfd2a4b85dbe034999026c0e24ca02a6bc1574f45df07fd76d935c2ea9", size = 58805, upload-time = "2026-02-21T13:32:38.767Z" }, +] + +[[package]] +name = "coverage" +version = "7.13.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/56/95b7e30fa389756cb56630faa728da46a27b8c6eb46f9d557c68fff12b65/coverage-7.13.4.tar.gz", hash = "sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91", size = 827239, upload-time = "2026-02-09T12:59:03.86Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/d4/7827d9ffa34d5d4d752eec907022aa417120936282fc488306f5da08c292/coverage-7.13.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0fc31c787a84f8cd6027eba44010517020e0d18487064cd3d8968941856d1415", size = 219152, upload-time = "2026-02-09T12:56:11.974Z" }, + { url = "https://files.pythonhosted.org/packages/35/b0/d69df26607c64043292644dbb9dc54b0856fabaa2cbb1eeee3331cc9e280/coverage-7.13.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a32ebc02a1805adf637fc8dec324b5cdacd2e493515424f70ee33799573d661b", size = 219667, upload-time = "2026-02-09T12:56:13.33Z" }, + { url = "https://files.pythonhosted.org/packages/82/a4/c1523f7c9e47b2271dbf8c2a097e7a1f89ef0d66f5840bb59b7e8814157b/coverage-7.13.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e24f9156097ff9dc286f2f913df3a7f63c0e333dcafa3c196f2c18b4175ca09a", size = 246425, upload-time = "2026-02-09T12:56:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/f8/02/aa7ec01d1a5023c4b680ab7257f9bfde9defe8fdddfe40be096ac19e8177/coverage-7.13.4-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8041b6c5bfdc03257666e9881d33b1abc88daccaf73f7b6340fb7946655cd10f", size = 248229, upload-time = "2026-02-09T12:56:16.31Z" }, + { url = "https://files.pythonhosted.org/packages/35/98/85aba0aed5126d896162087ef3f0e789a225697245256fc6181b95f47207/coverage-7.13.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a09cfa6a5862bc2fc6ca7c3def5b2926194a56b8ab78ffcf617d28911123012", size = 250106, upload-time = "2026-02-09T12:56:18.024Z" }, + { url = "https://files.pythonhosted.org/packages/96/72/1db59bd67494bc162e3e4cd5fbc7edba2c7026b22f7c8ef1496d58c2b94c/coverage-7.13.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:296f8b0af861d3970c2a4d8c91d48eb4dd4771bcef9baedec6a9b515d7de3def", size = 252021, upload-time = "2026-02-09T12:56:19.272Z" }, + { url = "https://files.pythonhosted.org/packages/9d/97/72899c59c7066961de6e3daa142d459d47d104956db43e057e034f015c8a/coverage-7.13.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e101609bcbbfb04605ea1027b10dc3735c094d12d40826a60f897b98b1c30256", size = 247114, upload-time = "2026-02-09T12:56:21.051Z" }, + { url = "https://files.pythonhosted.org/packages/39/1f/f1885573b5970235e908da4389176936c8933e86cb316b9620aab1585fa2/coverage-7.13.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:aa3feb8db2e87ff5e6d00d7e1480ae241876286691265657b500886c98f38bda", size = 248143, upload-time = "2026-02-09T12:56:22.585Z" }, + { url = "https://files.pythonhosted.org/packages/a8/cf/e80390c5b7480b722fa3e994f8202807799b85bc562aa4f1dde209fbb7be/coverage-7.13.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4fc7fa81bbaf5a02801b65346c8b3e657f1d93763e58c0abdf7c992addd81a92", size = 246152, upload-time = "2026-02-09T12:56:23.748Z" }, + { url = "https://files.pythonhosted.org/packages/44/bf/f89a8350d85572f95412debb0fb9bb4795b1d5b5232bd652923c759e787b/coverage-7.13.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:33901f604424145c6e9c2398684b92e176c0b12df77d52db81c20abd48c3794c", size = 249959, upload-time = "2026-02-09T12:56:25.209Z" }, + { url = "https://files.pythonhosted.org/packages/f7/6e/612a02aece8178c818df273e8d1642190c4875402ca2ba74514394b27aba/coverage-7.13.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:bb28c0f2cf2782508a40cec377935829d5fcc3ad9a3681375af4e84eb34b6b58", size = 246416, upload-time = "2026-02-09T12:56:26.475Z" }, + { url = "https://files.pythonhosted.org/packages/cb/98/b5afc39af67c2fa6786b03c3a7091fc300947387ce8914b096db8a73d67a/coverage-7.13.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9d107aff57a83222ddbd8d9ee705ede2af2cc926608b57abed8ef96b50b7e8f9", size = 247025, upload-time = "2026-02-09T12:56:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/51/30/2bba8ef0682d5bd210c38fe497e12a06c9f8d663f7025e9f5c2c31ce847d/coverage-7.13.4-cp310-cp310-win32.whl", hash = "sha256:a6f94a7d00eb18f1b6d403c91a88fd58cfc92d4b16080dfdb774afc8294469bf", size = 221758, upload-time = "2026-02-09T12:56:29.051Z" }, + { url = "https://files.pythonhosted.org/packages/78/13/331f94934cf6c092b8ea59ff868eb587bc8fe0893f02c55bc6c0183a192e/coverage-7.13.4-cp310-cp310-win_amd64.whl", hash = "sha256:2cb0f1e000ebc419632bbe04366a8990b6e32c4e0b51543a6484ffe15eaeda95", size = 222693, upload-time = "2026-02-09T12:56:30.366Z" }, + { url = "https://files.pythonhosted.org/packages/b4/ad/b59e5b451cf7172b8d1043dc0fa718f23aab379bc1521ee13d4bd9bfa960/coverage-7.13.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d490ba50c3f35dd7c17953c68f3270e7ccd1c6642e2d2afe2d8e720b98f5a053", size = 219278, upload-time = "2026-02-09T12:56:31.673Z" }, + { url = "https://files.pythonhosted.org/packages/f1/17/0cb7ca3de72e5f4ef2ec2fa0089beafbcaaaead1844e8b8a63d35173d77d/coverage-7.13.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:19bc3c88078789f8ef36acb014d7241961dbf883fd2533d18cb1e7a5b4e28b11", size = 219783, upload-time = "2026-02-09T12:56:33.104Z" }, + { url = "https://files.pythonhosted.org/packages/ab/63/325d8e5b11e0eaf6d0f6a44fad444ae58820929a9b0de943fa377fe73e85/coverage-7.13.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3998e5a32e62fdf410c0dbd3115df86297995d6e3429af80b8798aad894ca7aa", size = 250200, upload-time = "2026-02-09T12:56:34.474Z" }, + { url = "https://files.pythonhosted.org/packages/76/53/c16972708cbb79f2942922571a687c52bd109a7bd51175aeb7558dff2236/coverage-7.13.4-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8e264226ec98e01a8e1054314af91ee6cde0eacac4f465cc93b03dbe0bce2fd7", size = 252114, upload-time = "2026-02-09T12:56:35.749Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c2/7ab36d8b8cc412bec9ea2d07c83c48930eb4ba649634ba00cb7e4e0f9017/coverage-7.13.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3aa4e7b9e416774b21797365b358a6e827ffadaaca81b69ee02946852449f00", size = 254220, upload-time = "2026-02-09T12:56:37.796Z" }, + { url = "https://files.pythonhosted.org/packages/d6/4d/cf52c9a3322c89a0e6febdfbc83bb45c0ed3c64ad14081b9503adee702e7/coverage-7.13.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:71ca20079dd8f27fcf808817e281e90220475cd75115162218d0e27549f95fef", size = 256164, upload-time = "2026-02-09T12:56:39.016Z" }, + { url = "https://files.pythonhosted.org/packages/78/e9/eb1dd17bd6de8289df3580e967e78294f352a5df8a57ff4671ee5fc3dcd0/coverage-7.13.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e2f25215f1a359ab17320b47bcdaca3e6e6356652e8256f2441e4ef972052903", size = 250325, upload-time = "2026-02-09T12:56:40.668Z" }, + { url = "https://files.pythonhosted.org/packages/71/07/8c1542aa873728f72267c07278c5cc0ec91356daf974df21335ccdb46368/coverage-7.13.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d65b2d373032411e86960604dc4edac91fdfb5dca539461cf2cbe78327d1e64f", size = 251913, upload-time = "2026-02-09T12:56:41.97Z" }, + { url = "https://files.pythonhosted.org/packages/74/d7/c62e2c5e4483a748e27868e4c32ad3daa9bdddbba58e1bc7a15e252baa74/coverage-7.13.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94eb63f9b363180aff17de3e7c8760c3ba94664ea2695c52f10111244d16a299", size = 249974, upload-time = "2026-02-09T12:56:43.323Z" }, + { url = "https://files.pythonhosted.org/packages/98/9f/4c5c015a6e98ced54efd0f5cf8d31b88e5504ecb6857585fc0161bb1e600/coverage-7.13.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e856bf6616714c3a9fbc270ab54103f4e685ba236fa98c054e8f87f266c93505", size = 253741, upload-time = "2026-02-09T12:56:45.155Z" }, + { url = "https://files.pythonhosted.org/packages/bd/59/0f4eef89b9f0fcd9633b5d350016f54126ab49426a70ff4c4e87446cabdc/coverage-7.13.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:65dfcbe305c3dfe658492df2d85259e0d79ead4177f9ae724b6fb245198f55d6", size = 249695, upload-time = "2026-02-09T12:56:46.636Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2c/b7476f938deb07166f3eb281a385c262675d688ff4659ad56c6c6b8e2e70/coverage-7.13.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b507778ae8a4c915436ed5c2e05b4a6cecfa70f734e19c22a005152a11c7b6a9", size = 250599, upload-time = "2026-02-09T12:56:48.13Z" }, + { url = "https://files.pythonhosted.org/packages/b8/34/c3420709d9846ee3785b9f2831b4d94f276f38884032dca1457fa83f7476/coverage-7.13.4-cp311-cp311-win32.whl", hash = "sha256:784fc3cf8be001197b652d51d3fd259b1e2262888693a4636e18879f613a62a9", size = 221780, upload-time = "2026-02-09T12:56:50.479Z" }, + { url = "https://files.pythonhosted.org/packages/61/08/3d9c8613079d2b11c185b865de9a4c1a68850cfda2b357fae365cf609f29/coverage-7.13.4-cp311-cp311-win_amd64.whl", hash = "sha256:2421d591f8ca05b308cf0092807308b2facbefe54af7c02ac22548b88b95c98f", size = 222715, upload-time = "2026-02-09T12:56:51.815Z" }, + { url = "https://files.pythonhosted.org/packages/18/1a/54c3c80b2f056164cc0a6cdcb040733760c7c4be9d780fe655f356f433e4/coverage-7.13.4-cp311-cp311-win_arm64.whl", hash = "sha256:79e73a76b854d9c6088fe5d8b2ebe745f8681c55f7397c3c0a016192d681045f", size = 221385, upload-time = "2026-02-09T12:56:53.194Z" }, + { url = "https://files.pythonhosted.org/packages/d1/81/4ce2fdd909c5a0ed1f6dedb88aa57ab79b6d1fbd9b588c1ac7ef45659566/coverage-7.13.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:02231499b08dabbe2b96612993e5fc34217cdae907a51b906ac7fca8027a4459", size = 219449, upload-time = "2026-02-09T12:56:54.889Z" }, + { url = "https://files.pythonhosted.org/packages/5d/96/5238b1efc5922ddbdc9b0db9243152c09777804fb7c02ad1741eb18a11c0/coverage-7.13.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40aa8808140e55dc022b15d8aa7f651b6b3d68b365ea0398f1441e0b04d859c3", size = 219810, upload-time = "2026-02-09T12:56:56.33Z" }, + { url = "https://files.pythonhosted.org/packages/78/72/2f372b726d433c9c35e56377cf1d513b4c16fe51841060d826b95caacec1/coverage-7.13.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5b856a8ccf749480024ff3bd7310adaef57bf31fd17e1bfc404b7940b6986634", size = 251308, upload-time = "2026-02-09T12:56:57.858Z" }, + { url = "https://files.pythonhosted.org/packages/5d/a0/2ea570925524ef4e00bb6c82649f5682a77fac5ab910a65c9284de422600/coverage-7.13.4-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2c048ea43875fbf8b45d476ad79f179809c590ec7b79e2035c662e7afa3192e3", size = 254052, upload-time = "2026-02-09T12:56:59.754Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ac/45dc2e19a1939098d783c846e130b8f862fbb50d09e0af663988f2f21973/coverage-7.13.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b7b38448866e83176e28086674fe7368ab8590e4610fb662b44e345b86d63ffa", size = 255165, upload-time = "2026-02-09T12:57:01.287Z" }, + { url = "https://files.pythonhosted.org/packages/2d/4d/26d236ff35abc3b5e63540d3386e4c3b192168c1d96da5cb2f43c640970f/coverage-7.13.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:de6defc1c9badbf8b9e67ae90fd00519186d6ab64e5cc5f3d21359c2a9b2c1d3", size = 257432, upload-time = "2026-02-09T12:57:02.637Z" }, + { url = "https://files.pythonhosted.org/packages/ec/55/14a966c757d1348b2e19caf699415a2a4c4f7feaa4bbc6326a51f5c7dd1b/coverage-7.13.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7eda778067ad7ffccd23ecffce537dface96212576a07924cbf0d8799d2ded5a", size = 251716, upload-time = "2026-02-09T12:57:04.056Z" }, + { url = "https://files.pythonhosted.org/packages/77/33/50116647905837c66d28b2af1321b845d5f5d19be9655cb84d4a0ea806b4/coverage-7.13.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e87f6c587c3f34356c3759f0420693e35e7eb0e2e41e4c011cb6ec6ecbbf1db7", size = 253089, upload-time = "2026-02-09T12:57:05.503Z" }, + { url = "https://files.pythonhosted.org/packages/c2/b4/8efb11a46e3665d92635a56e4f2d4529de6d33f2cb38afd47d779d15fc99/coverage-7.13.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8248977c2e33aecb2ced42fef99f2d319e9904a36e55a8a68b69207fb7e43edc", size = 251232, upload-time = "2026-02-09T12:57:06.879Z" }, + { url = "https://files.pythonhosted.org/packages/51/24/8cd73dd399b812cc76bb0ac260e671c4163093441847ffe058ac9fda1e32/coverage-7.13.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:25381386e80ae727608e662474db537d4df1ecd42379b5ba33c84633a2b36d47", size = 255299, upload-time = "2026-02-09T12:57:08.245Z" }, + { url = "https://files.pythonhosted.org/packages/03/94/0a4b12f1d0e029ce1ccc1c800944a9984cbe7d678e470bb6d3c6bc38a0da/coverage-7.13.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ee756f00726693e5ba94d6df2bdfd64d4852d23b09bb0bc700e3b30e6f333985", size = 250796, upload-time = "2026-02-09T12:57:10.142Z" }, + { url = "https://files.pythonhosted.org/packages/73/44/6002fbf88f6698ca034360ce474c406be6d5a985b3fdb3401128031eef6b/coverage-7.13.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fdfc1e28e7c7cdce44985b3043bc13bbd9c747520f94a4d7164af8260b3d91f0", size = 252673, upload-time = "2026-02-09T12:57:12.197Z" }, + { url = "https://files.pythonhosted.org/packages/de/c6/a0279f7c00e786be75a749a5674e6fa267bcbd8209cd10c9a450c655dfa7/coverage-7.13.4-cp312-cp312-win32.whl", hash = "sha256:01d4cbc3c283a17fc1e42d614a119f7f438eabb593391283adca8dc86eff1246", size = 221990, upload-time = "2026-02-09T12:57:14.085Z" }, + { url = "https://files.pythonhosted.org/packages/77/4e/c0a25a425fcf5557d9abd18419c95b63922e897bc86c1f327f155ef234a9/coverage-7.13.4-cp312-cp312-win_amd64.whl", hash = "sha256:9401ebc7ef522f01d01d45532c68c5ac40fb27113019b6b7d8b208f6e9baa126", size = 222800, upload-time = "2026-02-09T12:57:15.944Z" }, + { url = "https://files.pythonhosted.org/packages/47/ac/92da44ad9a6f4e3a7debd178949d6f3769bedca33830ce9b1dcdab589a37/coverage-7.13.4-cp312-cp312-win_arm64.whl", hash = "sha256:b1ec7b6b6e93255f952e27ab58fbc68dcc468844b16ecbee881aeb29b6ab4d8d", size = 221415, upload-time = "2026-02-09T12:57:17.497Z" }, + { url = "https://files.pythonhosted.org/packages/db/23/aad45061a31677d68e47499197a131eea55da4875d16c1f42021ab963503/coverage-7.13.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b66a2da594b6068b48b2692f043f35d4d3693fb639d5ea8b39533c2ad9ac3ab9", size = 219474, upload-time = "2026-02-09T12:57:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/a5/70/9b8b67a0945f3dfec1fd896c5cefb7c19d5a3a6d74630b99a895170999ae/coverage-7.13.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3599eb3992d814d23b35c536c28df1a882caa950f8f507cef23d1cbf334995ac", size = 219844, upload-time = "2026-02-09T12:57:20.66Z" }, + { url = "https://files.pythonhosted.org/packages/97/fd/7e859f8fab324cef6c4ad7cff156ca7c489fef9179d5749b0c8d321281c2/coverage-7.13.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:93550784d9281e374fb5a12bf1324cc8a963fd63b2d2f223503ef0fd4aa339ea", size = 250832, upload-time = "2026-02-09T12:57:22.007Z" }, + { url = "https://files.pythonhosted.org/packages/e4/dc/b2442d10020c2f52617828862d8b6ee337859cd8f3a1f13d607dddda9cf7/coverage-7.13.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b720ce6a88a2755f7c697c23268ddc47a571b88052e6b155224347389fdf6a3b", size = 253434, upload-time = "2026-02-09T12:57:23.339Z" }, + { url = "https://files.pythonhosted.org/packages/5a/88/6728a7ad17428b18d836540630487231f5470fb82454871149502f5e5aa2/coverage-7.13.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b322db1284a2ed3aa28ffd8ebe3db91c929b7a333c0820abec3d838ef5b3525", size = 254676, upload-time = "2026-02-09T12:57:24.774Z" }, + { url = "https://files.pythonhosted.org/packages/7c/bc/21244b1b8cedf0dff0a2b53b208015fe798d5f2a8d5348dbfece04224fff/coverage-7.13.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4594c67d8a7c89cf922d9df0438c7c7bb022ad506eddb0fdb2863359ff78242", size = 256807, upload-time = "2026-02-09T12:57:26.125Z" }, + { url = "https://files.pythonhosted.org/packages/97/a0/ddba7ed3251cff51006737a727d84e05b61517d1784a9988a846ba508877/coverage-7.13.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:53d133df809c743eb8bce33b24bcababb371f4441340578cd406e084d94a6148", size = 251058, upload-time = "2026-02-09T12:57:27.614Z" }, + { url = "https://files.pythonhosted.org/packages/9b/55/e289addf7ff54d3a540526f33751951bf0878f3809b47f6dfb3def69c6f7/coverage-7.13.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76451d1978b95ba6507a039090ba076105c87cc76fc3efd5d35d72093964d49a", size = 252805, upload-time = "2026-02-09T12:57:29.066Z" }, + { url = "https://files.pythonhosted.org/packages/13/4e/cc276b1fa4a59be56d96f1dabddbdc30f4ba22e3b1cd42504c37b3313255/coverage-7.13.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f57b33491e281e962021de110b451ab8a24182589be17e12a22c79047935e23", size = 250766, upload-time = "2026-02-09T12:57:30.522Z" }, + { url = "https://files.pythonhosted.org/packages/94/44/1093b8f93018f8b41a8cf29636c9292502f05e4a113d4d107d14a3acd044/coverage-7.13.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1731dc33dc276dafc410a885cbf5992f1ff171393e48a21453b78727d090de80", size = 254923, upload-time = "2026-02-09T12:57:31.946Z" }, + { url = "https://files.pythonhosted.org/packages/8b/55/ea2796da2d42257f37dbea1aab239ba9263b31bd91d5527cdd6db5efe174/coverage-7.13.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:bd60d4fe2f6fa7dff9223ca1bbc9f05d2b6697bc5961072e5d3b952d46e1b1ea", size = 250591, upload-time = "2026-02-09T12:57:33.842Z" }, + { url = "https://files.pythonhosted.org/packages/d4/fa/7c4bb72aacf8af5020675aa633e59c1fbe296d22aed191b6a5b711eb2bc7/coverage-7.13.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9181a3ccead280b828fae232df12b16652702b49d41e99d657f46cc7b1f6ec7a", size = 252364, upload-time = "2026-02-09T12:57:35.743Z" }, + { url = "https://files.pythonhosted.org/packages/5c/38/a8d2ec0146479c20bbaa7181b5b455a0c41101eed57f10dd19a78ab44c80/coverage-7.13.4-cp313-cp313-win32.whl", hash = "sha256:f53d492307962561ac7de4cd1de3e363589b000ab69617c6156a16ba7237998d", size = 222010, upload-time = "2026-02-09T12:57:37.25Z" }, + { url = "https://files.pythonhosted.org/packages/e2/0c/dbfafbe90a185943dcfbc766fe0e1909f658811492d79b741523a414a6cc/coverage-7.13.4-cp313-cp313-win_amd64.whl", hash = "sha256:e6f70dec1cc557e52df5306d051ef56003f74d56e9c4dd7ddb07e07ef32a84dd", size = 222818, upload-time = "2026-02-09T12:57:38.734Z" }, + { url = "https://files.pythonhosted.org/packages/04/d1/934918a138c932c90d78301f45f677fb05c39a3112b96fd2c8e60503cdc7/coverage-7.13.4-cp313-cp313-win_arm64.whl", hash = "sha256:fb07dc5da7e849e2ad31a5d74e9bece81f30ecf5a42909d0a695f8bd1874d6af", size = 221438, upload-time = "2026-02-09T12:57:40.223Z" }, + { url = "https://files.pythonhosted.org/packages/52/57/ee93ced533bcb3e6df961c0c6e42da2fc6addae53fb95b94a89b1e33ebd7/coverage-7.13.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:40d74da8e6c4b9ac18b15331c4b5ebc35a17069410cad462ad4f40dcd2d50c0d", size = 220165, upload-time = "2026-02-09T12:57:41.639Z" }, + { url = "https://files.pythonhosted.org/packages/c5/e0/969fc285a6fbdda49d91af278488d904dcd7651b2693872f0ff94e40e84a/coverage-7.13.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4223b4230a376138939a9173f1bdd6521994f2aff8047fae100d6d94d50c5a12", size = 220516, upload-time = "2026-02-09T12:57:44.215Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b8/9531944e16267e2735a30a9641ff49671f07e8138ecf1ca13db9fd2560c7/coverage-7.13.4-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1d4be36a5114c499f9f1f9195e95ebf979460dbe2d88e6816ea202010ba1c34b", size = 261804, upload-time = "2026-02-09T12:57:45.989Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f3/e63df6d500314a2a60390d1989240d5f27318a7a68fa30ad3806e2a9323e/coverage-7.13.4-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:200dea7d1e8095cc6e98cdabe3fd1d21ab17d3cee6dab00cadbb2fe35d9c15b9", size = 263885, upload-time = "2026-02-09T12:57:47.42Z" }, + { url = "https://files.pythonhosted.org/packages/f3/67/7654810de580e14b37670b60a09c599fa348e48312db5b216d730857ffe6/coverage-7.13.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8eb931ee8e6d8243e253e5ed7336deea6904369d2fd8ae6e43f68abbf167092", size = 266308, upload-time = "2026-02-09T12:57:49.345Z" }, + { url = "https://files.pythonhosted.org/packages/37/6f/39d41eca0eab3cc82115953ad41c4e77935286c930e8fad15eaed1389d83/coverage-7.13.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:75eab1ebe4f2f64d9509b984f9314d4aa788540368218b858dad56dc8f3e5eb9", size = 267452, upload-time = "2026-02-09T12:57:50.811Z" }, + { url = "https://files.pythonhosted.org/packages/50/6d/39c0fbb8fc5cd4d2090811e553c2108cf5112e882f82505ee7495349a6bf/coverage-7.13.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c35eb28c1d085eb7d8c9b3296567a1bebe03ce72962e932431b9a61f28facf26", size = 261057, upload-time = "2026-02-09T12:57:52.447Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a2/60010c669df5fa603bb5a97fb75407e191a846510da70ac657eb696b7fce/coverage-7.13.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb88b316ec33760714a4720feb2816a3a59180fd58c1985012054fa7aebee4c2", size = 263875, upload-time = "2026-02-09T12:57:53.938Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d9/63b22a6bdbd17f1f96e9ed58604c2a6b0e72a9133e37d663bef185877cf6/coverage-7.13.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7d41eead3cc673cbd38a4417deb7fd0b4ca26954ff7dc6078e33f6ff97bed940", size = 261500, upload-time = "2026-02-09T12:57:56.012Z" }, + { url = "https://files.pythonhosted.org/packages/70/bf/69f86ba1ad85bc3ad240e4c0e57a2e620fbc0e1645a47b5c62f0e941ad7f/coverage-7.13.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:fb26a934946a6afe0e326aebe0730cdff393a8bc0bbb65a2f41e30feddca399c", size = 265212, upload-time = "2026-02-09T12:57:57.5Z" }, + { url = "https://files.pythonhosted.org/packages/ae/f2/5f65a278a8c2148731831574c73e42f57204243d33bedaaf18fa79c5958f/coverage-7.13.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:dae88bc0fc77edaa65c14be099bd57ee140cf507e6bfdeea7938457ab387efb0", size = 260398, upload-time = "2026-02-09T12:57:59.027Z" }, + { url = "https://files.pythonhosted.org/packages/ef/80/6e8280a350ee9fea92f14b8357448a242dcaa243cb2c72ab0ca591f66c8c/coverage-7.13.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:845f352911777a8e722bfce168958214951e07e47e5d5d9744109fa5fe77f79b", size = 262584, upload-time = "2026-02-09T12:58:01.129Z" }, + { url = "https://files.pythonhosted.org/packages/22/63/01ff182fc95f260b539590fb12c11ad3e21332c15f9799cb5e2386f71d9f/coverage-7.13.4-cp313-cp313t-win32.whl", hash = "sha256:2fa8d5f8de70688a28240de9e139fa16b153cc3cbb01c5f16d88d6505ebdadf9", size = 222688, upload-time = "2026-02-09T12:58:02.736Z" }, + { url = "https://files.pythonhosted.org/packages/a9/43/89de4ef5d3cd53b886afa114065f7e9d3707bdb3e5efae13535b46ae483d/coverage-7.13.4-cp313-cp313t-win_amd64.whl", hash = "sha256:9351229c8c8407645840edcc277f4a2d44814d1bc34a2128c11c2a031d45a5dd", size = 223746, upload-time = "2026-02-09T12:58:05.362Z" }, + { url = "https://files.pythonhosted.org/packages/35/39/7cf0aa9a10d470a5309b38b289b9bb07ddeac5d61af9b664fe9775a4cb3e/coverage-7.13.4-cp313-cp313t-win_arm64.whl", hash = "sha256:30b8d0512f2dc8c8747557e8fb459d6176a2c9e5731e2b74d311c03b78451997", size = 222003, upload-time = "2026-02-09T12:58:06.952Z" }, + { url = "https://files.pythonhosted.org/packages/92/11/a9cf762bb83386467737d32187756a42094927150c3e107df4cb078e8590/coverage-7.13.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:300deaee342f90696ed186e3a00c71b5b3d27bffe9e827677954f4ee56969601", size = 219522, upload-time = "2026-02-09T12:58:08.623Z" }, + { url = "https://files.pythonhosted.org/packages/d3/28/56e6d892b7b052236d67c95f1936b6a7cf7c3e2634bf27610b8cbd7f9c60/coverage-7.13.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29e3220258d682b6226a9b0925bc563ed9a1ebcff3cad30f043eceea7eaf2689", size = 219855, upload-time = "2026-02-09T12:58:10.176Z" }, + { url = "https://files.pythonhosted.org/packages/e5/69/233459ee9eb0c0d10fcc2fe425a029b3fa5ce0f040c966ebce851d030c70/coverage-7.13.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:391ee8f19bef69210978363ca930f7328081c6a0152f1166c91f0b5fdd2a773c", size = 250887, upload-time = "2026-02-09T12:58:12.503Z" }, + { url = "https://files.pythonhosted.org/packages/06/90/2cdab0974b9b5bbc1623f7876b73603aecac11b8d95b85b5b86b32de5eab/coverage-7.13.4-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0dd7ab8278f0d58a0128ba2fca25824321f05d059c1441800e934ff2efa52129", size = 253396, upload-time = "2026-02-09T12:58:14.615Z" }, + { url = "https://files.pythonhosted.org/packages/ac/15/ea4da0f85bf7d7b27635039e649e99deb8173fe551096ea15017f7053537/coverage-7.13.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78cdf0d578b15148b009ccf18c686aa4f719d887e76e6b40c38ffb61d264a552", size = 254745, upload-time = "2026-02-09T12:58:16.162Z" }, + { url = "https://files.pythonhosted.org/packages/99/11/bb356e86920c655ca4d61daee4e2bbc7258f0a37de0be32d233b561134ff/coverage-7.13.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:48685fee12c2eb3b27c62f2658e7ea21e9c3239cba5a8a242801a0a3f6a8c62a", size = 257055, upload-time = "2026-02-09T12:58:17.892Z" }, + { url = "https://files.pythonhosted.org/packages/c9/0f/9ae1f8cb17029e09da06ca4e28c9e1d5c1c0a511c7074592e37e0836c915/coverage-7.13.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4e83efc079eb39480e6346a15a1bcb3e9b04759c5202d157e1dd4303cd619356", size = 250911, upload-time = "2026-02-09T12:58:19.495Z" }, + { url = "https://files.pythonhosted.org/packages/89/3a/adfb68558fa815cbc29747b553bc833d2150228f251b127f1ce97e48547c/coverage-7.13.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ecae9737b72408d6a950f7e525f30aca12d4bd8dd95e37342e5beb3a2a8c4f71", size = 252754, upload-time = "2026-02-09T12:58:21.064Z" }, + { url = "https://files.pythonhosted.org/packages/32/b1/540d0c27c4e748bd3cd0bd001076ee416eda993c2bae47a73b7cc9357931/coverage-7.13.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ae4578f8528569d3cf303fef2ea569c7f4c4059a38c8667ccef15c6e1f118aa5", size = 250720, upload-time = "2026-02-09T12:58:22.622Z" }, + { url = "https://files.pythonhosted.org/packages/c7/95/383609462b3ffb1fe133014a7c84fc0dd01ed55ac6140fa1093b5af7ebb1/coverage-7.13.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:6fdef321fdfbb30a197efa02d48fcd9981f0d8ad2ae8903ac318adc653f5df98", size = 254994, upload-time = "2026-02-09T12:58:24.548Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ba/1761138e86c81680bfc3c49579d66312865457f9fe405b033184e5793cb3/coverage-7.13.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b0f6ccf3dbe577170bebfce1318707d0e8c3650003cb4b3a9dd744575daa8b5", size = 250531, upload-time = "2026-02-09T12:58:26.271Z" }, + { url = "https://files.pythonhosted.org/packages/f8/8e/05900df797a9c11837ab59c4d6fe94094e029582aab75c3309a93e6fb4e3/coverage-7.13.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75fcd519f2a5765db3f0e391eb3b7d150cce1a771bf4c9f861aeab86c767a3c0", size = 252189, upload-time = "2026-02-09T12:58:27.807Z" }, + { url = "https://files.pythonhosted.org/packages/00/bd/29c9f2db9ea4ed2738b8a9508c35626eb205d51af4ab7bf56a21a2e49926/coverage-7.13.4-cp314-cp314-win32.whl", hash = "sha256:8e798c266c378da2bd819b0677df41ab46d78065fb2a399558f3f6cae78b2fbb", size = 222258, upload-time = "2026-02-09T12:58:29.441Z" }, + { url = "https://files.pythonhosted.org/packages/a7/4d/1f8e723f6829977410efeb88f73673d794075091c8c7c18848d273dc9d73/coverage-7.13.4-cp314-cp314-win_amd64.whl", hash = "sha256:245e37f664d89861cf2329c9afa2c1fe9e6d4e1a09d872c947e70718aeeac505", size = 223073, upload-time = "2026-02-09T12:58:31.026Z" }, + { url = "https://files.pythonhosted.org/packages/51/5b/84100025be913b44e082ea32abcf1afbf4e872f5120b7a1cab1d331b1e13/coverage-7.13.4-cp314-cp314-win_arm64.whl", hash = "sha256:ad27098a189e5838900ce4c2a99f2fe42a0bf0c2093c17c69b45a71579e8d4a2", size = 221638, upload-time = "2026-02-09T12:58:32.599Z" }, + { url = "https://files.pythonhosted.org/packages/a7/e4/c884a405d6ead1370433dad1e3720216b4f9fd8ef5b64bfd984a2a60a11a/coverage-7.13.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:85480adfb35ffc32d40918aad81b89c69c9cc5661a9b8a81476d3e645321a056", size = 220246, upload-time = "2026-02-09T12:58:34.181Z" }, + { url = "https://files.pythonhosted.org/packages/81/5c/4d7ed8b23b233b0fffbc9dfec53c232be2e695468523242ea9fd30f97ad2/coverage-7.13.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:79be69cf7f3bf9b0deeeb062eab7ac7f36cd4cc4c4dd694bd28921ba4d8596cc", size = 220514, upload-time = "2026-02-09T12:58:35.704Z" }, + { url = "https://files.pythonhosted.org/packages/2f/6f/3284d4203fd2f28edd73034968398cd2d4cb04ab192abc8cff007ea35679/coverage-7.13.4-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:caa421e2684e382c5d8973ac55e4f36bed6821a9bad5c953494de960c74595c9", size = 261877, upload-time = "2026-02-09T12:58:37.864Z" }, + { url = "https://files.pythonhosted.org/packages/09/aa/b672a647bbe1556a85337dc95bfd40d146e9965ead9cc2fe81bde1e5cbce/coverage-7.13.4-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:14375934243ee05f56c45393fe2ce81fe5cc503c07cee2bdf1725fb8bef3ffaf", size = 264004, upload-time = "2026-02-09T12:58:39.492Z" }, + { url = "https://files.pythonhosted.org/packages/79/a1/aa384dbe9181f98bba87dd23dda436f0c6cf2e148aecbb4e50fc51c1a656/coverage-7.13.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25a41c3104d08edb094d9db0d905ca54d0cd41c928bb6be3c4c799a54753af55", size = 266408, upload-time = "2026-02-09T12:58:41.852Z" }, + { url = "https://files.pythonhosted.org/packages/53/5e/5150bf17b4019bc600799f376bb9606941e55bd5a775dc1e096b6ffea952/coverage-7.13.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f01afcff62bf9a08fb32b2c1d6e924236c0383c02c790732b6537269e466a72", size = 267544, upload-time = "2026-02-09T12:58:44.093Z" }, + { url = "https://files.pythonhosted.org/packages/e0/ed/f1de5c675987a4a7a672250d2c5c9d73d289dbf13410f00ed7181d8017dd/coverage-7.13.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eb9078108fbf0bcdde37c3f4779303673c2fa1fe8f7956e68d447d0dd426d38a", size = 260980, upload-time = "2026-02-09T12:58:45.721Z" }, + { url = "https://files.pythonhosted.org/packages/b3/e3/fe758d01850aa172419a6743fe76ba8b92c29d181d4f676ffe2dae2ba631/coverage-7.13.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e086334e8537ddd17e5f16a344777c1ab8194986ec533711cbe6c41cde841b6", size = 263871, upload-time = "2026-02-09T12:58:47.334Z" }, + { url = "https://files.pythonhosted.org/packages/b6/76/b829869d464115e22499541def9796b25312b8cf235d3bb00b39f1675395/coverage-7.13.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:725d985c5ab621268b2edb8e50dfe57633dc69bda071abc470fed55a14935fd3", size = 261472, upload-time = "2026-02-09T12:58:48.995Z" }, + { url = "https://files.pythonhosted.org/packages/14/9e/caedb1679e73e2f6ad240173f55218488bfe043e38da577c4ec977489915/coverage-7.13.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:3c06f0f1337c667b971ca2f975523347e63ec5e500b9aa5882d91931cd3ef750", size = 265210, upload-time = "2026-02-09T12:58:51.178Z" }, + { url = "https://files.pythonhosted.org/packages/3a/10/0dd02cb009b16ede425b49ec344aba13a6ae1dc39600840ea6abcb085ac4/coverage-7.13.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:590c0ed4bf8e85f745e6b805b2e1c457b2e33d5255dd9729743165253bc9ad39", size = 260319, upload-time = "2026-02-09T12:58:53.081Z" }, + { url = "https://files.pythonhosted.org/packages/92/8e/234d2c927af27c6d7a5ffad5bd2cf31634c46a477b4c7adfbfa66baf7ebb/coverage-7.13.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:eb30bf180de3f632cd043322dad5751390e5385108b2807368997d1a92a509d0", size = 262638, upload-time = "2026-02-09T12:58:55.258Z" }, + { url = "https://files.pythonhosted.org/packages/2f/64/e5547c8ff6964e5965c35a480855911b61509cce544f4d442caa759a0702/coverage-7.13.4-cp314-cp314t-win32.whl", hash = "sha256:c4240e7eded42d131a2d2c4dec70374b781b043ddc79a9de4d55ca71f8e98aea", size = 223040, upload-time = "2026-02-09T12:58:56.936Z" }, + { url = "https://files.pythonhosted.org/packages/c7/96/38086d58a181aac86d503dfa9c47eb20715a79c3e3acbdf786e92e5c09a8/coverage-7.13.4-cp314-cp314t-win_amd64.whl", hash = "sha256:4c7d3cc01e7350f2f0f6f7036caaf5673fb56b6998889ccfe9e1c1fe75a9c932", size = 224148, upload-time = "2026-02-09T12:58:58.645Z" }, + { url = "https://files.pythonhosted.org/packages/ce/72/8d10abd3740a0beb98c305e0c3faf454366221c0f37a8bcf8f60020bb65a/coverage-7.13.4-cp314-cp314t-win_arm64.whl", hash = "sha256:23e3f687cf945070d1c90f85db66d11e3025665d8dafa831301a0e0038f3db9b", size = 222172, upload-time = "2026-02-09T12:59:00.396Z" }, + { url = "https://files.pythonhosted.org/packages/0d/4a/331fe2caf6799d591109bb9c08083080f6de90a823695d412a935622abb2/coverage-7.13.4-py3-none-any.whl", hash = "sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0", size = 211242, upload-time = "2026-02-09T12:59:02.032Z" }, +] + +[package.optional-dependencies] +toml = [ + { name = "tomli", marker = "python_full_version <= '3.11'" }, +] + +[[package]] +name = "cryptography" +version = "46.0.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/04/ee2a9e8542e4fa2773b81771ff8349ff19cdd56b7258a0cc442639052edb/cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d", size = 750064, upload-time = "2026-02-10T19:18:38.255Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/81/b0bb27f2ba931a65409c6b8a8b358a7f03c0e46eceacddff55f7c84b1f3b/cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad", size = 7176289, upload-time = "2026-02-10T19:17:08.274Z" }, + { url = "https://files.pythonhosted.org/packages/ff/9e/6b4397a3e3d15123de3b1806ef342522393d50736c13b20ec4c9ea6693a6/cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b", size = 4275637, upload-time = "2026-02-10T19:17:10.53Z" }, + { url = "https://files.pythonhosted.org/packages/63/e7/471ab61099a3920b0c77852ea3f0ea611c9702f651600397ac567848b897/cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b", size = 4424742, upload-time = "2026-02-10T19:17:12.388Z" }, + { url = "https://files.pythonhosted.org/packages/37/53/a18500f270342d66bf7e4d9f091114e31e5ee9e7375a5aba2e85a91e0044/cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263", size = 4277528, upload-time = "2026-02-10T19:17:13.853Z" }, + { url = "https://files.pythonhosted.org/packages/22/29/c2e812ebc38c57b40e7c583895e73c8c5adb4d1e4a0cc4c5a4fdab2b1acc/cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d", size = 4947993, upload-time = "2026-02-10T19:17:15.618Z" }, + { url = "https://files.pythonhosted.org/packages/6b/e7/237155ae19a9023de7e30ec64e5d99a9431a567407ac21170a046d22a5a3/cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed", size = 4456855, upload-time = "2026-02-10T19:17:17.221Z" }, + { url = "https://files.pythonhosted.org/packages/2d/87/fc628a7ad85b81206738abbd213b07702bcbdada1dd43f72236ef3cffbb5/cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2", size = 3984635, upload-time = "2026-02-10T19:17:18.792Z" }, + { url = "https://files.pythonhosted.org/packages/84/29/65b55622bde135aedf4565dc509d99b560ee4095e56989e815f8fd2aa910/cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2", size = 4277038, upload-time = "2026-02-10T19:17:20.256Z" }, + { url = "https://files.pythonhosted.org/packages/bc/36/45e76c68d7311432741faf1fbf7fac8a196a0a735ca21f504c75d37e2558/cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0", size = 4912181, upload-time = "2026-02-10T19:17:21.825Z" }, + { url = "https://files.pythonhosted.org/packages/6d/1a/c1ba8fead184d6e3d5afcf03d569acac5ad063f3ac9fb7258af158f7e378/cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731", size = 4456482, upload-time = "2026-02-10T19:17:25.133Z" }, + { url = "https://files.pythonhosted.org/packages/f9/e5/3fb22e37f66827ced3b902cf895e6a6bc1d095b5b26be26bd13c441fdf19/cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82", size = 4405497, upload-time = "2026-02-10T19:17:26.66Z" }, + { url = "https://files.pythonhosted.org/packages/1a/df/9d58bb32b1121a8a2f27383fabae4d63080c7ca60b9b5c88be742be04ee7/cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1", size = 4667819, upload-time = "2026-02-10T19:17:28.569Z" }, + { url = "https://files.pythonhosted.org/packages/ea/ed/325d2a490c5e94038cdb0117da9397ece1f11201f425c4e9c57fe5b9f08b/cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48", size = 3028230, upload-time = "2026-02-10T19:17:30.518Z" }, + { url = "https://files.pythonhosted.org/packages/e9/5a/ac0f49e48063ab4255d9e3b79f5def51697fce1a95ea1370f03dc9db76f6/cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4", size = 3480909, upload-time = "2026-02-10T19:17:32.083Z" }, + { url = "https://files.pythonhosted.org/packages/00/13/3d278bfa7a15a96b9dc22db5a12ad1e48a9eb3d40e1827ef66a5df75d0d0/cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2", size = 7119287, upload-time = "2026-02-10T19:17:33.801Z" }, + { url = "https://files.pythonhosted.org/packages/67/c8/581a6702e14f0898a0848105cbefd20c058099e2c2d22ef4e476dfec75d7/cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678", size = 4265728, upload-time = "2026-02-10T19:17:35.569Z" }, + { url = "https://files.pythonhosted.org/packages/dd/4a/ba1a65ce8fc65435e5a849558379896c957870dd64fecea97b1ad5f46a37/cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87", size = 4408287, upload-time = "2026-02-10T19:17:36.938Z" }, + { url = "https://files.pythonhosted.org/packages/f8/67/8ffdbf7b65ed1ac224d1c2df3943553766914a8ca718747ee3871da6107e/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee", size = 4270291, upload-time = "2026-02-10T19:17:38.748Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/f52377ee93bc2f2bba55a41a886fd208c15276ffbd2569f2ddc89d50e2c5/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981", size = 4927539, upload-time = "2026-02-10T19:17:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/3b/02/cfe39181b02419bbbbcf3abdd16c1c5c8541f03ca8bda240debc467d5a12/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9", size = 4442199, upload-time = "2026-02-10T19:17:41.789Z" }, + { url = "https://files.pythonhosted.org/packages/c0/96/2fcaeb4873e536cf71421a388a6c11b5bc846e986b2b069c79363dc1648e/cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648", size = 3960131, upload-time = "2026-02-10T19:17:43.379Z" }, + { url = "https://files.pythonhosted.org/packages/d8/d2/b27631f401ddd644e94c5cf33c9a4069f72011821cf3dc7309546b0642a0/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4", size = 4270072, upload-time = "2026-02-10T19:17:45.481Z" }, + { url = "https://files.pythonhosted.org/packages/f4/a7/60d32b0370dae0b4ebe55ffa10e8599a2a59935b5ece1b9f06edb73abdeb/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0", size = 4892170, upload-time = "2026-02-10T19:17:46.997Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b9/cf73ddf8ef1164330eb0b199a589103c363afa0cf794218c24d524a58eab/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663", size = 4441741, upload-time = "2026-02-10T19:17:48.661Z" }, + { url = "https://files.pythonhosted.org/packages/5f/eb/eee00b28c84c726fe8fa0158c65afe312d9c3b78d9d01daf700f1f6e37ff/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826", size = 4396728, upload-time = "2026-02-10T19:17:50.058Z" }, + { url = "https://files.pythonhosted.org/packages/65/f4/6bc1a9ed5aef7145045114b75b77c2a8261b4d38717bd8dea111a63c3442/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d", size = 4652001, upload-time = "2026-02-10T19:17:51.54Z" }, + { url = "https://files.pythonhosted.org/packages/86/ef/5d00ef966ddd71ac2e6951d278884a84a40ffbd88948ef0e294b214ae9e4/cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a", size = 3003637, upload-time = "2026-02-10T19:17:52.997Z" }, + { url = "https://files.pythonhosted.org/packages/b7/57/f3f4160123da6d098db78350fdfd9705057aad21de7388eacb2401dceab9/cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4", size = 3469487, upload-time = "2026-02-10T19:17:54.549Z" }, + { url = "https://files.pythonhosted.org/packages/e2/fa/a66aa722105ad6a458bebd64086ca2b72cdd361fed31763d20390f6f1389/cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31", size = 7170514, upload-time = "2026-02-10T19:17:56.267Z" }, + { url = "https://files.pythonhosted.org/packages/0f/04/c85bdeab78c8bc77b701bf0d9bdcf514c044e18a46dcff330df5448631b0/cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18", size = 4275349, upload-time = "2026-02-10T19:17:58.419Z" }, + { url = "https://files.pythonhosted.org/packages/5c/32/9b87132a2f91ee7f5223b091dc963055503e9b442c98fc0b8a5ca765fab0/cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235", size = 4420667, upload-time = "2026-02-10T19:18:00.619Z" }, + { url = "https://files.pythonhosted.org/packages/a1/a6/a7cb7010bec4b7c5692ca6f024150371b295ee1c108bdc1c400e4c44562b/cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a", size = 4276980, upload-time = "2026-02-10T19:18:02.379Z" }, + { url = "https://files.pythonhosted.org/packages/8e/7c/c4f45e0eeff9b91e3f12dbd0e165fcf2a38847288fcfd889deea99fb7b6d/cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76", size = 4939143, upload-time = "2026-02-10T19:18:03.964Z" }, + { url = "https://files.pythonhosted.org/packages/37/19/e1b8f964a834eddb44fa1b9a9976f4e414cbb7aa62809b6760c8803d22d1/cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614", size = 4453674, upload-time = "2026-02-10T19:18:05.588Z" }, + { url = "https://files.pythonhosted.org/packages/db/ed/db15d3956f65264ca204625597c410d420e26530c4e2943e05a0d2f24d51/cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229", size = 3978801, upload-time = "2026-02-10T19:18:07.167Z" }, + { url = "https://files.pythonhosted.org/packages/41/e2/df40a31d82df0a70a0daf69791f91dbb70e47644c58581d654879b382d11/cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1", size = 4276755, upload-time = "2026-02-10T19:18:09.813Z" }, + { url = "https://files.pythonhosted.org/packages/33/45/726809d1176959f4a896b86907b98ff4391a8aa29c0aaaf9450a8a10630e/cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d", size = 4901539, upload-time = "2026-02-10T19:18:11.263Z" }, + { url = "https://files.pythonhosted.org/packages/99/0f/a3076874e9c88ecb2ecc31382f6e7c21b428ede6f55aafa1aa272613e3cd/cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c", size = 4452794, upload-time = "2026-02-10T19:18:12.914Z" }, + { url = "https://files.pythonhosted.org/packages/02/ef/ffeb542d3683d24194a38f66ca17c0a4b8bf10631feef44a7ef64e631b1a/cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4", size = 4404160, upload-time = "2026-02-10T19:18:14.375Z" }, + { url = "https://files.pythonhosted.org/packages/96/93/682d2b43c1d5f1406ed048f377c0fc9fc8f7b0447a478d5c65ab3d3a66eb/cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9", size = 4667123, upload-time = "2026-02-10T19:18:15.886Z" }, + { url = "https://files.pythonhosted.org/packages/45/2d/9c5f2926cb5300a8eefc3f4f0b3f3df39db7f7ce40c8365444c49363cbda/cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72", size = 3010220, upload-time = "2026-02-10T19:18:17.361Z" }, + { url = "https://files.pythonhosted.org/packages/48/ef/0c2f4a8e31018a986949d34a01115dd057bf536905dca38897bacd21fac3/cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595", size = 3467050, upload-time = "2026-02-10T19:18:18.899Z" }, + { url = "https://files.pythonhosted.org/packages/eb/dd/2d9fdb07cebdf3d51179730afb7d5e576153c6744c3ff8fded23030c204e/cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c", size = 3476964, upload-time = "2026-02-10T19:18:20.687Z" }, + { url = "https://files.pythonhosted.org/packages/e9/6f/6cc6cc9955caa6eaf83660b0da2b077c7fe8ff9950a3c5e45d605038d439/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a", size = 4218321, upload-time = "2026-02-10T19:18:22.349Z" }, + { url = "https://files.pythonhosted.org/packages/3e/5d/c4da701939eeee699566a6c1367427ab91a8b7088cc2328c09dbee940415/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356", size = 4381786, upload-time = "2026-02-10T19:18:24.529Z" }, + { url = "https://files.pythonhosted.org/packages/ac/97/a538654732974a94ff96c1db621fa464f455c02d4bb7d2652f4edc21d600/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da", size = 4217990, upload-time = "2026-02-10T19:18:25.957Z" }, + { url = "https://files.pythonhosted.org/packages/ae/11/7e500d2dd3ba891197b9efd2da5454b74336d64a7cc419aa7327ab74e5f6/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257", size = 4381252, upload-time = "2026-02-10T19:18:27.496Z" }, + { url = "https://files.pythonhosted.org/packages/bc/58/6b3d24e6b9bc474a2dcdee65dfd1f008867015408a271562e4b690561a4d/cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7", size = 3407605, upload-time = "2026-02-10T19:18:29.233Z" }, +] + +[[package]] +name = "cyclonedx-python-lib" +version = "11.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "license-expression" }, + { name = "packageurl-python" }, + { name = "py-serializable" }, + { name = "sortedcontainers" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/89/ed/54ecfa25fc145c58bf4f98090f7b6ffe5188d0759248c57dde44427ea239/cyclonedx_python_lib-11.6.0.tar.gz", hash = "sha256:7fb85a4371fa3a203e5be577ac22b7e9a7157f8b0058b7448731474d6dea7bf0", size = 1408147, upload-time = "2025-12-02T12:28:46.446Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/1b/534ad8a5e0f9470522811a8e5a9bc5d328fb7738ba29faf357467a4ef6d0/cyclonedx_python_lib-11.6.0-py3-none-any.whl", hash = "sha256:94f4aae97db42a452134dafdddcfab9745324198201c4777ed131e64c8380759", size = 511157, upload-time = "2025-12-02T12:28:44.158Z" }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + +[[package]] +name = "distlib" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, +] + +[[package]] +name = "docutils" +version = "0.19" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/330ea8d383eb2ce973df34d1239b3b21e91cd8c865d21ff82902d952f91f/docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6", size = 2056383, upload-time = "2022-07-05T20:17:31.045Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/69/e391bd51bc08ed9141ecd899a0ddb61ab6465309f1eb470905c0c8868081/docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc", size = 570472, upload-time = "2022-07-05T20:17:26.388Z" }, +] + +[[package]] +name = "dotty-dict" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6a/ab/88d67f02024700b48cd8232579ad1316aa9df2272c63049c27cc094229d6/dotty_dict-1.3.1.tar.gz", hash = "sha256:4b016e03b8ae265539757a53eba24b9bfda506fb94fbce0bee843c6f05541a15", size = 7699, upload-time = "2022-07-09T18:50:57.727Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/91/e0d457ee03ec33d79ee2cd8d212debb1bc21dfb99728ae35efdb5832dc22/dotty_dict-1.3.1-py3-none-any.whl", hash = "sha256:5022d234d9922f13aa711b4950372a06a6d64cb6d6db9ba43d0ba133ebfce31f", size = 7014, upload-time = "2022-07-09T18:50:55.058Z" }, +] + +[[package]] +name = "dunamai" +version = "1.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/c4/346cef905782df6152f29f02d9c8ed4acf7ae66b0e66210b7156c5575ccb/dunamai-1.26.0.tar.gz", hash = "sha256:5396ac43aa20ed059040034e9f9798c7464cf4334c6fc3da3732e29273a2f97d", size = 45500, upload-time = "2026-02-15T02:58:55.534Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/10/2c7edbf230e5c507d38367af498fa94258ed97205d9b4b6f63a921fe9c49/dunamai-1.26.0-py3-none-any.whl", hash = "sha256:f584edf0fda0d308cce0961f807bc90a8fe3d9ff4d62f94e72eca7b43f0ed5f6", size = 27322, upload-time = "2026-02-15T02:58:54.143Z" }, +] + +[[package]] +name = "empty-files" +version = "0.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/19/ac55ab18403da2885b3fd5baa7974b12d8a3c59ee56ea185a9a80632839b/empty-files-0.0.9.tar.gz", hash = "sha256:22e74de327271ef9592a661aaa53bb1d5fa6cfd539dac7315625c8b30b7292ae", size = 6812, upload-time = "2023-07-30T19:40:44.035Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/4c/d5b6973c9f10992a2aee9c4cb542b25ebdabe907243d6c9650c89dbf578b/empty_files-0.0.9-py3-none-any.whl", hash = "sha256:9af04feacd5858d1255a00e76926a2d760f6d05c3c5a8df58abd6be21da742c2", size = 7165, upload-time = "2023-07-30T19:40:42.657Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, +] + +[[package]] +name = "execnet" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, +] + +[[package]] +name = "filelock" +version = "3.25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/77/18/a1fd2231c679dcb9726204645721b12498aeac28e1ad0601038f94b42556/filelock-3.25.0.tar.gz", hash = "sha256:8f00faf3abf9dc730a1ffe9c354ae5c04e079ab7d3a683b7c32da5dd05f26af3", size = 40158, upload-time = "2026-03-01T15:08:45.916Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/0b/de6f54d4a8bedfe8645c41497f3c18d749f0bd3218170c667bf4b81d0cdd/filelock-3.25.0-py3-none-any.whl", hash = "sha256:5ccf8069f7948f494968fc0713c10e5c182a9c9d9eef3a636307a20c2490f047", size = 26427, upload-time = "2026-03-01T15:08:44.593Z" }, +] + +[[package]] +name = "funcy" +version = "2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/b8/c6081521ff70afdff55cd9512b2220bbf4fa88804dae51d1b57b4b58ef32/funcy-2.0.tar.gz", hash = "sha256:3963315d59d41c6f30c04bc910e10ab50a3ac4a225868bfa96feed133df075cb", size = 537931, upload-time = "2023-03-28T06:22:46.764Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl", hash = "sha256:53df23c8bb1651b12f095df764bfb057935d49537a56de211b098f4c79614bb0", size = 30891, upload-time = "2023-03-28T06:22:42.576Z" }, +] + +[[package]] +name = "gfm-toc" +version = "0.0.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/11/ebcf4b0f261f886d06ba81c6055fad17eb64ba259f2d20e259b67913b7f1/gfm-toc-0.0.7.tar.gz", hash = "sha256:c53ed0e2cd400e89051377017ca98c11c9cef628b2effddf787db4fc19ff343d", size = 6018, upload-time = "2019-04-07T07:56:58.35Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/93/5af84cd3a2f818d5a68d154796b0e6a25cd490b82ee26071d6d43d883dc8/gfm_toc-0.0.7-py3-none-any.whl", hash = "sha256:247af7267a6cbbdd4213f8383157997bcb07e39e819db737bd2dbfbdb94ee7ae", size = 6781, upload-time = "2019-04-07T07:56:56.814Z" }, +] + +[[package]] +name = "gitdb" +version = "4.0.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "smmap" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/94/63b0fc47eb32792c7ba1fe1b694daec9a63620db1e313033d18140c2320a/gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571", size = 394684, upload-time = "2025-01-02T07:20:46.413Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf", size = 62794, upload-time = "2025-01-02T07:20:43.624Z" }, +] + +[[package]] +name = "gitpython" +version = "3.1.46" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "gitdb" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/b5/59d16470a1f0dfe8c793f9ef56fd3826093fc52b3bd96d6b9d6c26c7e27b/gitpython-3.1.46.tar.gz", hash = "sha256:400124c7d0ef4ea03f7310ac2fbf7151e09ff97f2a3288d64a440c584a29c37f", size = 215371, upload-time = "2026-01-01T15:37:32.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl", hash = "sha256:79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058", size = 208620, upload-time = "2026-01-01T15:37:30.574Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "html2text" +version = "2025.4.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/27/e158d86ba1e82967cc2f790b0cb02030d4a8bef58e0c79a8590e9678107f/html2text-2025.4.15.tar.gz", hash = "sha256:948a645f8f0bc3abe7fd587019a2197a12436cd73d0d4908af95bfc8da337588", size = 64316, upload-time = "2025-04-15T04:02:30.045Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/84/1a0f9555fd5f2b1c924ff932d99b40a0f8a6b12f6dd625e2a47f415b00ea/html2text-2025.4.15-py3-none-any.whl", hash = "sha256:00569167ffdab3d7767a4cdf589b7f57e777a5ed28d12907d8c58769ec734acc", size = 34656, upload-time = "2025-04-15T04:02:28.44Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "identify" +version = "2.6.17" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/84/376a3b96e5a8d33a7aa2c5b3b31a4b3c364117184bf0b17418055f6ace66/identify-2.6.17.tar.gz", hash = "sha256:f816b0b596b204c9fdf076ded172322f2723cf958d02f9c3587504834c8ff04d", size = 99579, upload-time = "2026-03-01T20:04:12.702Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl", hash = "sha256:be5f8412d5ed4b20f2bd41a65f920990bdccaa6a4a18a08f1eefdcd0bdd885f0", size = 99382, upload-time = "2026-03-01T20:04:11.439Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "imagesize" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/e6/7bf14eeb8f8b7251141944835abd42eb20a658d89084b7e1f3e5fe394090/imagesize-2.0.0.tar.gz", hash = "sha256:8e8358c4a05c304f1fccf7ff96f036e7243a189e9e42e90851993c558cfe9ee3", size = 1773045, upload-time = "2026-03-03T14:18:29.941Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/53/fb7122b71361a0d121b669dcf3d31244ef75badbbb724af388948de543e2/imagesize-2.0.0-py2.py3-none-any.whl", hash = "sha256:5667c5bbb57ab3f1fa4bc366f4fbc971db3d5ed011fd2715fd8001f782718d96", size = 9441, upload-time = "2026-03-03T14:18:27.892Z" }, +] + +[[package]] +name = "importlib-metadata" +version = "8.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "invoke" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/de/bd/b461d3424a24c80490313fd77feeb666ca4f6a28c7e72713e3d9095719b4/invoke-2.2.1.tar.gz", hash = "sha256:515bf49b4a48932b79b024590348da22f39c4942dff991ad1fb8b8baea1be707", size = 304762, upload-time = "2025-10-11T00:36:35.172Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/4b/b99e37f88336009971405cbb7630610322ed6fbfa31e1d7ab3fbf3049a2d/invoke-2.2.1-py3-none-any.whl", hash = "sha256:2413bc441b376e5cd3f55bb5d364f973ad8bdd7bf87e53c79de3c11bf3feecc8", size = 160287, upload-time = "2025-10-11T00:36:33.703Z" }, +] + +[[package]] +name = "jaraco-classes" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" }, +] + +[[package]] +name = "jaraco-context" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "backports-tarfile", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/9c/a788f5bb29c61e456b8ee52ce76dbdd32fd72cd73dd67bc95f42c7a8d13c/jaraco_context-6.1.0.tar.gz", hash = "sha256:129a341b0a85a7db7879e22acd66902fda67882db771754574338898b2d5d86f", size = 15850, upload-time = "2026-01-13T02:53:53.847Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/48/aa685dbf1024c7bd82bede569e3a85f82c32fd3d79ba5fea578f0159571a/jaraco_context-6.1.0-py3-none-any.whl", hash = "sha256:a43b5ed85815223d0d3cfdb6d7ca0d2bc8946f28f30b6f3216bda070f68badda", size = 7065, upload-time = "2026-01-13T02:53:53.031Z" }, +] + +[[package]] +name = "jaraco-functools" +version = "4.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0f/27/056e0638a86749374d6f57d0b0db39f29509cce9313cf91bdc0ac4d91084/jaraco_functools-4.4.0.tar.gz", hash = "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb", size = 19943, upload-time = "2025-12-21T09:29:43.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl", hash = "sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176", size = 10481, upload-time = "2025-12-21T09:29:42.27Z" }, +] + +[[package]] +name = "jeepney" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "jinja2-ansible-filters" +version = "1.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jinja2" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1a/27/fa186af4b246eb869ffca8ffa42d92b05abaec08c99329e74d88b2c46ec7/jinja2-ansible-filters-1.3.2.tar.gz", hash = "sha256:07c10cf44d7073f4f01102ca12d9a2dc31b41d47e4c61ed92ef6a6d2669b356b", size = 16945, upload-time = "2022-06-30T14:08:50.775Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl", hash = "sha256:e1082f5564917649c76fed239117820610516ec10f87735d0338688800a55b34", size = 18975, upload-time = "2022-06-30T14:08:49.571Z" }, +] + +[[package]] +name = "jsondiff" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/35/48/841137f1843fa215ea284834d1514b8e9e20962bda63a636c7417e02f8fb/jsondiff-2.2.1.tar.gz", hash = "sha256:658d162c8a86ba86de26303cd86a7b37e1b2c1ec98b569a60e2ca6180545f7fe", size = 26649, upload-time = "2024-08-29T04:09:06.201Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/94/a8066f84d62ab666d61ef97deba1a33126e3e5c0c0da2c458ada17053ed6/jsondiff-2.2.1-py3-none-any.whl", hash = "sha256:b1f0f7e2421881848b1d556d541ac01a91680cfcc14f51a9b62cdf4da0e56722", size = 13440, upload-time = "2024-08-29T04:09:04.955Z" }, +] + +[[package]] +name = "keyring" +version = "25.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata", marker = "python_full_version < '3.12'" }, + { name = "jaraco-classes" }, + { name = "jaraco-context" }, + { name = "jaraco-functools" }, + { name = "jeepney", marker = "sys_platform == 'linux'" }, + { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, + { name = "secretstorage", marker = "sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/70/09/d904a6e96f76ff214be59e7aa6ef7190008f52a0ab6689760a98de0bf37d/keyring-25.6.0.tar.gz", hash = "sha256:0b39998aa941431eb3d9b0d4b2460bc773b9df6fed7621c2dfb291a7e0187a66", size = 62750, upload-time = "2024-12-25T15:26:45.782Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/32/da7f44bcb1105d3e88a0b74ebdca50c59121d2ddf71c9e34ba47df7f3a56/keyring-25.6.0-py3-none-any.whl", hash = "sha256:552a3f7af126ece7ed5c89753650eec89c7eaae8617d0aa4d9ad2b75111266bd", size = 39085, upload-time = "2024-12-25T15:26:44.377Z" }, +] + +[[package]] +name = "librt" +version = "0.8.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/56/9c/b4b0c54d84da4a94b37bd44151e46d5e583c9534c7e02250b961b1b6d8a8/librt-0.8.1.tar.gz", hash = "sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73", size = 177471, upload-time = "2026-02-17T16:13:06.101Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/5f/63f5fa395c7a8a93558c0904ba8f1c8d1b997ca6a3de61bc7659970d66bf/librt-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc", size = 65697, upload-time = "2026-02-17T16:11:06.903Z" }, + { url = "https://files.pythonhosted.org/packages/ff/e0/0472cf37267b5920eff2f292ccfaede1886288ce35b7f3203d8de00abfe6/librt-0.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7", size = 68376, upload-time = "2026-02-17T16:11:08.395Z" }, + { url = "https://files.pythonhosted.org/packages/c8/be/8bd1359fdcd27ab897cd5963294fa4a7c83b20a8564678e4fd12157e56a5/librt-0.8.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6", size = 197084, upload-time = "2026-02-17T16:11:09.774Z" }, + { url = "https://files.pythonhosted.org/packages/e2/fe/163e33fdd091d0c2b102f8a60cc0a61fd730ad44e32617cd161e7cd67a01/librt-0.8.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0", size = 207337, upload-time = "2026-02-17T16:11:11.311Z" }, + { url = "https://files.pythonhosted.org/packages/01/99/f85130582f05dcf0c8902f3d629270231d2f4afdfc567f8305a952ac7f14/librt-0.8.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b", size = 219980, upload-time = "2026-02-17T16:11:12.499Z" }, + { url = "https://files.pythonhosted.org/packages/6f/54/cb5e4d03659e043a26c74e08206412ac9a3742f0477d96f9761a55313b5f/librt-0.8.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6", size = 212921, upload-time = "2026-02-17T16:11:14.484Z" }, + { url = "https://files.pythonhosted.org/packages/b1/81/a3a01e4240579c30f3487f6fed01eb4bc8ef0616da5b4ebac27ca19775f3/librt-0.8.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71", size = 221381, upload-time = "2026-02-17T16:11:17.459Z" }, + { url = "https://files.pythonhosted.org/packages/08/b0/fc2d54b4b1c6fb81e77288ff31ff25a2c1e62eaef4424a984f228839717b/librt-0.8.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7", size = 216714, upload-time = "2026-02-17T16:11:19.197Z" }, + { url = "https://files.pythonhosted.org/packages/96/96/85daa73ffbd87e1fb287d7af6553ada66bf25a2a6b0de4764344a05469f6/librt-0.8.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05", size = 214777, upload-time = "2026-02-17T16:11:20.443Z" }, + { url = "https://files.pythonhosted.org/packages/12/9c/c3aa7a2360383f4bf4f04d98195f2739a579128720c603f4807f006a4225/librt-0.8.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891", size = 237398, upload-time = "2026-02-17T16:11:22.083Z" }, + { url = "https://files.pythonhosted.org/packages/61/19/d350ea89e5274665185dabc4bbb9c3536c3411f862881d316c8b8e00eb66/librt-0.8.1-cp310-cp310-win32.whl", hash = "sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7", size = 54285, upload-time = "2026-02-17T16:11:23.27Z" }, + { url = "https://files.pythonhosted.org/packages/4f/d6/45d587d3d41c112e9543a0093d883eb57a24a03e41561c127818aa2a6bcc/librt-0.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2", size = 61352, upload-time = "2026-02-17T16:11:24.207Z" }, + { url = "https://files.pythonhosted.org/packages/1d/01/0e748af5e4fee180cf7cd12bd12b0513ad23b045dccb2a83191bde82d168/librt-0.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd", size = 65315, upload-time = "2026-02-17T16:11:25.152Z" }, + { url = "https://files.pythonhosted.org/packages/9d/4d/7184806efda571887c798d573ca4134c80ac8642dcdd32f12c31b939c595/librt-0.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965", size = 68021, upload-time = "2026-02-17T16:11:26.129Z" }, + { url = "https://files.pythonhosted.org/packages/ae/88/c3c52d2a5d5101f28d3dc89298444626e7874aa904eed498464c2af17627/librt-0.8.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da", size = 194500, upload-time = "2026-02-17T16:11:27.177Z" }, + { url = "https://files.pythonhosted.org/packages/d6/5d/6fb0a25b6a8906e85b2c3b87bee1d6ed31510be7605b06772f9374ca5cb3/librt-0.8.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0", size = 205622, upload-time = "2026-02-17T16:11:28.242Z" }, + { url = "https://files.pythonhosted.org/packages/b2/a6/8006ae81227105476a45691f5831499e4d936b1c049b0c1feb17c11b02d1/librt-0.8.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e", size = 218304, upload-time = "2026-02-17T16:11:29.344Z" }, + { url = "https://files.pythonhosted.org/packages/ee/19/60e07886ad16670aae57ef44dada41912c90906a6fe9f2b9abac21374748/librt-0.8.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3", size = 211493, upload-time = "2026-02-17T16:11:30.445Z" }, + { url = "https://files.pythonhosted.org/packages/9c/cf/f666c89d0e861d05600438213feeb818c7514d3315bae3648b1fc145d2b6/librt-0.8.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac", size = 219129, upload-time = "2026-02-17T16:11:32.021Z" }, + { url = "https://files.pythonhosted.org/packages/8f/ef/f1bea01e40b4a879364c031476c82a0dc69ce068daad67ab96302fed2d45/librt-0.8.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596", size = 213113, upload-time = "2026-02-17T16:11:33.192Z" }, + { url = "https://files.pythonhosted.org/packages/9b/80/cdab544370cc6bc1b72ea369525f547a59e6938ef6863a11ab3cd24759af/librt-0.8.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99", size = 212269, upload-time = "2026-02-17T16:11:34.373Z" }, + { url = "https://files.pythonhosted.org/packages/9d/9c/48d6ed8dac595654f15eceab2035131c136d1ae9a1e3548e777bb6dbb95d/librt-0.8.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe", size = 234673, upload-time = "2026-02-17T16:11:36.063Z" }, + { url = "https://files.pythonhosted.org/packages/16/01/35b68b1db517f27a01be4467593292eb5315def8900afad29fabf56304ba/librt-0.8.1-cp311-cp311-win32.whl", hash = "sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb", size = 54597, upload-time = "2026-02-17T16:11:37.544Z" }, + { url = "https://files.pythonhosted.org/packages/71/02/796fe8f02822235966693f257bf2c79f40e11337337a657a8cfebba5febc/librt-0.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b", size = 61733, upload-time = "2026-02-17T16:11:38.691Z" }, + { url = "https://files.pythonhosted.org/packages/28/ad/232e13d61f879a42a4e7117d65e4984bb28371a34bb6fb9ca54ec2c8f54e/librt-0.8.1-cp311-cp311-win_arm64.whl", hash = "sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9", size = 52273, upload-time = "2026-02-17T16:11:40.308Z" }, + { url = "https://files.pythonhosted.org/packages/95/21/d39b0a87ac52fc98f621fb6f8060efb017a767ebbbac2f99fbcbc9ddc0d7/librt-0.8.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a", size = 66516, upload-time = "2026-02-17T16:11:41.604Z" }, + { url = "https://files.pythonhosted.org/packages/69/f1/46375e71441c43e8ae335905e069f1c54febee63a146278bcee8782c84fd/librt-0.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9", size = 68634, upload-time = "2026-02-17T16:11:43.268Z" }, + { url = "https://files.pythonhosted.org/packages/0a/33/c510de7f93bf1fa19e13423a606d8189a02624a800710f6e6a0a0f0784b3/librt-0.8.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb", size = 198941, upload-time = "2026-02-17T16:11:44.28Z" }, + { url = "https://files.pythonhosted.org/packages/dd/36/e725903416409a533d92398e88ce665476f275081d0d7d42f9c4951999e5/librt-0.8.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d", size = 209991, upload-time = "2026-02-17T16:11:45.462Z" }, + { url = "https://files.pythonhosted.org/packages/30/7a/8d908a152e1875c9f8eac96c97a480df425e657cdb47854b9efaa4998889/librt-0.8.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7", size = 224476, upload-time = "2026-02-17T16:11:46.542Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b8/a22c34f2c485b8903a06f3fe3315341fe6876ef3599792344669db98fcff/librt-0.8.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440", size = 217518, upload-time = "2026-02-17T16:11:47.746Z" }, + { url = "https://files.pythonhosted.org/packages/79/6f/5c6fea00357e4f82ba44f81dbfb027921f1ab10e320d4a64e1c408d035d9/librt-0.8.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9", size = 225116, upload-time = "2026-02-17T16:11:49.298Z" }, + { url = "https://files.pythonhosted.org/packages/f2/a0/95ced4e7b1267fe1e2720a111685bcddf0e781f7e9e0ce59d751c44dcfe5/librt-0.8.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972", size = 217751, upload-time = "2026-02-17T16:11:50.49Z" }, + { url = "https://files.pythonhosted.org/packages/93/c2/0517281cb4d4101c27ab59472924e67f55e375bc46bedae94ac6dc6e1902/librt-0.8.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921", size = 218378, upload-time = "2026-02-17T16:11:51.783Z" }, + { url = "https://files.pythonhosted.org/packages/43/e8/37b3ac108e8976888e559a7b227d0ceac03c384cfd3e7a1c2ee248dbae79/librt-0.8.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0", size = 241199, upload-time = "2026-02-17T16:11:53.561Z" }, + { url = "https://files.pythonhosted.org/packages/4b/5b/35812d041c53967fedf551a39399271bbe4257e681236a2cf1a69c8e7fa1/librt-0.8.1-cp312-cp312-win32.whl", hash = "sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a", size = 54917, upload-time = "2026-02-17T16:11:54.758Z" }, + { url = "https://files.pythonhosted.org/packages/de/d1/fa5d5331b862b9775aaf2a100f5ef86854e5d4407f71bddf102f4421e034/librt-0.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444", size = 62017, upload-time = "2026-02-17T16:11:55.748Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7c/c614252f9acda59b01a66e2ddfd243ed1c7e1deab0293332dfbccf862808/librt-0.8.1-cp312-cp312-win_arm64.whl", hash = "sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d", size = 52441, upload-time = "2026-02-17T16:11:56.801Z" }, + { url = "https://files.pythonhosted.org/packages/c5/3c/f614c8e4eaac7cbf2bbdf9528790b21d89e277ee20d57dc6e559c626105f/librt-0.8.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35", size = 66529, upload-time = "2026-02-17T16:11:57.809Z" }, + { url = "https://files.pythonhosted.org/packages/ab/96/5836544a45100ae411eda07d29e3d99448e5258b6e9c8059deb92945f5c2/librt-0.8.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583", size = 68669, upload-time = "2026-02-17T16:11:58.843Z" }, + { url = "https://files.pythonhosted.org/packages/06/53/f0b992b57af6d5531bf4677d75c44f095f2366a1741fb695ee462ae04b05/librt-0.8.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c", size = 199279, upload-time = "2026-02-17T16:11:59.862Z" }, + { url = "https://files.pythonhosted.org/packages/f3/ad/4848cc16e268d14280d8168aee4f31cea92bbd2b79ce33d3e166f2b4e4fc/librt-0.8.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04", size = 210288, upload-time = "2026-02-17T16:12:00.954Z" }, + { url = "https://files.pythonhosted.org/packages/52/05/27fdc2e95de26273d83b96742d8d3b7345f2ea2bdbd2405cc504644f2096/librt-0.8.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363", size = 224809, upload-time = "2026-02-17T16:12:02.108Z" }, + { url = "https://files.pythonhosted.org/packages/7a/d0/78200a45ba3240cb042bc597d6f2accba9193a2c57d0356268cbbe2d0925/librt-0.8.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0", size = 218075, upload-time = "2026-02-17T16:12:03.631Z" }, + { url = "https://files.pythonhosted.org/packages/af/72/a210839fa74c90474897124c064ffca07f8d4b347b6574d309686aae7ca6/librt-0.8.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012", size = 225486, upload-time = "2026-02-17T16:12:04.725Z" }, + { url = "https://files.pythonhosted.org/packages/a3/c1/a03cc63722339ddbf087485f253493e2b013039f5b707e8e6016141130fa/librt-0.8.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb", size = 218219, upload-time = "2026-02-17T16:12:05.828Z" }, + { url = "https://files.pythonhosted.org/packages/58/f5/fff6108af0acf941c6f274a946aea0e484bd10cd2dc37610287ce49388c5/librt-0.8.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b", size = 218750, upload-time = "2026-02-17T16:12:07.09Z" }, + { url = "https://files.pythonhosted.org/packages/71/67/5a387bfef30ec1e4b4f30562c8586566faf87e47d696768c19feb49e3646/librt-0.8.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d", size = 241624, upload-time = "2026-02-17T16:12:08.43Z" }, + { url = "https://files.pythonhosted.org/packages/d4/be/24f8502db11d405232ac1162eb98069ca49c3306c1d75c6ccc61d9af8789/librt-0.8.1-cp313-cp313-win32.whl", hash = "sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a", size = 54969, upload-time = "2026-02-17T16:12:09.633Z" }, + { url = "https://files.pythonhosted.org/packages/5c/73/c9fdf6cb2a529c1a092ce769a12d88c8cca991194dfe641b6af12fa964d2/librt-0.8.1-cp313-cp313-win_amd64.whl", hash = "sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79", size = 62000, upload-time = "2026-02-17T16:12:10.632Z" }, + { url = "https://files.pythonhosted.org/packages/d3/97/68f80ca3ac4924f250cdfa6e20142a803e5e50fca96ef5148c52ee8c10ea/librt-0.8.1-cp313-cp313-win_arm64.whl", hash = "sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0", size = 52495, upload-time = "2026-02-17T16:12:11.633Z" }, + { url = "https://files.pythonhosted.org/packages/c9/6a/907ef6800f7bca71b525a05f1839b21f708c09043b1c6aa77b6b827b3996/librt-0.8.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f", size = 66081, upload-time = "2026-02-17T16:12:12.766Z" }, + { url = "https://files.pythonhosted.org/packages/1b/18/25e991cd5640c9fb0f8d91b18797b29066b792f17bf8493da183bf5caabe/librt-0.8.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c", size = 68309, upload-time = "2026-02-17T16:12:13.756Z" }, + { url = "https://files.pythonhosted.org/packages/a4/36/46820d03f058cfb5a9de5940640ba03165ed8aded69e0733c417bb04df34/librt-0.8.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc", size = 196804, upload-time = "2026-02-17T16:12:14.818Z" }, + { url = "https://files.pythonhosted.org/packages/59/18/5dd0d3b87b8ff9c061849fbdb347758d1f724b9a82241aa908e0ec54ccd0/librt-0.8.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c", size = 206907, upload-time = "2026-02-17T16:12:16.513Z" }, + { url = "https://files.pythonhosted.org/packages/d1/96/ef04902aad1424fd7299b62d1890e803e6ab4018c3044dca5922319c4b97/librt-0.8.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3", size = 221217, upload-time = "2026-02-17T16:12:17.906Z" }, + { url = "https://files.pythonhosted.org/packages/6d/ff/7e01f2dda84a8f5d280637a2e5827210a8acca9a567a54507ef1c75b342d/librt-0.8.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14", size = 214622, upload-time = "2026-02-17T16:12:19.108Z" }, + { url = "https://files.pythonhosted.org/packages/1e/8c/5b093d08a13946034fed57619742f790faf77058558b14ca36a6e331161e/librt-0.8.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7", size = 221987, upload-time = "2026-02-17T16:12:20.331Z" }, + { url = "https://files.pythonhosted.org/packages/d3/cc/86b0b3b151d40920ad45a94ce0171dec1aebba8a9d72bb3fa00c73ab25dd/librt-0.8.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6", size = 215132, upload-time = "2026-02-17T16:12:21.54Z" }, + { url = "https://files.pythonhosted.org/packages/fc/be/8588164a46edf1e69858d952654e216a9a91174688eeefb9efbb38a9c799/librt-0.8.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071", size = 215195, upload-time = "2026-02-17T16:12:23.073Z" }, + { url = "https://files.pythonhosted.org/packages/f5/f2/0b9279bea735c734d69344ecfe056c1ba211694a72df10f568745c899c76/librt-0.8.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78", size = 237946, upload-time = "2026-02-17T16:12:24.275Z" }, + { url = "https://files.pythonhosted.org/packages/e9/cc/5f2a34fbc8aeb35314a3641f9956fa9051a947424652fad9882be7a97949/librt-0.8.1-cp314-cp314-win32.whl", hash = "sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023", size = 50689, upload-time = "2026-02-17T16:12:25.766Z" }, + { url = "https://files.pythonhosted.org/packages/a0/76/cd4d010ab2147339ca2b93e959c3686e964edc6de66ddacc935c325883d7/librt-0.8.1-cp314-cp314-win_amd64.whl", hash = "sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730", size = 57875, upload-time = "2026-02-17T16:12:27.465Z" }, + { url = "https://files.pythonhosted.org/packages/84/0f/2143cb3c3ca48bd3379dcd11817163ca50781927c4537345d608b5045998/librt-0.8.1-cp314-cp314-win_arm64.whl", hash = "sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3", size = 48058, upload-time = "2026-02-17T16:12:28.556Z" }, + { url = "https://files.pythonhosted.org/packages/d2/0e/9b23a87e37baf00311c3efe6b48d6b6c168c29902dfc3f04c338372fd7db/librt-0.8.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1", size = 68313, upload-time = "2026-02-17T16:12:29.659Z" }, + { url = "https://files.pythonhosted.org/packages/db/9a/859c41e5a4f1c84200a7d2b92f586aa27133c8243b6cac9926f6e54d01b9/librt-0.8.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee", size = 70994, upload-time = "2026-02-17T16:12:31.516Z" }, + { url = "https://files.pythonhosted.org/packages/4c/28/10605366ee599ed34223ac2bf66404c6fb59399f47108215d16d5ad751a8/librt-0.8.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7", size = 220770, upload-time = "2026-02-17T16:12:33.294Z" }, + { url = "https://files.pythonhosted.org/packages/af/8d/16ed8fd452dafae9c48d17a6bc1ee3e818fd40ef718d149a8eff2c9f4ea2/librt-0.8.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040", size = 235409, upload-time = "2026-02-17T16:12:35.443Z" }, + { url = "https://files.pythonhosted.org/packages/89/1b/7bdf3e49349c134b25db816e4a3db6b94a47ac69d7d46b1e682c2c4949be/librt-0.8.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e", size = 246473, upload-time = "2026-02-17T16:12:36.656Z" }, + { url = "https://files.pythonhosted.org/packages/4e/8a/91fab8e4fd2a24930a17188c7af5380eb27b203d72101c9cc000dbdfd95a/librt-0.8.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732", size = 238866, upload-time = "2026-02-17T16:12:37.849Z" }, + { url = "https://files.pythonhosted.org/packages/b9/e0/c45a098843fc7c07e18a7f8a24ca8496aecbf7bdcd54980c6ca1aaa79a8e/librt-0.8.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624", size = 250248, upload-time = "2026-02-17T16:12:39.445Z" }, + { url = "https://files.pythonhosted.org/packages/82/30/07627de23036640c952cce0c1fe78972e77d7d2f8fd54fa5ef4554ff4a56/librt-0.8.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4", size = 240629, upload-time = "2026-02-17T16:12:40.889Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c1/55bfe1ee3542eba055616f9098eaf6eddb966efb0ca0f44eaa4aba327307/librt-0.8.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382", size = 239615, upload-time = "2026-02-17T16:12:42.446Z" }, + { url = "https://files.pythonhosted.org/packages/2b/39/191d3d28abc26c9099b19852e6c99f7f6d400b82fa5a4e80291bd3803e19/librt-0.8.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994", size = 263001, upload-time = "2026-02-17T16:12:43.627Z" }, + { url = "https://files.pythonhosted.org/packages/b9/eb/7697f60fbe7042ab4e88f4ee6af496b7f222fffb0a4e3593ef1f29f81652/librt-0.8.1-cp314-cp314t-win32.whl", hash = "sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a", size = 51328, upload-time = "2026-02-17T16:12:45.148Z" }, + { url = "https://files.pythonhosted.org/packages/7c/72/34bf2eb7a15414a23e5e70ecb9440c1d3179f393d9349338a91e2781c0fb/librt-0.8.1-cp314-cp314t-win_amd64.whl", hash = "sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4", size = 58722, upload-time = "2026-02-17T16:12:46.85Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c8/d148e041732d631fc76036f8b30fae4e77b027a1e95b7a84bb522481a940/librt-0.8.1-cp314-cp314t-win_arm64.whl", hash = "sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61", size = 48755, upload-time = "2026-02-17T16:12:47.943Z" }, +] + +[[package]] +name = "license-expression" +version = "30.4.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "boolean-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/71/d89bb0e71b1415453980fd32315f2a037aad9f7f70f695c7cec7035feb13/license_expression-30.4.4.tar.gz", hash = "sha256:73448f0aacd8d0808895bdc4b2c8e01a8d67646e4188f887375398c761f340fd", size = 186402, upload-time = "2025-07-22T11:13:32.17Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/40/791891d4c0c4dab4c5e187c17261cedc26285fd41541577f900470a45a4d/license_expression-30.4.4-py3-none-any.whl", hash = "sha256:421788fdcadb41f049d2dc934ce666626265aeccefddd25e162a26f23bcbf8a4", size = 120615, upload-time = "2025-07-22T11:13:31.217Z" }, +] + +[[package]] +name = "linkify-it-py" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "uc-micro-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2e/c9/06ea13676ef354f0af6169587ae292d3e2406e212876a413bf9eece4eb23/linkify_it_py-2.1.0.tar.gz", hash = "sha256:43360231720999c10e9328dc3691160e27a718e280673d444c38d7d3aaa3b98b", size = 29158, upload-time = "2026-03-01T07:48:47.683Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b4/de/88b3be5c31b22333b3ca2f6ff1de4e863d8fe45aaea7485f591970ec1d3e/linkify_it_py-2.1.0-py3-none-any.whl", hash = "sha256:0d252c1594ecba2ecedc444053db5d3a9b7ec1b0dd929c8f1d74dce89f86c05e", size = 19878, upload-time = "2026-03-01T07:48:46.098Z" }, +] + +[[package]] +name = "macholib" +version = "1.16.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "altgraph" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/2f/97589876ea967487978071c9042518d28b958d87b17dceb7cdc1d881f963/macholib-1.16.4.tar.gz", hash = "sha256:f408c93ab2e995cd2c46e34fe328b130404be143469e41bc366c807448979362", size = 59427, upload-time = "2025-11-22T08:28:38.373Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/d1/a9f36f8ecdf0fb7c9b1e78c8d7af12b8c8754e74851ac7b94a8305540fc7/macholib-1.16.4-py2.py3-none-any.whl", hash = "sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea", size = 38117, upload-time = "2025-11-22T08:28:36.939Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[package.optional-dependencies] +linkify = [ + { name = "linkify-it-py" }, +] +plugins = [ + { name = "mdit-py-plugins" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", size = 11631, upload-time = "2025-09-27T18:36:05.558Z" }, + { url = "https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", size = 12057, upload-time = "2025-09-27T18:36:07.165Z" }, + { url = "https://files.pythonhosted.org/packages/40/01/e560d658dc0bb8ab762670ece35281dec7b6c1b33f5fbc09ebb57a185519/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", size = 22050, upload-time = "2025-09-27T18:36:08.005Z" }, + { url = "https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", size = 20681, upload-time = "2025-09-27T18:36:08.881Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2a/b5c12c809f1c3045c4d580b035a743d12fcde53cf685dbc44660826308da/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", size = 20705, upload-time = "2025-09-27T18:36:10.131Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e3/9427a68c82728d0a88c50f890d0fc072a1484de2f3ac1ad0bfc1a7214fd5/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", size = 21524, upload-time = "2025-09-27T18:36:11.324Z" }, + { url = "https://files.pythonhosted.org/packages/bc/36/23578f29e9e582a4d0278e009b38081dbe363c5e7165113fad546918a232/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", size = 20282, upload-time = "2025-09-27T18:36:12.573Z" }, + { url = "https://files.pythonhosted.org/packages/56/21/dca11354e756ebd03e036bd8ad58d6d7168c80ce1fe5e75218e4945cbab7/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", size = 20745, upload-time = "2025-09-27T18:36:13.504Z" }, + { url = "https://files.pythonhosted.org/packages/87/99/faba9369a7ad6e4d10b6a5fbf71fa2a188fe4a593b15f0963b73859a1bbd/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", size = 14571, upload-time = "2025-09-27T18:36:14.779Z" }, + { url = "https://files.pythonhosted.org/packages/d6/25/55dc3ab959917602c96985cb1253efaa4ff42f71194bddeb61eb7278b8be/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", size = 15056, upload-time = "2025-09-27T18:36:16.125Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9e/0a02226640c255d1da0b8d12e24ac2aa6734da68bff14c05dd53b94a0fc3/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", size = 13932, upload-time = "2025-09-27T18:36:17.311Z" }, + { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, + { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, + { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, + { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, + { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, + { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, + { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, + { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, + { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "mdit-py-plugins" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b2/fd/a756d36c0bfba5f6e39a1cdbdbfdd448dc02692467d83816dff4592a1ebc/mdit_py_plugins-0.5.0.tar.gz", hash = "sha256:f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6", size = 44655, upload-time = "2025-08-11T07:25:49.083Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl", hash = "sha256:07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f", size = 57205, upload-time = "2025-08-11T07:25:47.597Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "more-itertools" +version = "10.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ea/5d/38b681d3fce7a266dd9ab73c66959406d565b3e85f21d5e66e1181d93721/more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd", size = 137431, upload-time = "2025-09-02T15:23:11.018Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" }, +] + +[[package]] +name = "mrjob" +version = "0.7.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2c/ed/207853d1ebc6b549551d12db35e471289d26cac2cdae363419357294d3c5/mrjob-0.7.4.tar.gz", hash = "sha256:2c8d8dc8aa4b354a97de18d0260f551f018693af74af104b3d41daf165eebdd4", size = 652429, upload-time = "2020-09-17T22:26:04.518Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/58/fc28ab743aba16e90736ad4e29694bd2adaf7b879376ff149306d50c4e90/mrjob-0.7.4-py2.py3-none-any.whl", hash = "sha256:d8fa1bafcada0ffe3e7166896a27e996815e2cb835088aec025e3dd12c7146ce", size = 439592, upload-time = "2020-09-17T22:26:01.029Z" }, +] + +[[package]] +name = "msgpack" +version = "1.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4d/f2/bfb55a6236ed8725a96b0aa3acbd0ec17588e6a2c3b62a93eb513ed8783f/msgpack-1.1.2.tar.gz", hash = "sha256:3b60763c1373dd60f398488069bcdc703cd08a711477b5d480eecc9f9626f47e", size = 173581, upload-time = "2025-10-08T09:15:56.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f5/a2/3b68a9e769db68668b25c6108444a35f9bd163bb848c0650d516761a59c0/msgpack-1.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0051fffef5a37ca2cd16978ae4f0aef92f164df86823871b5162812bebecd8e2", size = 81318, upload-time = "2025-10-08T09:14:38.722Z" }, + { url = "https://files.pythonhosted.org/packages/5b/e1/2b720cc341325c00be44e1ed59e7cfeae2678329fbf5aa68f5bda57fe728/msgpack-1.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a605409040f2da88676e9c9e5853b3449ba8011973616189ea5ee55ddbc5bc87", size = 83786, upload-time = "2025-10-08T09:14:40.082Z" }, + { url = "https://files.pythonhosted.org/packages/71/e5/c2241de64bfceac456b140737812a2ab310b10538a7b34a1d393b748e095/msgpack-1.1.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b696e83c9f1532b4af884045ba7f3aa741a63b2bc22617293a2c6a7c645f251", size = 398240, upload-time = "2025-10-08T09:14:41.151Z" }, + { url = "https://files.pythonhosted.org/packages/b7/09/2a06956383c0fdebaef5aa9246e2356776f12ea6f2a44bd1368abf0e46c4/msgpack-1.1.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:365c0bbe981a27d8932da71af63ef86acc59ed5c01ad929e09a0b88c6294e28a", size = 406070, upload-time = "2025-10-08T09:14:42.821Z" }, + { url = "https://files.pythonhosted.org/packages/0e/74/2957703f0e1ef20637d6aead4fbb314330c26f39aa046b348c7edcf6ca6b/msgpack-1.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:41d1a5d875680166d3ac5c38573896453bbbea7092936d2e107214daf43b1d4f", size = 393403, upload-time = "2025-10-08T09:14:44.38Z" }, + { url = "https://files.pythonhosted.org/packages/a5/09/3bfc12aa90f77b37322fc33e7a8a7c29ba7c8edeadfa27664451801b9860/msgpack-1.1.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:354e81bcdebaab427c3df4281187edc765d5d76bfb3a7c125af9da7a27e8458f", size = 398947, upload-time = "2025-10-08T09:14:45.56Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4f/05fcebd3b4977cb3d840f7ef6b77c51f8582086de5e642f3fefee35c86fc/msgpack-1.1.2-cp310-cp310-win32.whl", hash = "sha256:e64c8d2f5e5d5fda7b842f55dec6133260ea8f53c4257d64494c534f306bf7a9", size = 64769, upload-time = "2025-10-08T09:14:47.334Z" }, + { url = "https://files.pythonhosted.org/packages/d0/3e/b4547e3a34210956382eed1c85935fff7e0f9b98be3106b3745d7dec9c5e/msgpack-1.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:db6192777d943bdaaafb6ba66d44bf65aa0e9c5616fa1d2da9bb08828c6b39aa", size = 71293, upload-time = "2025-10-08T09:14:48.665Z" }, + { url = "https://files.pythonhosted.org/packages/2c/97/560d11202bcd537abca693fd85d81cebe2107ba17301de42b01ac1677b69/msgpack-1.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2e86a607e558d22985d856948c12a3fa7b42efad264dca8a3ebbcfa2735d786c", size = 82271, upload-time = "2025-10-08T09:14:49.967Z" }, + { url = "https://files.pythonhosted.org/packages/83/04/28a41024ccbd67467380b6fb440ae916c1e4f25e2cd4c63abe6835ac566e/msgpack-1.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:283ae72fc89da59aa004ba147e8fc2f766647b1251500182fac0350d8af299c0", size = 84914, upload-time = "2025-10-08T09:14:50.958Z" }, + { url = "https://files.pythonhosted.org/packages/71/46/b817349db6886d79e57a966346cf0902a426375aadc1e8e7a86a75e22f19/msgpack-1.1.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61c8aa3bd513d87c72ed0b37b53dd5c5a0f58f2ff9f26e1555d3bd7948fb7296", size = 416962, upload-time = "2025-10-08T09:14:51.997Z" }, + { url = "https://files.pythonhosted.org/packages/da/e0/6cc2e852837cd6086fe7d8406af4294e66827a60a4cf60b86575a4a65ca8/msgpack-1.1.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:454e29e186285d2ebe65be34629fa0e8605202c60fbc7c4c650ccd41870896ef", size = 426183, upload-time = "2025-10-08T09:14:53.477Z" }, + { url = "https://files.pythonhosted.org/packages/25/98/6a19f030b3d2ea906696cedd1eb251708e50a5891d0978b012cb6107234c/msgpack-1.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7bc8813f88417599564fafa59fd6f95be417179f76b40325b500b3c98409757c", size = 411454, upload-time = "2025-10-08T09:14:54.648Z" }, + { url = "https://files.pythonhosted.org/packages/b7/cd/9098fcb6adb32187a70b7ecaabf6339da50553351558f37600e53a4a2a23/msgpack-1.1.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bafca952dc13907bdfdedfc6a5f579bf4f292bdd506fadb38389afa3ac5b208e", size = 422341, upload-time = "2025-10-08T09:14:56.328Z" }, + { url = "https://files.pythonhosted.org/packages/e6/ae/270cecbcf36c1dc85ec086b33a51a4d7d08fc4f404bdbc15b582255d05ff/msgpack-1.1.2-cp311-cp311-win32.whl", hash = "sha256:602b6740e95ffc55bfb078172d279de3773d7b7db1f703b2f1323566b878b90e", size = 64747, upload-time = "2025-10-08T09:14:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/2a/79/309d0e637f6f37e83c711f547308b91af02b72d2326ddd860b966080ef29/msgpack-1.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:d198d275222dc54244bf3327eb8cbe00307d220241d9cec4d306d49a44e85f68", size = 71633, upload-time = "2025-10-08T09:14:59.177Z" }, + { url = "https://files.pythonhosted.org/packages/73/4d/7c4e2b3d9b1106cd0aa6cb56cc57c6267f59fa8bfab7d91df5adc802c847/msgpack-1.1.2-cp311-cp311-win_arm64.whl", hash = "sha256:86f8136dfa5c116365a8a651a7d7484b65b13339731dd6faebb9a0242151c406", size = 64755, upload-time = "2025-10-08T09:15:00.48Z" }, + { url = "https://files.pythonhosted.org/packages/ad/bd/8b0d01c756203fbab65d265859749860682ccd2a59594609aeec3a144efa/msgpack-1.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:70a0dff9d1f8da25179ffcf880e10cf1aad55fdb63cd59c9a49a1b82290062aa", size = 81939, upload-time = "2025-10-08T09:15:01.472Z" }, + { url = "https://files.pythonhosted.org/packages/34/68/ba4f155f793a74c1483d4bdef136e1023f7bcba557f0db4ef3db3c665cf1/msgpack-1.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:446abdd8b94b55c800ac34b102dffd2f6aa0ce643c55dfc017ad89347db3dbdb", size = 85064, upload-time = "2025-10-08T09:15:03.764Z" }, + { url = "https://files.pythonhosted.org/packages/f2/60/a064b0345fc36c4c3d2c743c82d9100c40388d77f0b48b2f04d6041dbec1/msgpack-1.1.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c63eea553c69ab05b6747901b97d620bb2a690633c77f23feb0c6a947a8a7b8f", size = 417131, upload-time = "2025-10-08T09:15:05.136Z" }, + { url = "https://files.pythonhosted.org/packages/65/92/a5100f7185a800a5d29f8d14041f61475b9de465ffcc0f3b9fba606e4505/msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:372839311ccf6bdaf39b00b61288e0557916c3729529b301c52c2d88842add42", size = 427556, upload-time = "2025-10-08T09:15:06.837Z" }, + { url = "https://files.pythonhosted.org/packages/f5/87/ffe21d1bf7d9991354ad93949286f643b2bb6ddbeab66373922b44c3b8cc/msgpack-1.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2929af52106ca73fcb28576218476ffbb531a036c2adbcf54a3664de124303e9", size = 404920, upload-time = "2025-10-08T09:15:08.179Z" }, + { url = "https://files.pythonhosted.org/packages/ff/41/8543ed2b8604f7c0d89ce066f42007faac1eaa7d79a81555f206a5cdb889/msgpack-1.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be52a8fc79e45b0364210eef5234a7cf8d330836d0a64dfbb878efa903d84620", size = 415013, upload-time = "2025-10-08T09:15:09.83Z" }, + { url = "https://files.pythonhosted.org/packages/41/0d/2ddfaa8b7e1cee6c490d46cb0a39742b19e2481600a7a0e96537e9c22f43/msgpack-1.1.2-cp312-cp312-win32.whl", hash = "sha256:1fff3d825d7859ac888b0fbda39a42d59193543920eda9d9bea44d958a878029", size = 65096, upload-time = "2025-10-08T09:15:11.11Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ec/d431eb7941fb55a31dd6ca3404d41fbb52d99172df2e7707754488390910/msgpack-1.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:1de460f0403172cff81169a30b9a92b260cb809c4cb7e2fc79ae8d0510c78b6b", size = 72708, upload-time = "2025-10-08T09:15:12.554Z" }, + { url = "https://files.pythonhosted.org/packages/c5/31/5b1a1f70eb0e87d1678e9624908f86317787b536060641d6798e3cf70ace/msgpack-1.1.2-cp312-cp312-win_arm64.whl", hash = "sha256:be5980f3ee0e6bd44f3a9e9dea01054f175b50c3e6cdb692bc9424c0bbb8bf69", size = 64119, upload-time = "2025-10-08T09:15:13.589Z" }, + { url = "https://files.pythonhosted.org/packages/6b/31/b46518ecc604d7edf3a4f94cb3bf021fc62aa301f0cb849936968164ef23/msgpack-1.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4efd7b5979ccb539c221a4c4e16aac1a533efc97f3b759bb5a5ac9f6d10383bf", size = 81212, upload-time = "2025-10-08T09:15:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/92/dc/c385f38f2c2433333345a82926c6bfa5ecfff3ef787201614317b58dd8be/msgpack-1.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:42eefe2c3e2af97ed470eec850facbe1b5ad1d6eacdbadc42ec98e7dcf68b4b7", size = 84315, upload-time = "2025-10-08T09:15:15.543Z" }, + { url = "https://files.pythonhosted.org/packages/d3/68/93180dce57f684a61a88a45ed13047558ded2be46f03acb8dec6d7c513af/msgpack-1.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1fdf7d83102bf09e7ce3357de96c59b627395352a4024f6e2458501f158bf999", size = 412721, upload-time = "2025-10-08T09:15:16.567Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ba/459f18c16f2b3fc1a1ca871f72f07d70c07bf768ad0a507a698b8052ac58/msgpack-1.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fac4be746328f90caa3cd4bc67e6fe36ca2bf61d5c6eb6d895b6527e3f05071e", size = 424657, upload-time = "2025-10-08T09:15:17.825Z" }, + { url = "https://files.pythonhosted.org/packages/38/f8/4398c46863b093252fe67368b44edc6c13b17f4e6b0e4929dbf0bdb13f23/msgpack-1.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fffee09044073e69f2bad787071aeec727183e7580443dfeb8556cbf1978d162", size = 402668, upload-time = "2025-10-08T09:15:19.003Z" }, + { url = "https://files.pythonhosted.org/packages/28/ce/698c1eff75626e4124b4d78e21cca0b4cc90043afb80a507626ea354ab52/msgpack-1.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5928604de9b032bc17f5099496417f113c45bc6bc21b5c6920caf34b3c428794", size = 419040, upload-time = "2025-10-08T09:15:20.183Z" }, + { url = "https://files.pythonhosted.org/packages/67/32/f3cd1667028424fa7001d82e10ee35386eea1408b93d399b09fb0aa7875f/msgpack-1.1.2-cp313-cp313-win32.whl", hash = "sha256:a7787d353595c7c7e145e2331abf8b7ff1e6673a6b974ded96e6d4ec09f00c8c", size = 65037, upload-time = "2025-10-08T09:15:21.416Z" }, + { url = "https://files.pythonhosted.org/packages/74/07/1ed8277f8653c40ebc65985180b007879f6a836c525b3885dcc6448ae6cb/msgpack-1.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:a465f0dceb8e13a487e54c07d04ae3ba131c7c5b95e2612596eafde1dccf64a9", size = 72631, upload-time = "2025-10-08T09:15:22.431Z" }, + { url = "https://files.pythonhosted.org/packages/e5/db/0314e4e2db56ebcf450f277904ffd84a7988b9e5da8d0d61ab2d057df2b6/msgpack-1.1.2-cp313-cp313-win_arm64.whl", hash = "sha256:e69b39f8c0aa5ec24b57737ebee40be647035158f14ed4b40e6f150077e21a84", size = 64118, upload-time = "2025-10-08T09:15:23.402Z" }, + { url = "https://files.pythonhosted.org/packages/22/71/201105712d0a2ff07b7873ed3c220292fb2ea5120603c00c4b634bcdafb3/msgpack-1.1.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e23ce8d5f7aa6ea6d2a2b326b4ba46c985dbb204523759984430db7114f8aa00", size = 81127, upload-time = "2025-10-08T09:15:24.408Z" }, + { url = "https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6c15b7d74c939ebe620dd8e559384be806204d73b4f9356320632d783d1f7939", size = 84981, upload-time = "2025-10-08T09:15:25.812Z" }, + { url = "https://files.pythonhosted.org/packages/8e/a9/3536e385167b88c2cc8f4424c49e28d49a6fc35206d4a8060f136e71f94c/msgpack-1.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99e2cb7b9031568a2a5c73aa077180f93dd2e95b4f8d3b8e14a73ae94a9e667e", size = 411885, upload-time = "2025-10-08T09:15:27.22Z" }, + { url = "https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:180759d89a057eab503cf62eeec0aa61c4ea1200dee709f3a8e9397dbb3b6931", size = 419658, upload-time = "2025-10-08T09:15:28.4Z" }, + { url = "https://files.pythonhosted.org/packages/3b/ef/2b92e286366500a09a67e03496ee8b8ba00562797a52f3c117aa2b29514b/msgpack-1.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:04fb995247a6e83830b62f0b07bf36540c213f6eac8e851166d8d86d83cbd014", size = 403290, upload-time = "2025-10-08T09:15:29.764Z" }, + { url = "https://files.pythonhosted.org/packages/78/90/e0ea7990abea5764e4655b8177aa7c63cdfa89945b6e7641055800f6c16b/msgpack-1.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8e22ab046fa7ede9e36eeb4cfad44d46450f37bb05d5ec482b02868f451c95e2", size = 415234, upload-time = "2025-10-08T09:15:31.022Z" }, + { url = "https://files.pythonhosted.org/packages/72/4e/9390aed5db983a2310818cd7d3ec0aecad45e1f7007e0cda79c79507bb0d/msgpack-1.1.2-cp314-cp314-win32.whl", hash = "sha256:80a0ff7d4abf5fecb995fcf235d4064b9a9a8a40a3ab80999e6ac1e30b702717", size = 66391, upload-time = "2025-10-08T09:15:32.265Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:9ade919fac6a3e7260b7f64cea89df6bec59104987cbea34d34a2fa15d74310b", size = 73787, upload-time = "2025-10-08T09:15:33.219Z" }, + { url = "https://files.pythonhosted.org/packages/6a/b0/9d9f667ab48b16ad4115c1935d94023b82b3198064cb84a123e97f7466c1/msgpack-1.1.2-cp314-cp314-win_arm64.whl", hash = "sha256:59415c6076b1e30e563eb732e23b994a61c159cec44deaf584e5cc1dd662f2af", size = 66453, upload-time = "2025-10-08T09:15:34.225Z" }, + { url = "https://files.pythonhosted.org/packages/16/67/93f80545eb1792b61a217fa7f06d5e5cb9e0055bed867f43e2b8e012e137/msgpack-1.1.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:897c478140877e5307760b0ea66e0932738879e7aa68144d9b78ea4c8302a84a", size = 85264, upload-time = "2025-10-08T09:15:35.61Z" }, + { url = "https://files.pythonhosted.org/packages/87/1c/33c8a24959cf193966ef11a6f6a2995a65eb066bd681fd085afd519a57ce/msgpack-1.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a668204fa43e6d02f89dbe79a30b0d67238d9ec4c5bd8a940fc3a004a47b721b", size = 89076, upload-time = "2025-10-08T09:15:36.619Z" }, + { url = "https://files.pythonhosted.org/packages/fc/6b/62e85ff7193663fbea5c0254ef32f0c77134b4059f8da89b958beb7696f3/msgpack-1.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5559d03930d3aa0f3aacb4c42c776af1a2ace2611871c84a75afe436695e6245", size = 435242, upload-time = "2025-10-08T09:15:37.647Z" }, + { url = "https://files.pythonhosted.org/packages/c1/47/5c74ecb4cc277cf09f64e913947871682ffa82b3b93c8dad68083112f412/msgpack-1.1.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:70c5a7a9fea7f036b716191c29047374c10721c389c21e9ffafad04df8c52c90", size = 432509, upload-time = "2025-10-08T09:15:38.794Z" }, + { url = "https://files.pythonhosted.org/packages/24/a4/e98ccdb56dc4e98c929a3f150de1799831c0a800583cde9fa022fa90602d/msgpack-1.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f2cb069d8b981abc72b41aea1c580ce92d57c673ec61af4c500153a626cb9e20", size = 415957, upload-time = "2025-10-08T09:15:40.238Z" }, + { url = "https://files.pythonhosted.org/packages/da/28/6951f7fb67bc0a4e184a6b38ab71a92d9ba58080b27a77d3e2fb0be5998f/msgpack-1.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d62ce1f483f355f61adb5433ebfd8868c5f078d1a52d042b0a998682b4fa8c27", size = 422910, upload-time = "2025-10-08T09:15:41.505Z" }, + { url = "https://files.pythonhosted.org/packages/f0/03/42106dcded51f0a0b5284d3ce30a671e7bd3f7318d122b2ead66ad289fed/msgpack-1.1.2-cp314-cp314t-win32.whl", hash = "sha256:1d1418482b1ee984625d88aa9585db570180c286d942da463533b238b98b812b", size = 75197, upload-time = "2025-10-08T09:15:42.954Z" }, + { url = "https://files.pythonhosted.org/packages/15/86/d0071e94987f8db59d4eeb386ddc64d0bb9b10820a8d82bcd3e53eeb2da6/msgpack-1.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:5a46bf7e831d09470ad92dff02b8b1ac92175ca36b087f904a0519857c6be3ff", size = 85772, upload-time = "2025-10-08T09:15:43.954Z" }, + { url = "https://files.pythonhosted.org/packages/81/f2/08ace4142eb281c12701fc3b93a10795e4d4dc7f753911d836675050f886/msgpack-1.1.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d99ef64f349d5ec3293688e91486c5fdb925ed03807f64d98d205d2713c60b46", size = 70868, upload-time = "2025-10-08T09:15:44.959Z" }, +] + +[[package]] +name = "msgpack-types" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "msgpack" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7f/26/a15707f2af5681333cd598724bedd1948844ac2af45eafc4175af0671a8d/msgpack_types-0.5.0.tar.gz", hash = "sha256:aebd1b8da23f8f9966d66ebb1a43bd261b95751c6a267bd21a124d2ccac84201", size = 6702, upload-time = "2024-09-21T13:55:05.587Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/dd/cd9d2b0ef506f6164cd81d4e92e408095041f28523d751b9f7dabdc244eb/msgpack_types-0.5.0-py3-none-any.whl", hash = "sha256:8b633ed75e495a555fa0615843de559a74b1d176828d59bb393d266e51f6bda7", size = 8182, upload-time = "2024-09-21T13:55:04.232Z" }, +] + +[[package]] +name = "mslex" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/97/7022667073c99a0fe028f2e34b9bf76b49a611afd21b02527fbfd92d4cd5/mslex-1.3.0.tar.gz", hash = "sha256:641c887d1d3db610eee2af37a8e5abda3f70b3006cdfd2d0d29dc0d1ae28a85d", size = 11583, upload-time = "2024-10-16T13:16:18.523Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/f2/66bd65ca0139675a0d7b18f0bada6e12b51a984e41a76dbe44761bf1b3ee/mslex-1.3.0-py3-none-any.whl", hash = "sha256:c7074b347201b3466fc077c5692fbce9b5f62a63a51f537a53fbbd02eff2eea4", size = 7820, upload-time = "2024-10-16T13:16:17.566Z" }, +] + +[[package]] +name = "multiformats" +version = "0.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bases" }, + { name = "multiformats-config" }, + { name = "typing-extensions" }, + { name = "typing-validation" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0a/a8/5b341c3ca0dd651b6276430651b7a6943625a2df419427bcae11b6e32267/multiformats-0.3.1.tar.gz", hash = "sha256:6b011e780d8283395c3062e16def6a61636ee265a3a8c94cc83d7a80293e70e5", size = 825880, upload-time = "2023-12-18T22:08:46.984Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/a3/7f2566a11d72502eacbeaedad95fa156a292862b9220483aea522a76ddb5/multiformats-0.3.1-py3-none-any.whl", hash = "sha256:e194bae88004cb41ca8df83cd330d97e0a566c46db99e915831761cbf0a319a4", size = 57218, upload-time = "2023-12-18T22:08:44.616Z" }, +] + +[[package]] +name = "multiformats-config" +version = "0.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "multiformats" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c6/09/ccb6867c2d6c6de98d1d285d8a3a2103fdf452c2fef5019bb3d8ac9938d9/multiformats-config-0.3.1.tar.gz", hash = "sha256:7eaa80ef5d9c5ee9b86612d21f93a087c4a655cbcb68960457e61adbc62b47a7", size = 28345, upload-time = "2023-12-18T21:35:23.972Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/9b/c21a9c1d5ea4847989f1eb00e3147e38e79aaea7c4b4d1cbd4f1afae9740/multiformats_config-0.3.1-py3-none-any.whl", hash = "sha256:dec4c9d42ed0d9305889b67440f72e8e8d74b82b80abd7219667764b5b0a8e1d", size = 17153, upload-time = "2023-12-18T21:35:21.171Z" }, +] + +[[package]] +name = "mypy" +version = "1.19.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/db/4efed9504bc01309ab9c2da7e352cc223569f05478012b5d9ece38fd44d2/mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", size = 3582404, upload-time = "2025-12-15T05:03:48.42Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/63/e499890d8e39b1ff2df4c0c6ce5d371b6844ee22b8250687a99fd2f657a8/mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec", size = 13101333, upload-time = "2025-12-15T05:03:03.28Z" }, + { url = "https://files.pythonhosted.org/packages/72/4b/095626fc136fba96effc4fd4a82b41d688ab92124f8c4f7564bffe5cf1b0/mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b", size = 12164102, upload-time = "2025-12-15T05:02:33.611Z" }, + { url = "https://files.pythonhosted.org/packages/0c/5b/952928dd081bf88a83a5ccd49aaecfcd18fd0d2710c7ff07b8fb6f7032b9/mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6", size = 12765799, upload-time = "2025-12-15T05:03:28.44Z" }, + { url = "https://files.pythonhosted.org/packages/2a/0d/93c2e4a287f74ef11a66fb6d49c7a9f05e47b0a4399040e6719b57f500d2/mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74", size = 13522149, upload-time = "2025-12-15T05:02:36.011Z" }, + { url = "https://files.pythonhosted.org/packages/7b/0e/33a294b56aaad2b338d203e3a1d8b453637ac36cb278b45005e0901cf148/mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1", size = 13810105, upload-time = "2025-12-15T05:02:40.327Z" }, + { url = "https://files.pythonhosted.org/packages/0e/fd/3e82603a0cb66b67c5e7abababce6bf1a929ddf67bf445e652684af5c5a0/mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac", size = 10057200, upload-time = "2025-12-15T05:02:51.012Z" }, + { url = "https://files.pythonhosted.org/packages/ef/47/6b3ebabd5474d9cdc170d1342fbf9dddc1b0ec13ec90bf9004ee6f391c31/mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288", size = 13028539, upload-time = "2025-12-15T05:03:44.129Z" }, + { url = "https://files.pythonhosted.org/packages/5c/a6/ac7c7a88a3c9c54334f53a941b765e6ec6c4ebd65d3fe8cdcfbe0d0fd7db/mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab", size = 12083163, upload-time = "2025-12-15T05:03:37.679Z" }, + { url = "https://files.pythonhosted.org/packages/67/af/3afa9cf880aa4a2c803798ac24f1d11ef72a0c8079689fac5cfd815e2830/mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6", size = 12687629, upload-time = "2025-12-15T05:02:31.526Z" }, + { url = "https://files.pythonhosted.org/packages/2d/46/20f8a7114a56484ab268b0ab372461cb3a8f7deed31ea96b83a4e4cfcfca/mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331", size = 13436933, upload-time = "2025-12-15T05:03:15.606Z" }, + { url = "https://files.pythonhosted.org/packages/5b/f8/33b291ea85050a21f15da910002460f1f445f8007adb29230f0adea279cb/mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925", size = 13661754, upload-time = "2025-12-15T05:02:26.731Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a3/47cbd4e85bec4335a9cd80cf67dbc02be21b5d4c9c23ad6b95d6c5196bac/mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042", size = 10055772, upload-time = "2025-12-15T05:03:26.179Z" }, + { url = "https://files.pythonhosted.org/packages/06/8a/19bfae96f6615aa8a0604915512e0289b1fad33d5909bf7244f02935d33a/mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1", size = 13206053, upload-time = "2025-12-15T05:03:46.622Z" }, + { url = "https://files.pythonhosted.org/packages/a5/34/3e63879ab041602154ba2a9f99817bb0c85c4df19a23a1443c8986e4d565/mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e", size = 12219134, upload-time = "2025-12-15T05:03:24.367Z" }, + { url = "https://files.pythonhosted.org/packages/89/cc/2db6f0e95366b630364e09845672dbee0cbf0bbe753a204b29a944967cd9/mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2", size = 12731616, upload-time = "2025-12-15T05:02:44.725Z" }, + { url = "https://files.pythonhosted.org/packages/00/be/dd56c1fd4807bc1eba1cf18b2a850d0de7bacb55e158755eb79f77c41f8e/mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8", size = 13620847, upload-time = "2025-12-15T05:03:39.633Z" }, + { url = "https://files.pythonhosted.org/packages/6d/42/332951aae42b79329f743bf1da088cd75d8d4d9acc18fbcbd84f26c1af4e/mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a", size = 13834976, upload-time = "2025-12-15T05:03:08.786Z" }, + { url = "https://files.pythonhosted.org/packages/6f/63/e7493e5f90e1e085c562bb06e2eb32cae27c5057b9653348d38b47daaecc/mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13", size = 10118104, upload-time = "2025-12-15T05:03:10.834Z" }, + { url = "https://files.pythonhosted.org/packages/de/9f/a6abae693f7a0c697dbb435aac52e958dc8da44e92e08ba88d2e42326176/mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250", size = 13201927, upload-time = "2025-12-15T05:02:29.138Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a4/45c35ccf6e1c65afc23a069f50e2c66f46bd3798cbe0d680c12d12935caa/mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b", size = 12206730, upload-time = "2025-12-15T05:03:01.325Z" }, + { url = "https://files.pythonhosted.org/packages/05/bb/cdcf89678e26b187650512620eec8368fded4cfd99cfcb431e4cdfd19dec/mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e", size = 12724581, upload-time = "2025-12-15T05:03:20.087Z" }, + { url = "https://files.pythonhosted.org/packages/d1/32/dd260d52babf67bad8e6770f8e1102021877ce0edea106e72df5626bb0ec/mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef", size = 13616252, upload-time = "2025-12-15T05:02:49.036Z" }, + { url = "https://files.pythonhosted.org/packages/71/d0/5e60a9d2e3bd48432ae2b454b7ef2b62a960ab51292b1eda2a95edd78198/mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75", size = 13840848, upload-time = "2025-12-15T05:02:55.95Z" }, + { url = "https://files.pythonhosted.org/packages/98/76/d32051fa65ecf6cc8c6610956473abdc9b4c43301107476ac03559507843/mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd", size = 10135510, upload-time = "2025-12-15T05:02:58.438Z" }, + { url = "https://files.pythonhosted.org/packages/de/eb/b83e75f4c820c4247a58580ef86fcd35165028f191e7e1ba57128c52782d/mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1", size = 13199744, upload-time = "2025-12-15T05:03:30.823Z" }, + { url = "https://files.pythonhosted.org/packages/94/28/52785ab7bfa165f87fcbb61547a93f98bb20e7f82f90f165a1f69bce7b3d/mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718", size = 12215815, upload-time = "2025-12-15T05:02:42.323Z" }, + { url = "https://files.pythonhosted.org/packages/0a/c6/bdd60774a0dbfb05122e3e925f2e9e846c009e479dcec4821dad881f5b52/mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b", size = 12740047, upload-time = "2025-12-15T05:03:33.168Z" }, + { url = "https://files.pythonhosted.org/packages/32/2a/66ba933fe6c76bd40d1fe916a83f04fed253152f451a877520b3c4a5e41e/mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045", size = 13601998, upload-time = "2025-12-15T05:03:13.056Z" }, + { url = "https://files.pythonhosted.org/packages/e3/da/5055c63e377c5c2418760411fd6a63ee2b96cf95397259038756c042574f/mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957", size = 13807476, upload-time = "2025-12-15T05:03:17.977Z" }, + { url = "https://files.pythonhosted.org/packages/cd/09/4ebd873390a063176f06b0dbf1f7783dd87bd120eae7727fa4ae4179b685/mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f", size = 10281872, upload-time = "2025-12-15T05:03:05.549Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "nh3" +version = "0.3.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/37/ab55eb2b05e334ff9a1ad52c556ace1f9c20a3f63613a165d384d5387657/nh3-0.3.3.tar.gz", hash = "sha256:185ed41b88c910b9ca8edc89ca3b4be688a12cb9de129d84befa2f74a0039fee", size = 18968, upload-time = "2026-02-14T09:35:15.664Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/a4/834f0ebd80844ce67e1bdb011d6f844f61cdb4c1d7cdc56a982bc054cc00/nh3-0.3.3-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:21b058cd20d9f0919421a820a2843fdb5e1749c0bf57a6247ab8f4ba6723c9fc", size = 1428680, upload-time = "2026-02-14T09:34:33.015Z" }, + { url = "https://files.pythonhosted.org/packages/7f/1a/a7d72e750f74c6b71befbeebc4489579fe783466889d41f32e34acde0b6b/nh3-0.3.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4400a73c2a62859e769f9d36d1b5a7a5c65c4179d1dddd2f6f3095b2db0cbfc", size = 799003, upload-time = "2026-02-14T09:34:35.108Z" }, + { url = "https://files.pythonhosted.org/packages/58/d5/089eb6d65da139dc2223b83b2627e00872eccb5e1afdf5b1d76eb6ad3fcc/nh3-0.3.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1ef87f8e916321a88b45f2d597f29bd56e560ed4568a50f0f1305afab86b7189", size = 846818, upload-time = "2026-02-14T09:34:37Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c6/44a0b65fc7b213a3a725f041ef986534b100e58cd1a2e00f0fd3c9603893/nh3-0.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a446eae598987f49ee97ac2f18eafcce4e62e7574bd1eb23782e4702e54e217d", size = 1012537, upload-time = "2026-02-14T09:34:38.515Z" }, + { url = "https://files.pythonhosted.org/packages/94/3a/91bcfcc0a61b286b8b25d39e288b9c0ba91c3290d402867d1cd705169844/nh3-0.3.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:0d5eb734a78ac364af1797fef718340a373f626a9ff6b4fb0b4badf7927e7b81", size = 1095435, upload-time = "2026-02-14T09:34:40.022Z" }, + { url = "https://files.pythonhosted.org/packages/fd/fd/4617a19d80cf9f958e65724ff5e97bc2f76f2f4c5194c740016606c87bd1/nh3-0.3.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:92a958e6f6d0100e025a5686aafd67e3c98eac67495728f8bb64fbeb3e474493", size = 1056344, upload-time = "2026-02-14T09:34:41.469Z" }, + { url = "https://files.pythonhosted.org/packages/bd/7d/5bcbbc56e71b7dda7ef1d6008098da9c5426d6334137ef32bb2b9c496984/nh3-0.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9ed40cf8449a59a03aa465114fedce1ff7ac52561688811d047917cc878b19ca", size = 1034533, upload-time = "2026-02-14T09:34:43.313Z" }, + { url = "https://files.pythonhosted.org/packages/3f/9c/054eff8a59a8b23b37f0f4ac84cdd688ee84cf5251664c0e14e5d30a8a67/nh3-0.3.3-cp314-cp314t-win32.whl", hash = "sha256:b50c3770299fb2a7c1113751501e8878d525d15160a4c05194d7fe62b758aad8", size = 608305, upload-time = "2026-02-14T09:34:44.622Z" }, + { url = "https://files.pythonhosted.org/packages/d7/b0/64667b8d522c7b859717a02b1a66ba03b529ca1df623964e598af8db1ed5/nh3-0.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:21a63ccb18ddad3f784bb775955839b8b80e347e597726f01e43ca1abcc5c808", size = 620633, upload-time = "2026-02-14T09:34:46.069Z" }, + { url = "https://files.pythonhosted.org/packages/91/b5/ae9909e4ddfd86ee076c4d6d62ba69e9b31061da9d2f722936c52df8d556/nh3-0.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f508ddd4e2433fdcb78c790fc2d24e3a349ba775e5fa904af89891321d4844a3", size = 607027, upload-time = "2026-02-14T09:34:47.91Z" }, + { url = "https://files.pythonhosted.org/packages/13/3e/aef8cf8e0419b530c95e96ae93a5078e9b36c1e6613eeb1df03a80d5194e/nh3-0.3.3-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e8ee96156f7dfc6e30ecda650e480c5ae0a7d38f0c6fafc3c1c655e2500421d9", size = 1448640, upload-time = "2026-02-14T09:34:49.316Z" }, + { url = "https://files.pythonhosted.org/packages/ca/43/d2011a4f6c0272cb122eeff40062ee06bb2b6e57eabc3a5e057df0d582df/nh3-0.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45fe0d6a607264910daec30360c8a3b5b1500fd832d21b2da608256287bcb92d", size = 839405, upload-time = "2026-02-14T09:34:50.779Z" }, + { url = "https://files.pythonhosted.org/packages/f8/f3/965048510c1caf2a34ed04411a46a04a06eb05563cd06f1aa57b71eb2bc8/nh3-0.3.3-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5bc1d4b30ba1ba896669d944b6003630592665974bd11a3dc2f661bde92798a7", size = 825849, upload-time = "2026-02-14T09:34:52.622Z" }, + { url = "https://files.pythonhosted.org/packages/78/99/b4bbc6ad16329d8db2c2c320423f00b549ca3b129c2b2f9136be2606dbb0/nh3-0.3.3-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f433a2dd66545aad4a720ad1b2150edcdca75bfff6f4e6f378ade1ec138d5e77", size = 1068303, upload-time = "2026-02-14T09:34:54.179Z" }, + { url = "https://files.pythonhosted.org/packages/3f/34/3420d97065aab1b35f3e93ce9c96c8ebd423ce86fe84dee3126790421a2a/nh3-0.3.3-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52e973cb742e95b9ae1b35822ce23992428750f4b46b619fe86eba4205255b30", size = 1029316, upload-time = "2026-02-14T09:34:56.186Z" }, + { url = "https://files.pythonhosted.org/packages/f1/9a/99eda757b14e596fdb2ca5f599a849d9554181aa899274d0d183faef4493/nh3-0.3.3-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c730617bdc15d7092dcc0469dc2826b914c8f874996d105b4bc3842a41c1cd9", size = 919944, upload-time = "2026-02-14T09:34:57.886Z" }, + { url = "https://files.pythonhosted.org/packages/6f/84/c0dc75c7fb596135f999e59a410d9f45bdabb989f1cb911f0016d22b747b/nh3-0.3.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e98fa3dbfd54e25487e36ba500bc29bca3a4cab4ffba18cfb1a35a2d02624297", size = 811461, upload-time = "2026-02-14T09:34:59.65Z" }, + { url = "https://files.pythonhosted.org/packages/7e/ec/b1bf57cab6230eec910e4863528dc51dcf21b57aaf7c88ee9190d62c9185/nh3-0.3.3-cp38-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:3a62b8ae7c235481715055222e54c682422d0495a5c73326807d4e44c5d14691", size = 840360, upload-time = "2026-02-14T09:35:01.444Z" }, + { url = "https://files.pythonhosted.org/packages/37/5e/326ae34e904dde09af1de51219a611ae914111f0970f2f111f4f0188f57e/nh3-0.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc305a2264868ec8fa16548296f803d8fd9c1fa66cd28b88b605b1bd06667c0b", size = 859872, upload-time = "2026-02-14T09:35:03.348Z" }, + { url = "https://files.pythonhosted.org/packages/09/38/7eba529ce17ab4d3790205da37deabb4cb6edcba15f27b8562e467f2fc97/nh3-0.3.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:90126a834c18af03bfd6ff9a027bfa6bbf0e238527bc780a24de6bd7cc1041e2", size = 1023550, upload-time = "2026-02-14T09:35:04.829Z" }, + { url = "https://files.pythonhosted.org/packages/05/a2/556fdecd37c3681b1edee2cf795a6799c6ed0a5551b2822636960d7e7651/nh3-0.3.3-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:24769a428e9e971e4ccfb24628f83aaa7dc3c8b41b130c8ddc1835fa1c924489", size = 1105212, upload-time = "2026-02-14T09:35:06.821Z" }, + { url = "https://files.pythonhosted.org/packages/dd/e3/5db0b0ad663234967d83702277094687baf7c498831a2d3ad3451c11770f/nh3-0.3.3-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:b7a18ee057761e455d58b9d31445c3e4b2594cff4ddb84d2e331c011ef46f462", size = 1069970, upload-time = "2026-02-14T09:35:08.504Z" }, + { url = "https://files.pythonhosted.org/packages/79/b2/2ea21b79c6e869581ce5f51549b6e185c4762233591455bf2a326fb07f3b/nh3-0.3.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5a4b2c1f3e6f3cbe7048e17f4fefad3f8d3e14cc0fd08fb8599e0d5653f6b181", size = 1047588, upload-time = "2026-02-14T09:35:09.911Z" }, + { url = "https://files.pythonhosted.org/packages/e2/92/2e434619e658c806d9c096eed2cdff9a883084299b7b19a3f0824eb8e63d/nh3-0.3.3-cp38-abi3-win32.whl", hash = "sha256:e974850b131fdffa75e7ad8e0d9c7a855b96227b093417fdf1bd61656e530f37", size = 616179, upload-time = "2026-02-14T09:35:11.366Z" }, + { url = "https://files.pythonhosted.org/packages/73/88/1ce287ef8649dc51365b5094bd3713b76454838140a32ab4f8349973883c/nh3-0.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:2efd17c0355d04d39e6d79122b42662277ac10a17ea48831d90b46e5ef7e4fc0", size = 631159, upload-time = "2026-02-14T09:35:12.77Z" }, + { url = "https://files.pythonhosted.org/packages/31/f1/b4835dbde4fb06f29db89db027576d6014081cd278d9b6751facc3e69e43/nh3-0.3.3-cp38-abi3-win_arm64.whl", hash = "sha256:b838e619f483531483d26d889438e53a880510e832d2aafe73f93b7b1ac2bce2", size = 616645, upload-time = "2026-02-14T09:35:14.062Z" }, +] + +[[package]] +name = "nodeenv" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, +] + +[[package]] +name = "packageurl-python" +version = "0.17.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/d6/3b5a4e3cfaef7a53869a26ceb034d1ff5e5c27c814ce77260a96d50ab7bb/packageurl_python-0.17.6.tar.gz", hash = "sha256:1252ce3a102372ca6f86eb968e16f9014c4ba511c5c37d95a7f023e2ca6e5c25", size = 50618, upload-time = "2025-11-24T15:20:17.998Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/2f/c7277b7615a93f51b5fbc1eacfc1b75e8103370e786fd8ce2abf6e5c04ab/packageurl_python-0.17.6-py3-none-any.whl", hash = "sha256:31a85c2717bc41dd818f3c62908685ff9eebcb68588213745b14a6ee9e7df7c9", size = 36776, upload-time = "2025-11-24T15:20:16.962Z" }, +] + +[[package]] +name = "packaging" +version = "26.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, +] + +[[package]] +name = "pasteboard" +version = "0.3.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/06/43/adc39246de74e9c482c11fbe6a50e8bc7f9dc367fdc261f6f767de5b1419/pasteboard-0.3.3.tar.gz", hash = "sha256:d80275e76ff1eaaa5ca3d0e0fd8aecd5ea1298523dfd51f3774b5aaebdde02cf", size = 13540, upload-time = "2021-01-29T08:10:43.131Z" } + +[[package]] +name = "pastel" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/f1/4594f5e0fcddb6953e5b8fe00da8c317b8b41b547e2b3ae2da7512943c62/pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d", size = 7555, upload-time = "2020-09-16T19:21:12.43Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/18/a8444036c6dd65ba3624c63b734d3ba95ba63ace513078e1580590075d21/pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364", size = 5955, upload-time = "2020-09-16T19:21:11.409Z" }, +] + +[[package]] +name = "pathspec" +version = "1.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, +] + +[[package]] +name = "pefile" +version = "2024.8.26" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/03/4f/2750f7f6f025a1507cd3b7218691671eecfd0bbebebe8b39aa0fe1d360b8/pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632", size = 76008, upload-time = "2024-08-26T20:58:38.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/16/12b82f791c7f50ddec566873d5bdd245baa1491bac11d15ffb98aecc8f8b/pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f", size = 74766, upload-time = "2024-08-26T21:01:02.632Z" }, +] + +[[package]] +name = "pip" +version = "26.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/48/83/0d7d4e9efe3344b8e2fe25d93be44f64b65364d3c8d7bc6dc90198d5422e/pip-26.0.1.tar.gz", hash = "sha256:c4037d8a277c89b320abe636d59f91e6d0922d08a05b60e85e53b296613346d8", size = 1812747, upload-time = "2026-02-05T02:20:18.702Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl", hash = "sha256:bdb1b08f4274833d62c1aa29e20907365a2ceb950410df15fc9521bad440122b", size = 1787723, upload-time = "2026-02-05T02:20:16.416Z" }, +] + +[[package]] +name = "pip-api" +version = "0.0.34" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pip" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/f1/ee85f8c7e82bccf90a3c7aad22863cc6e20057860a1361083cd2adacb92e/pip_api-0.0.34.tar.gz", hash = "sha256:9b75e958f14c5a2614bae415f2adf7eeb54d50a2cfbe7e24fd4826471bac3625", size = 123017, upload-time = "2024-07-09T20:32:30.641Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/f7/ebf5003e1065fd00b4cbef53bf0a65c3d3e1b599b676d5383ccb7a8b88ba/pip_api-0.0.34-py3-none-any.whl", hash = "sha256:8b2d7d7c37f2447373aa2cf8b1f60a2f2b27a84e1e9e0294a3f6ef10eb3ba6bb", size = 120369, upload-time = "2024-07-09T20:32:29.099Z" }, +] + +[[package]] +name = "pip-audit" +version = "2.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cachecontrol", extra = ["filecache"] }, + { name = "cyclonedx-python-lib" }, + { name = "packaging" }, + { name = "pip-api" }, + { name = "pip-requirements-parser" }, + { name = "platformdirs" }, + { name = "requests" }, + { name = "rich" }, + { name = "tomli" }, + { name = "tomli-w" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/89/0e999b413facab81c33d118f3ac3739fd02c0622ccf7c4e82e37cebd8447/pip_audit-2.10.0.tar.gz", hash = "sha256:427ea5bf61d1d06b98b1ae29b7feacc00288a2eced52c9c58ceed5253ef6c2a4", size = 53776, upload-time = "2025-12-01T23:42:40.612Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/f3/4888f895c02afa085630a3a3329d1b18b998874642ad4c530e9a4d7851fe/pip_audit-2.10.0-py3-none-any.whl", hash = "sha256:16e02093872fac97580303f0848fa3ad64f7ecf600736ea7835a2b24de49613f", size = 61518, upload-time = "2025-12-01T23:42:39.193Z" }, +] + +[[package]] +name = "pip-requirements-parser" +version = "32.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "pyparsing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/2a/63b574101850e7f7b306ddbdb02cb294380d37948140eecd468fae392b54/pip-requirements-parser-32.0.1.tar.gz", hash = "sha256:b4fa3a7a0be38243123cf9d1f3518da10c51bdb165a2b2985566247f9155a7d3", size = 209359, upload-time = "2022-12-21T15:25:22.732Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/d0/d04f1d1e064ac901439699ee097f58688caadea42498ec9c4b4ad2ef84ab/pip_requirements_parser-32.0.1-py3-none-any.whl", hash = "sha256:4659bc2a667783e7a15d190f6fccf8b2486685b6dba4c19c3876314769c57526", size = 35648, upload-time = "2022-12-21T15:25:21.046Z" }, +] + +[[package]] +name = "pkginfo" +version = "1.12.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/03/e26bf3d6453b7fda5bd2b84029a426553bb373d6277ef6b5ac8863421f87/pkginfo-1.12.1.2.tar.gz", hash = "sha256:5cd957824ac36f140260964eba3c6be6442a8359b8c48f4adf90210f33a04b7b", size = 451828, upload-time = "2025-02-19T15:27:37.188Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fa/3d/f4f2ba829efb54b6cd2d91349c7463316a9cc55a43fc980447416c88540f/pkginfo-1.12.1.2-py3-none-any.whl", hash = "sha256:c783ac885519cab2c34927ccfa6bf64b5a704d7c69afaea583dd9b7afe969343", size = 32717, upload-time = "2025-02-19T15:27:33.071Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.9.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/04/fea538adf7dbbd6d186f551d595961e564a3b6715bdf276b477460858672/platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291", size = 28394, upload-time = "2026-02-16T03:56:10.574Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/31/05e764397056194206169869b50cf2fee4dbbbc71b344705b9c0d878d4d8/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd", size = 21168, upload-time = "2026-02-16T03:56:08.891Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "plumbum" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywin32", marker = "platform_python_implementation != 'PyPy' and sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dc/c8/11a5f792704b70f071a3dbc329105a98e9cc8d25daaf09f733c44eb0ef8e/plumbum-1.10.0.tar.gz", hash = "sha256:f8cbf0ecec0b73ff4e349398b65112a9e3f9300e7dc019001217dcc148d5c97c", size = 320039, upload-time = "2025-10-31T05:02:48.697Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl", hash = "sha256:9583d737ac901c474d99d030e4d5eec4c4e6d2d7417b1cf49728cf3be34f6dc8", size = 127383, upload-time = "2025-10-31T05:02:47.002Z" }, +] + +[[package]] +name = "poethepoet" +version = "0.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pastel" }, + { name = "pyyaml" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cf/ac/311c8a492dc887f0b7a54d0ec3324cb2f9538b7b78ea06e5f7ae1f167e52/poethepoet-0.36.0.tar.gz", hash = "sha256:2217b49cb4e4c64af0b42ff8c4814b17f02e107d38bc461542517348ede25663", size = 66854, upload-time = "2025-06-29T19:54:50.444Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/29/dedb3a6b7e17ea723143b834a2da428a7d743c80d5cd4d22ed28b5e8c441/poethepoet-0.36.0-py3-none-any.whl", hash = "sha256:693e3c1eae9f6731d3613c3c0c40f747d3c5c68a375beda42e590a63c5623308", size = 88031, upload-time = "2025-06-29T19:54:48.884Z" }, +] + +[[package]] +name = "pre-commit" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/64/10/97ee2fa54dff1e9da9badbc5e35d0bbaef0776271ea5907eccf64140f72f/pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af", size = 177815, upload-time = "2024-07-28T19:59:01.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/92/caae8c86e94681b42c246f0bca35c059a2f0529e5b92619f6aba4cf7e7b6/pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f", size = 204643, upload-time = "2024-07-28T19:58:59.335Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.51" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940, upload-time = "2025-04-15T09:18:47.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810, upload-time = "2025-04-15T09:18:44.753Z" }, +] + +[[package]] +name = "py-serializable" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "defusedxml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/21/d250cfca8ff30c2e5a7447bc13861541126ce9bd4426cd5d0c9f08b5547d/py_serializable-2.1.0.tar.gz", hash = "sha256:9d5db56154a867a9b897c0163b33a793c804c80cee984116d02d49e4578fc103", size = 52368, upload-time = "2025-07-21T09:56:48.07Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/bf/7595e817906a29453ba4d99394e781b6fabe55d21f3c15d240f85dd06bb1/py_serializable-2.1.0-py3-none-any.whl", hash = "sha256:b56d5d686b5a03ba4f4db5e769dc32336e142fc3bd4d68a8c25579ebb0a67304", size = 23045, upload-time = "2025-07-21T09:56:46.848Z" }, +] + +[[package]] +name = "pyclip" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pasteboard", marker = "sys_platform == 'darwin'" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/65/8a/98ed02d81dea4b2211a4746724d7a271264b701c991fed503c246de52864/pyclip-0.7.0.tar.gz", hash = "sha256:57602047a4ceab709bdcd42f3dde6449a3349b95c16154cfdce27376a2072491", size = 13639, upload-time = "2022-10-31T21:13:34.952Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/4f/4b02e2c232ddf694bca0baea3049b886eeb80ee3d89c415067f5191596c1/pyclip-0.7.0-py3-none-any.whl", hash = "sha256:a7b7ea2cfad2dd61e86a529af588d006070d3eb0bd32981afaee5215f4604fec", size = 18864, upload-time = "2022-10-31T21:13:33.459Z" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pycryptodomex" +version = "3.23.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/85/e24bf90972a30b0fcd16c73009add1d7d7cd9140c2498a68252028899e41/pycryptodomex-3.23.0.tar.gz", hash = "sha256:71909758f010c82bc99b0abf4ea12012c98962fbf0583c2164f8b84533c2e4da", size = 4922157, upload-time = "2025-05-17T17:23:41.434Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/00/10edb04777069a42490a38c137099d4b17ba6e36a4e6e28bdc7470e9e853/pycryptodomex-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:7b37e08e3871efe2187bc1fd9320cc81d87caf19816c648f24443483005ff886", size = 2498764, upload-time = "2025-05-17T17:22:21.453Z" }, + { url = "https://files.pythonhosted.org/packages/6b/3f/2872a9c2d3a27eac094f9ceaa5a8a483b774ae69018040ea3240d5b11154/pycryptodomex-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:91979028227543010d7b2ba2471cf1d1e398b3f183cb105ac584df0c36dac28d", size = 1643012, upload-time = "2025-05-17T17:22:23.702Z" }, + { url = "https://files.pythonhosted.org/packages/70/af/774c2e2b4f6570fbf6a4972161adbb183aeeaa1863bde31e8706f123bf92/pycryptodomex-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8962204c47464d5c1c4038abeadd4514a133b28748bcd9fa5b6d62e3cec6fa", size = 2187643, upload-time = "2025-05-17T17:22:26.37Z" }, + { url = "https://files.pythonhosted.org/packages/de/a3/71065b24cb889d537954cedc3ae5466af00a2cabcff8e29b73be047e9a19/pycryptodomex-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a33986a0066860f7fcf7c7bd2bc804fa90e434183645595ae7b33d01f3c91ed8", size = 2273762, upload-time = "2025-05-17T17:22:28.313Z" }, + { url = "https://files.pythonhosted.org/packages/c9/0b/ff6f43b7fbef4d302c8b981fe58467b8871902cdc3eb28896b52421422cc/pycryptodomex-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7947ab8d589e3178da3d7cdeabe14f841b391e17046954f2fbcd941705762b5", size = 2313012, upload-time = "2025-05-17T17:22:30.57Z" }, + { url = "https://files.pythonhosted.org/packages/02/de/9d4772c0506ab6da10b41159493657105d3f8bb5c53615d19452afc6b315/pycryptodomex-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c25e30a20e1b426e1f0fa00131c516f16e474204eee1139d1603e132acffc314", size = 2186856, upload-time = "2025-05-17T17:22:32.819Z" }, + { url = "https://files.pythonhosted.org/packages/28/ad/8b30efcd6341707a234e5eba5493700a17852ca1ac7a75daa7945fcf6427/pycryptodomex-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:da4fa650cef02db88c2b98acc5434461e027dce0ae8c22dd5a69013eaf510006", size = 2347523, upload-time = "2025-05-17T17:22:35.386Z" }, + { url = "https://files.pythonhosted.org/packages/0f/02/16868e9f655b7670dbb0ac4f2844145cbc42251f916fc35c414ad2359849/pycryptodomex-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:58b851b9effd0d072d4ca2e4542bf2a4abcf13c82a29fd2c93ce27ee2a2e9462", size = 2272825, upload-time = "2025-05-17T17:22:37.632Z" }, + { url = "https://files.pythonhosted.org/packages/ca/18/4ca89ac737230b52ac8ffaca42f9c6f1fd07c81a6cd821e91af79db60632/pycryptodomex-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:a9d446e844f08299236780f2efa9898c818fe7e02f17263866b8550c7d5fb328", size = 1772078, upload-time = "2025-05-17T17:22:40Z" }, + { url = "https://files.pythonhosted.org/packages/73/34/13e01c322db027682e00986873eca803f11c56ade9ba5bbf3225841ea2d4/pycryptodomex-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:bc65bdd9fc8de7a35a74cab1c898cab391a4add33a8fe740bda00f5976ca4708", size = 1803656, upload-time = "2025-05-17T17:22:42.139Z" }, + { url = "https://files.pythonhosted.org/packages/54/68/9504c8796b1805d58f4425002bcca20f12880e6fa4dc2fc9a668705c7a08/pycryptodomex-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:c885da45e70139464f082018ac527fdaad26f1657a99ee13eecdce0f0ca24ab4", size = 1707172, upload-time = "2025-05-17T17:22:44.704Z" }, + { url = "https://files.pythonhosted.org/packages/dd/9c/1a8f35daa39784ed8adf93a694e7e5dc15c23c741bbda06e1d45f8979e9e/pycryptodomex-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:06698f957fe1ab229a99ba2defeeae1c09af185baa909a31a5d1f9d42b1aaed6", size = 2499240, upload-time = "2025-05-17T17:22:46.953Z" }, + { url = "https://files.pythonhosted.org/packages/7a/62/f5221a191a97157d240cf6643747558759126c76ee92f29a3f4aee3197a5/pycryptodomex-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b2c2537863eccef2d41061e82a881dcabb04944c5c06c5aa7110b577cc487545", size = 1644042, upload-time = "2025-05-17T17:22:49.098Z" }, + { url = "https://files.pythonhosted.org/packages/8c/fd/5a054543c8988d4ed7b612721d7e78a4b9bf36bc3c5ad45ef45c22d0060e/pycryptodomex-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43c446e2ba8df8889e0e16f02211c25b4934898384c1ec1ec04d7889c0333587", size = 2186227, upload-time = "2025-05-17T17:22:51.139Z" }, + { url = "https://files.pythonhosted.org/packages/c8/a9/8862616a85cf450d2822dbd4fff1fcaba90877907a6ff5bc2672cafe42f8/pycryptodomex-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f489c4765093fb60e2edafdf223397bc716491b2b69fe74367b70d6999257a5c", size = 2272578, upload-time = "2025-05-17T17:22:53.676Z" }, + { url = "https://files.pythonhosted.org/packages/46/9f/bda9c49a7c1842820de674ab36c79f4fbeeee03f8ff0e4f3546c3889076b/pycryptodomex-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdc69d0d3d989a1029df0eed67cc5e8e5d968f3724f4519bd03e0ec68df7543c", size = 2312166, upload-time = "2025-05-17T17:22:56.585Z" }, + { url = "https://files.pythonhosted.org/packages/03/cc/870b9bf8ca92866ca0186534801cf8d20554ad2a76ca959538041b7a7cf4/pycryptodomex-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6bbcb1dd0f646484939e142462d9e532482bc74475cecf9c4903d4e1cd21f003", size = 2185467, upload-time = "2025-05-17T17:22:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/96/e3/ce9348236d8e669fea5dd82a90e86be48b9c341210f44e25443162aba187/pycryptodomex-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:8a4fcd42ccb04c31268d1efeecfccfd1249612b4de6374205376b8f280321744", size = 2346104, upload-time = "2025-05-17T17:23:02.112Z" }, + { url = "https://files.pythonhosted.org/packages/a5/e9/e869bcee87beb89040263c416a8a50204f7f7a83ac11897646c9e71e0daf/pycryptodomex-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:55ccbe27f049743a4caf4f4221b166560d3438d0b1e5ab929e07ae1702a4d6fd", size = 2271038, upload-time = "2025-05-17T17:23:04.872Z" }, + { url = "https://files.pythonhosted.org/packages/8d/67/09ee8500dd22614af5fbaa51a4aee6e342b5fa8aecf0a6cb9cbf52fa6d45/pycryptodomex-3.23.0-cp37-abi3-win32.whl", hash = "sha256:189afbc87f0b9f158386bf051f720e20fa6145975f1e76369303d0f31d1a8d7c", size = 1771969, upload-time = "2025-05-17T17:23:07.115Z" }, + { url = "https://files.pythonhosted.org/packages/69/96/11f36f71a865dd6df03716d33bd07a67e9d20f6b8d39820470b766af323c/pycryptodomex-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:52e5ca58c3a0b0bd5e100a9fbc8015059b05cffc6c66ce9d98b4b45e023443b9", size = 1803124, upload-time = "2025-05-17T17:23:09.267Z" }, + { url = "https://files.pythonhosted.org/packages/f9/93/45c1cdcbeb182ccd2e144c693eaa097763b08b38cded279f0053ed53c553/pycryptodomex-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:02d87b80778c171445d67e23d1caef279bf4b25c3597050ccd2e13970b57fd51", size = 1707161, upload-time = "2025-05-17T17:23:11.414Z" }, + { url = "https://files.pythonhosted.org/packages/f3/b8/3e76d948c3c4ac71335bbe75dac53e154b40b0f8f1f022dfa295257a0c96/pycryptodomex-3.23.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ebfff755c360d674306e5891c564a274a47953562b42fb74a5c25b8fc1fb1cb5", size = 1627695, upload-time = "2025-05-17T17:23:17.38Z" }, + { url = "https://files.pythonhosted.org/packages/6a/cf/80f4297a4820dfdfd1c88cf6c4666a200f204b3488103d027b5edd9176ec/pycryptodomex-3.23.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eca54f4bb349d45afc17e3011ed4264ef1cc9e266699874cdd1349c504e64798", size = 1675772, upload-time = "2025-05-17T17:23:19.202Z" }, + { url = "https://files.pythonhosted.org/packages/d1/42/1e969ee0ad19fe3134b0e1b856c39bd0b70d47a4d0e81c2a8b05727394c9/pycryptodomex-3.23.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2596e643d4365e14d0879dc5aafe6355616c61c2176009270f3048f6d9a61f", size = 1668083, upload-time = "2025-05-17T17:23:21.867Z" }, + { url = "https://files.pythonhosted.org/packages/6e/c3/1de4f7631fea8a992a44ba632aa40e0008764c0fb9bf2854b0acf78c2cf2/pycryptodomex-3.23.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fdfac7cda115bca3a5abb2f9e43bc2fb66c2b65ab074913643803ca7083a79ea", size = 1706056, upload-time = "2025-05-17T17:23:24.031Z" }, + { url = "https://files.pythonhosted.org/packages/f2/5f/af7da8e6f1e42b52f44a24d08b8e4c726207434e2593732d39e7af5e7256/pycryptodomex-3.23.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:14c37aaece158d0ace436f76a7bb19093db3b4deade9797abfc39ec6cd6cc2fe", size = 1806478, upload-time = "2025-05-17T17:23:26.066Z" }, +] + +[[package]] +name = "pydantic" +version = "2.12.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.41.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", size = 2107298, upload-time = "2025-11-04T13:39:04.116Z" }, + { url = "https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", size = 1901475, upload-time = "2025-11-04T13:39:06.055Z" }, + { url = "https://files.pythonhosted.org/packages/5d/b6/338abf60225acc18cdc08b4faef592d0310923d19a87fba1faf05af5346e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", size = 1918815, upload-time = "2025-11-04T13:39:10.41Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1c/2ed0433e682983d8e8cba9c8d8ef274d4791ec6a6f24c58935b90e780e0a/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", size = 2065567, upload-time = "2025-11-04T13:39:12.244Z" }, + { url = "https://files.pythonhosted.org/packages/b3/24/cf84974ee7d6eae06b9e63289b7b8f6549d416b5c199ca2d7ce13bbcf619/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52", size = 2230442, upload-time = "2025-11-04T13:39:13.962Z" }, + { url = "https://files.pythonhosted.org/packages/fd/21/4e287865504b3edc0136c89c9c09431be326168b1eb7841911cbc877a995/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", size = 2350956, upload-time = "2025-11-04T13:39:15.889Z" }, + { url = "https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", size = 2068253, upload-time = "2025-11-04T13:39:17.403Z" }, + { url = "https://files.pythonhosted.org/packages/d5/8c/a4abfc79604bcb4c748e18975c44f94f756f08fb04218d5cb87eb0d3a63e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", size = 2177050, upload-time = "2025-11-04T13:39:19.351Z" }, + { url = "https://files.pythonhosted.org/packages/67/b1/de2e9a9a79b480f9cb0b6e8b6ba4c50b18d4e89852426364c66aa82bb7b3/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", size = 2147178, upload-time = "2025-11-04T13:39:21Z" }, + { url = "https://files.pythonhosted.org/packages/16/c1/dfb33f837a47b20417500efaa0378adc6635b3c79e8369ff7a03c494b4ac/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", size = 2341833, upload-time = "2025-11-04T13:39:22.606Z" }, + { url = "https://files.pythonhosted.org/packages/47/36/00f398642a0f4b815a9a558c4f1dca1b4020a7d49562807d7bc9ff279a6c/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", size = 2321156, upload-time = "2025-11-04T13:39:25.843Z" }, + { url = "https://files.pythonhosted.org/packages/7e/70/cad3acd89fde2010807354d978725ae111ddf6d0ea46d1ea1775b5c1bd0c/pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", size = 1989378, upload-time = "2025-11-04T13:39:27.92Z" }, + { url = "https://files.pythonhosted.org/packages/76/92/d338652464c6c367e5608e4488201702cd1cbb0f33f7b6a85a60fe5f3720/pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", size = 2013622, upload-time = "2025-11-04T13:39:29.848Z" }, + { url = "https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" }, + { url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" }, + { url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" }, + { url = "https://files.pythonhosted.org/packages/6e/6a/30d94a9674a7fe4f4744052ed6c5e083424510be1e93da5bc47569d11810/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", size = 2063890, upload-time = "2025-11-04T13:39:36.053Z" }, + { url = "https://files.pythonhosted.org/packages/50/be/76e5d46203fcb2750e542f32e6c371ffa9b8ad17364cf94bb0818dbfb50c/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", size = 2229740, upload-time = "2025-11-04T13:39:37.753Z" }, + { url = "https://files.pythonhosted.org/packages/d3/ee/fed784df0144793489f87db310a6bbf8118d7b630ed07aa180d6067e653a/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", size = 2350021, upload-time = "2025-11-04T13:39:40.94Z" }, + { url = "https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", size = 2066378, upload-time = "2025-11-04T13:39:42.523Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3b/698cf8ae1d536a010e05121b4958b1257f0b5522085e335360e53a6b1c8b/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", size = 2175761, upload-time = "2025-11-04T13:39:44.553Z" }, + { url = "https://files.pythonhosted.org/packages/b8/ba/15d537423939553116dea94ce02f9c31be0fa9d0b806d427e0308ec17145/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", size = 2146303, upload-time = "2025-11-04T13:39:46.238Z" }, + { url = "https://files.pythonhosted.org/packages/58/7f/0de669bf37d206723795f9c90c82966726a2ab06c336deba4735b55af431/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", size = 2340355, upload-time = "2025-11-04T13:39:48.002Z" }, + { url = "https://files.pythonhosted.org/packages/e5/de/e7482c435b83d7e3c3ee5ee4451f6e8973cff0eb6007d2872ce6383f6398/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", size = 2319875, upload-time = "2025-11-04T13:39:49.705Z" }, + { url = "https://files.pythonhosted.org/packages/fe/e6/8c9e81bb6dd7560e33b9053351c29f30c8194b72f2d6932888581f503482/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", size = 1987549, upload-time = "2025-11-04T13:39:51.842Z" }, + { url = "https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", size = 2011305, upload-time = "2025-11-04T13:39:53.485Z" }, + { url = "https://files.pythonhosted.org/packages/56/d8/0e271434e8efd03186c5386671328154ee349ff0354d83c74f5caaf096ed/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", size = 1972902, upload-time = "2025-11-04T13:39:56.488Z" }, + { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, + { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, + { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, + { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, + { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, + { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, + { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, + { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, + { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, + { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, + { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, + { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, + { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, + { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, + { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, + { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, + { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, + { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, + { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, + { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, + { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, + { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, + { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, + { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, + { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, + { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, + { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, + { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, + { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, + { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, + { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, + { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, + { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, + { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, + { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, + { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, + { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, + { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, + { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, + { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, + { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, + { url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" }, + { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" }, + { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905, upload-time = "2025-11-04T13:42:47.156Z" }, + { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, + { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, + { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, + { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b0/1a2aa41e3b5a4ba11420aba2d091b2d17959c8d1519ece3627c371951e73/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", size = 2103351, upload-time = "2025-11-04T13:43:02.058Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ee/31b1f0020baaf6d091c87900ae05c6aeae101fa4e188e1613c80e4f1ea31/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", size = 1925363, upload-time = "2025-11-04T13:43:05.159Z" }, + { url = "https://files.pythonhosted.org/packages/e1/89/ab8e86208467e467a80deaca4e434adac37b10a9d134cd2f99b28a01e483/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", size = 2135615, upload-time = "2025-11-04T13:43:08.116Z" }, + { url = "https://files.pythonhosted.org/packages/99/0a/99a53d06dd0348b2008f2f30884b34719c323f16c3be4e6cc1203b74a91d/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", size = 2175369, upload-time = "2025-11-04T13:43:12.49Z" }, + { url = "https://files.pythonhosted.org/packages/6d/94/30ca3b73c6d485b9bb0bc66e611cff4a7138ff9736b7e66bcf0852151636/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", size = 2144218, upload-time = "2025-11-04T13:43:15.431Z" }, + { url = "https://files.pythonhosted.org/packages/87/57/31b4f8e12680b739a91f472b5671294236b82586889ef764b5fbc6669238/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", size = 2329951, upload-time = "2025-11-04T13:43:18.062Z" }, + { url = "https://files.pythonhosted.org/packages/7d/73/3c2c8edef77b8f7310e6fb012dbc4b8551386ed575b9eb6fb2506e28a7eb/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", size = 2318428, upload-time = "2025-11-04T13:43:20.679Z" }, + { url = "https://files.pythonhosted.org/packages/2f/02/8559b1f26ee0d502c74f9cca5c0d2fd97e967e083e006bbbb4e97f3a043a/pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", size = 2147009, upload-time = "2025-11-04T13:43:23.286Z" }, + { url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" }, + { url = "https://files.pythonhosted.org/packages/83/d9/8412d7f06f616bbc053d30cb4e5f76786af3221462ad5eee1f202021eb4e/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", size = 2174762, upload-time = "2025-11-04T13:43:34.744Z" }, + { url = "https://files.pythonhosted.org/packages/55/4c/162d906b8e3ba3a99354e20faa1b49a85206c47de97a639510a0e673f5da/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", size = 2143141, upload-time = "2025-11-04T13:43:37.701Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f2/f11dd73284122713f5f89fc940f370d035fa8e1e078d446b3313955157fe/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", size = 2330317, upload-time = "2025-11-04T13:43:40.406Z" }, + { url = "https://files.pythonhosted.org/packages/88/9d/b06ca6acfe4abb296110fb1273a4d848a0bfb2ff65f3ee92127b3244e16b/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", size = 2316992, upload-time = "2025-11-04T13:43:43.602Z" }, + { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, +] + +[[package]] +name = "pydash" +version = "8.0.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/75/c1/1c55272f49d761cec38ddb80be9817935b9c91ebd6a8988e10f532868d56/pydash-8.0.6.tar.gz", hash = "sha256:b2821547e9723f69cf3a986be4db64de41730be149b2641947ecd12e1e11025a", size = 164338, upload-time = "2026-01-17T16:42:56.576Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/b7/cc5e7974699db40014d58c7dd7c4ad4ffc244d36930dc9ec7d06ee67d7a9/pydash-8.0.6-py3-none-any.whl", hash = "sha256:ee70a81a5b292c007f28f03a4ee8e75c1f5d7576df5457b836ec7ab2839cc5d0", size = 101561, upload-time = "2026-01-17T16:42:55.448Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pyinstaller" +version = "6.19.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "altgraph" }, + { name = "macholib", marker = "sys_platform == 'darwin'" }, + { name = "packaging" }, + { name = "pefile", marker = "sys_platform == 'win32'" }, + { name = "pyinstaller-hooks-contrib" }, + { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, + { name = "setuptools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c8/63/fd62472b6371d89dc138d40c36d87a50dc2de18a035803bbdc376b4ffac4/pyinstaller-6.19.0.tar.gz", hash = "sha256:ec73aeb8bd9b7f2f1240d328a4542e90b3c6e6fbc106014778431c616592a865", size = 4036072, upload-time = "2026-02-14T18:06:28.718Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/eb/23374721fecfa72677e79800921cb6aceefa6ba48574dc404f3f6c6c3be7/pyinstaller-6.19.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:4190e76b74f0c4b5c5f11ac360928cd2e36ec8e3194d437bf6b8648c7bc0c134", size = 1040563, upload-time = "2026-02-14T18:05:22.436Z" }, + { url = "https://files.pythonhosted.org/packages/cd/7e/dfd724b0b533f5aaec0ee5df406fe2319987ed6964480a706f85478b12ea/pyinstaller-6.19.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:8bd68abd812d8a6ba33b9f1810e91fee0f325969733721b78151f0065319ca11", size = 735477, upload-time = "2026-02-14T18:05:27.143Z" }, + { url = "https://files.pythonhosted.org/packages/88/c9/ee3a4101c31f26344e66896c73c1fd6ed8282bf871473365b7f8674af406/pyinstaller-6.19.0-py3-none-manylinux2014_i686.whl", hash = "sha256:1ec54ef967996ca61dacba676227e2b23219878ccce5ee9d6f3aada7b8ed8abf", size = 747143, upload-time = "2026-02-14T18:05:31.488Z" }, + { url = "https://files.pythonhosted.org/packages/da/0a/fc77e9f861be8cf300ac37155f59cc92aff99b29f2ddd78546f563a5b5a6/pyinstaller-6.19.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:4ab2bb52e58448e14ddf9450601bdedd66800465043501c1d8f1cab87b60b122", size = 744849, upload-time = "2026-02-14T18:05:35.492Z" }, + { url = "https://files.pythonhosted.org/packages/6d/e3/6872e020ee758afe0b821663858492c10745608b07150e5e2c824a5b3e1c/pyinstaller-6.19.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:da6d5c6391ccefe73554b9fa29b86001c8e378e0f20c2a4004f836ba537eff63", size = 741590, upload-time = "2026-02-14T18:05:39.59Z" }, + { url = "https://files.pythonhosted.org/packages/53/60/b8db5f1a4b0fb228175f2ea0aa33f949adcc097fbe981cc524f9faf85777/pyinstaller-6.19.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a0fc5f6b3c55aa54353f0c74ffa59b1115433c1850c6f655d62b461a2ed6cbbe", size = 741448, upload-time = "2026-02-14T18:05:45.636Z" }, + { url = "https://files.pythonhosted.org/packages/6f/4d/63b0600f2694e9141b83129fbc1c488ec84d5a0770b1448ec154dcd0fee9/pyinstaller-6.19.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:e649ba6bd1b0b89b210ad92adb5fbdc8a42dd2c5ca4f72ef3a0bfec83a424b83", size = 740613, upload-time = "2026-02-14T18:05:49.726Z" }, + { url = "https://files.pythonhosted.org/packages/01/d4/e812ad36178093a0e9fd4b8127577748dd85b0cb71de912229dca21fd741/pyinstaller-6.19.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:481a909c8e60c8692fc60fcb1344d984b44b943f8bc9682f2fcdae305ad297e6", size = 740350, upload-time = "2026-02-14T18:05:54.093Z" }, + { url = "https://files.pythonhosted.org/packages/52/03/b2c2ee41fb8e10fd2a45d21f5ec2ef25852cfb978dbf762972eed59e3d63/pyinstaller-6.19.0-py3-none-win32.whl", hash = "sha256:3c5c251054fe4cfaa04c34a363dcfbf811545438cb7198304cd444756bc2edd2", size = 1324317, upload-time = "2026-02-14T18:06:00.085Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d3/6d5e62b8270e2b53a6065e281b3a7785079b00e9019c8019952828dd1669/pyinstaller-6.19.0-py3-none-win_amd64.whl", hash = "sha256:b5bb6536c6560330d364d91522250f254b107cf69129d9cbcd0e6727c570be33", size = 1384894, upload-time = "2026-02-14T18:06:06.425Z" }, + { url = "https://files.pythonhosted.org/packages/81/65/458cd523308a101a22fd2742893405030cc24994cc74b1b767cecf137160/pyinstaller-6.19.0-py3-none-win_arm64.whl", hash = "sha256:c2d5a539b0bfe6159d5522c8c70e1c0e487f22c2badae0f97d45246223b798ea", size = 1325374, upload-time = "2026-02-14T18:06:12.804Z" }, +] + +[[package]] +name = "pyinstaller-hooks-contrib" +version = "2026.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "setuptools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6b/90/f3b30d72b89ab5b8f3ef714db94d09c7c263cce6562b4c7c636d99630695/pyinstaller_hooks_contrib-2026.2.tar.gz", hash = "sha256:cbd1eb00b5d13301b1cce602e1fffb17f0c531c0391f0a87a383d376be68a186", size = 171884, upload-time = "2026-03-02T23:07:01.221Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/3b/1efef5ff4d4d150f646b873e963437c0b800cb375a37df01fefab149f4d9/pyinstaller_hooks_contrib-2026.2-py3-none-any.whl", hash = "sha256:fc29f0481b58adf78ce9c1d9cf135fe96f38c708f74b2aa0670ef93e59578ab9", size = 453939, upload-time = "2026-03-02T23:06:59.469Z" }, +] + +[[package]] +name = "pyjwt" +version = "2.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/5a/b46fa56bf322901eee5b0454a34343cdbdae202cd421775a8ee4e42fd519/pyjwt-2.11.0.tar.gz", hash = "sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623", size = 98019, upload-time = "2026-01-30T19:59:55.694Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/01/c26ce75ba460d5cd503da9e13b21a33804d38c2165dec7b716d06b13010c/pyjwt-2.11.0-py3-none-any.whl", hash = "sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469", size = 28224, upload-time = "2026-01-30T19:59:54.539Z" }, +] + +[[package]] +name = "pynacl" +version = "1.6.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/9a/4019b524b03a13438637b11538c82781a5eda427394380381af8f04f467a/pynacl-1.6.2.tar.gz", hash = "sha256:018494d6d696ae03c7e656e5e74cdfd8ea1326962cc401bcf018f1ed8436811c", size = 3511692, upload-time = "2026-01-01T17:48:10.851Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/79/0e3c34dc3c4671f67d251c07aa8eb100916f250ee470df230b0ab89551b4/pynacl-1.6.2-cp314-cp314t-macosx_10_10_universal2.whl", hash = "sha256:622d7b07cc5c02c666795792931b50c91f3ce3c2649762efb1ef0d5684c81594", size = 390064, upload-time = "2026-01-01T17:31:57.264Z" }, + { url = "https://files.pythonhosted.org/packages/eb/1c/23a26e931736e13b16483795c8a6b2f641bf6a3d5238c22b070a5112722c/pynacl-1.6.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d071c6a9a4c94d79eb665db4ce5cedc537faf74f2355e4d502591d850d3913c0", size = 809370, upload-time = "2026-01-01T17:31:59.198Z" }, + { url = "https://files.pythonhosted.org/packages/87/74/8d4b718f8a22aea9e8dcc8b95deb76d4aae380e2f5b570cc70b5fd0a852d/pynacl-1.6.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe9847ca47d287af41e82be1dd5e23023d3c31a951da134121ab02e42ac218c9", size = 1408304, upload-time = "2026-01-01T17:32:01.162Z" }, + { url = "https://files.pythonhosted.org/packages/fd/73/be4fdd3a6a87fe8a4553380c2b47fbd1f7f58292eb820902f5c8ac7de7b0/pynacl-1.6.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:04316d1fc625d860b6c162fff704eb8426b1a8bcd3abacea11142cbd99a6b574", size = 844871, upload-time = "2026-01-01T17:32:02.824Z" }, + { url = "https://files.pythonhosted.org/packages/55/ad/6efc57ab75ee4422e96b5f2697d51bbcf6cdcc091e66310df91fbdc144a8/pynacl-1.6.2-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44081faff368d6c5553ccf55322ef2819abb40e25afaec7e740f159f74813634", size = 1446356, upload-time = "2026-01-01T17:32:04.452Z" }, + { url = "https://files.pythonhosted.org/packages/78/b7/928ee9c4779caa0a915844311ab9fb5f99585621c5d6e4574538a17dca07/pynacl-1.6.2-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:a9f9932d8d2811ce1a8ffa79dcbdf3970e7355b5c8eb0c1a881a57e7f7d96e88", size = 826814, upload-time = "2026-01-01T17:32:06.078Z" }, + { url = "https://files.pythonhosted.org/packages/f7/a9/1bdba746a2be20f8809fee75c10e3159d75864ef69c6b0dd168fc60e485d/pynacl-1.6.2-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:bc4a36b28dd72fb4845e5d8f9760610588a96d5a51f01d84d8c6ff9849968c14", size = 1411742, upload-time = "2026-01-01T17:32:07.651Z" }, + { url = "https://files.pythonhosted.org/packages/f3/2f/5e7ea8d85f9f3ea5b6b87db1d8388daa3587eed181bdeb0306816fdbbe79/pynacl-1.6.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3bffb6d0f6becacb6526f8f42adfb5efb26337056ee0831fb9a7044d1a964444", size = 801714, upload-time = "2026-01-01T17:32:09.558Z" }, + { url = "https://files.pythonhosted.org/packages/06/ea/43fe2f7eab5f200e40fb10d305bf6f87ea31b3bbc83443eac37cd34a9e1e/pynacl-1.6.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2fef529ef3ee487ad8113d287a593fa26f48ee3620d92ecc6f1d09ea38e0709b", size = 1372257, upload-time = "2026-01-01T17:32:11.026Z" }, + { url = "https://files.pythonhosted.org/packages/4d/54/c9ea116412788629b1347e415f72195c25eb2f3809b2d3e7b25f5c79f13a/pynacl-1.6.2-cp314-cp314t-win32.whl", hash = "sha256:a84bf1c20339d06dc0c85d9aea9637a24f718f375d861b2668b2f9f96fa51145", size = 231319, upload-time = "2026-01-01T17:32:12.46Z" }, + { url = "https://files.pythonhosted.org/packages/ce/04/64e9d76646abac2dccf904fccba352a86e7d172647557f35b9fe2a5ee4a1/pynacl-1.6.2-cp314-cp314t-win_amd64.whl", hash = "sha256:320ef68a41c87547c91a8b58903c9caa641ab01e8512ce291085b5fe2fcb7590", size = 244044, upload-time = "2026-01-01T17:32:13.781Z" }, + { url = "https://files.pythonhosted.org/packages/33/33/7873dc161c6a06f43cda13dec67b6fe152cb2f982581151956fa5e5cdb47/pynacl-1.6.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d29bfe37e20e015a7d8b23cfc8bd6aa7909c92a1b8f41ee416bbb3e79ef182b2", size = 188740, upload-time = "2026-01-01T17:32:15.083Z" }, + { url = "https://files.pythonhosted.org/packages/be/7b/4845bbf88e94586ec47a432da4e9107e3fc3ce37eb412b1398630a37f7dd/pynacl-1.6.2-cp38-abi3-macosx_10_10_universal2.whl", hash = "sha256:c949ea47e4206af7c8f604b8278093b674f7c79ed0d4719cc836902bf4517465", size = 388458, upload-time = "2026-01-01T17:32:16.829Z" }, + { url = "https://files.pythonhosted.org/packages/1e/b4/e927e0653ba63b02a4ca5b4d852a8d1d678afbf69b3dbf9c4d0785ac905c/pynacl-1.6.2-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8845c0631c0be43abdd865511c41eab235e0be69c81dc66a50911594198679b0", size = 800020, upload-time = "2026-01-01T17:32:18.34Z" }, + { url = "https://files.pythonhosted.org/packages/7f/81/d60984052df5c97b1d24365bc1e30024379b42c4edcd79d2436b1b9806f2/pynacl-1.6.2-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:22de65bb9010a725b0dac248f353bb072969c94fa8d6b1f34b87d7953cf7bbe4", size = 1399174, upload-time = "2026-01-01T17:32:20.239Z" }, + { url = "https://files.pythonhosted.org/packages/68/f7/322f2f9915c4ef27d140101dd0ed26b479f7e6f5f183590fd32dfc48c4d3/pynacl-1.6.2-cp38-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:46065496ab748469cdd999246d17e301b2c24ae2fdf739132e580a0e94c94a87", size = 835085, upload-time = "2026-01-01T17:32:22.24Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d0/f301f83ac8dbe53442c5a43f6a39016f94f754d7a9815a875b65e218a307/pynacl-1.6.2-cp38-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a66d6fb6ae7661c58995f9c6435bda2b1e68b54b598a6a10247bfcdadac996c", size = 1437614, upload-time = "2026-01-01T17:32:23.766Z" }, + { url = "https://files.pythonhosted.org/packages/c4/58/fc6e649762b029315325ace1a8c6be66125e42f67416d3dbd47b69563d61/pynacl-1.6.2-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:26bfcd00dcf2cf160f122186af731ae30ab120c18e8375684ec2670dccd28130", size = 818251, upload-time = "2026-01-01T17:32:25.69Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a8/b917096b1accc9acd878819a49d3d84875731a41eb665f6ebc826b1af99e/pynacl-1.6.2-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c8a231e36ec2cab018c4ad4358c386e36eede0319a0c41fed24f840b1dac59f6", size = 1402859, upload-time = "2026-01-01T17:32:27.215Z" }, + { url = "https://files.pythonhosted.org/packages/85/42/fe60b5f4473e12c72f977548e4028156f4d340b884c635ec6b063fe7e9a5/pynacl-1.6.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:68be3a09455743ff9505491220b64440ced8973fe930f270c8e07ccfa25b1f9e", size = 791926, upload-time = "2026-01-01T17:32:29.314Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f9/e40e318c604259301cc091a2a63f237d9e7b424c4851cafaea4ea7c4834e/pynacl-1.6.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:8b097553b380236d51ed11356c953bf8ce36a29a3e596e934ecabe76c985a577", size = 1363101, upload-time = "2026-01-01T17:32:31.263Z" }, + { url = "https://files.pythonhosted.org/packages/48/47/e761c254f410c023a469284a9bc210933e18588ca87706ae93002c05114c/pynacl-1.6.2-cp38-abi3-win32.whl", hash = "sha256:5811c72b473b2f38f7e2a3dc4f8642e3a3e9b5e7317266e4ced1fba85cae41aa", size = 227421, upload-time = "2026-01-01T17:32:33.076Z" }, + { url = "https://files.pythonhosted.org/packages/41/ad/334600e8cacc7d86587fe5f565480fde569dfb487389c8e1be56ac21d8ac/pynacl-1.6.2-cp38-abi3-win_amd64.whl", hash = "sha256:62985f233210dee6548c223301b6c25440852e13d59a8b81490203c3227c5ba0", size = 239754, upload-time = "2026-01-01T17:32:34.557Z" }, + { url = "https://files.pythonhosted.org/packages/29/7d/5945b5af29534641820d3bd7b00962abbbdfee84ec7e19f0d5b3175f9a31/pynacl-1.6.2-cp38-abi3-win_arm64.whl", hash = "sha256:834a43af110f743a754448463e8fd61259cd4ab5bbedcf70f9dabad1d28a394c", size = 184801, upload-time = "2026-01-01T17:32:36.309Z" }, +] + +[[package]] +name = "pyparsing" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, +] + +[[package]] +name = "pyperclip" +version = "1.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/52/d87eba7cb129b81563019d1679026e7a112ef76855d6159d24754dbd2a51/pyperclip-1.11.0.tar.gz", hash = "sha256:244035963e4428530d9e3a6101a1ef97209c6825edab1567beac148ccc1db1b6", size = 12185, upload-time = "2025-09-26T14:40:37.245Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/80/fc9d01d5ed37ba4c42ca2b55b4339ae6e200b456be3a1aaddf4a9fa99b8c/pyperclip-1.11.0-py3-none-any.whl", hash = "sha256:299403e9ff44581cb9ba2ffeed69c7aa96a008622ad0c46cb575ca75b5b84273", size = 11063, upload-time = "2025-09-26T14:40:36.069Z" }, +] + +[[package]] +name = "pytest" +version = "8.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, +] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage", extra = ["toml"] }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/15/da3df99fd551507694a9b01f512a2f6cf1254f33601605843c3775f39460/pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6", size = 63245, upload-time = "2023-05-24T18:44:56.845Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/4b/8b78d126e275efa2379b1c2e09dc52cf70df16fc3b90613ef82531499d73/pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a", size = 21949, upload-time = "2023-05-24T18:44:54.079Z" }, +] + +[[package]] +name = "pytest-httpx" +version = "0.35.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1f/89/5b12b7b29e3d0af3a4b9c071ee92fa25a9017453731a38f08ba01c280f4c/pytest_httpx-0.35.0.tar.gz", hash = "sha256:d619ad5d2e67734abfbb224c3d9025d64795d4b8711116b1a13f72a251ae511f", size = 54146, upload-time = "2024-11-28T19:16:54.237Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/ed/026d467c1853dd83102411a78126b4842618e86c895f93528b0528c7a620/pytest_httpx-0.35.0-py3-none-any.whl", hash = "sha256:ee11a00ffcea94a5cbff47af2114d34c5b231c326902458deed73f9c459fd744", size = 19442, upload-time = "2024-11-28T19:16:52.787Z" }, +] + +[[package]] +name = "pytest-mock" +version = "3.15.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" }, +] + +[[package]] +name = "pytest-sugar" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, + { name = "termcolor" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0b/4e/60fed105549297ba1a700e1ea7b828044842ea27d72c898990510b79b0e2/pytest-sugar-1.1.1.tar.gz", hash = "sha256:73b8b65163ebf10f9f671efab9eed3d56f20d2ca68bda83fa64740a92c08f65d", size = 16533, upload-time = "2025-08-23T12:19:35.737Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/d5/81d38a91c1fdafb6711f053f5a9b92ff788013b19821257c2c38c1e132df/pytest_sugar-1.1.1-py3-none-any.whl", hash = "sha256:2f8319b907548d5b9d03a171515c1d43d2e38e32bd8182a1781eb20b43344cc8", size = 11440, upload-time = "2025-08-23T12:19:34.894Z" }, +] + +[[package]] +name = "pytest-xdist" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, +] + +[[package]] +name = "python-discovery" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/82/bb/93a3e83bdf9322c7e21cafd092e56a4a17c4d8ef4277b6eb01af1a540a6f/python_discovery-1.1.0.tar.gz", hash = "sha256:447941ba1aed8cc2ab7ee3cb91be5fc137c5bdbb05b7e6ea62fbdcb66e50b268", size = 55674, upload-time = "2026-02-26T09:42:49.668Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/54/82a6e2ef37f0f23dccac604b9585bdcbd0698604feb64807dcb72853693e/python_discovery-1.1.0-py3-none-any.whl", hash = "sha256:a162893b8809727f54594a99ad2179d2ede4bf953e12d4c7abc3cc9cdbd1437b", size = 30687, upload-time = "2026-02-26T09:42:48.548Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, +] + +[[package]] +name = "python-gitlab" +version = "3.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "requests" }, + { name = "requests-toolbelt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/53/248b87282df591d74ba3d38c3c3ced2b5087248c0ccfb6b3a947bb1034c3/python-gitlab-3.15.0.tar.gz", hash = "sha256:c9e65eb7612a9fbb8abf0339972eca7fd7a73d4da66c9b446ffe528930aff534", size = 273270, upload-time = "2023-06-09T09:51:31.92Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/51/3c7dd08272658e5490d0c0b6c94af15bd0c0649e7ad23c9ed0db1d276143/python_gitlab-3.15.0-py3-none-any.whl", hash = "sha256:8f8d1c0d387f642eb1ac7bf5e8e0cd8b3dd49c6f34170cee3c7deb7d384611f3", size = 135865, upload-time = "2023-06-09T09:51:29.996Z" }, +] + +[[package]] +name = "python-semantic-release" +version = "7.34.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "click-log" }, + { name = "dotty-dict" }, + { name = "gitpython" }, + { name = "invoke" }, + { name = "packaging" }, + { name = "python-gitlab" }, + { name = "requests" }, + { name = "semver" }, + { name = "tomlkit" }, + { name = "twine" }, + { name = "wheel" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/67/abf0ed527dafc5545b2ae264ec090b9849fac7775c319f0f6da95a50e9b7/python-semantic-release-7.34.6.tar.gz", hash = "sha256:e9b8fb788024ae9510a924136d573588415a16eeca31cc5240f2754a80a2e831", size = 41885, upload-time = "2023-06-17T14:12:17.089Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/53/d9b4c4a811a946489f89b62b02b01e9e456dc8c3bde154a18eac4f1dcbe4/python_semantic_release-7.34.6-py3-none-any.whl", hash = "sha256:7e3969ba4663d9b2087b02bf3ac140e202551377bf045c34e09bfe19753e19ab", size = 55637, upload-time = "2023-06-17T14:12:14.975Z" }, +] + +[[package]] +name = "pywin32" +version = "311" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/40/44efbb0dfbd33aca6a6483191dae0716070ed99e2ecb0c53683f400a0b4f/pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3", size = 8760432, upload-time = "2025-07-14T20:13:05.9Z" }, + { url = "https://files.pythonhosted.org/packages/5e/bf/360243b1e953bd254a82f12653974be395ba880e7ec23e3731d9f73921cc/pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b", size = 9590103, upload-time = "2025-07-14T20:13:07.698Z" }, + { url = "https://files.pythonhosted.org/packages/57/38/d290720e6f138086fb3d5ffe0b6caa019a791dd57866940c82e4eeaf2012/pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b", size = 8778557, upload-time = "2025-07-14T20:13:11.11Z" }, + { url = "https://files.pythonhosted.org/packages/7c/af/449a6a91e5d6db51420875c54f6aff7c97a86a3b13a0b4f1a5c13b988de3/pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151", size = 8697031, upload-time = "2025-07-14T20:13:13.266Z" }, + { url = "https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503", size = 9508308, upload-time = "2025-07-14T20:13:15.147Z" }, + { url = "https://files.pythonhosted.org/packages/44/7b/9c2ab54f74a138c491aba1b1cd0795ba61f144c711daea84a88b63dc0f6c/pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2", size = 8703930, upload-time = "2025-07-14T20:13:16.945Z" }, + { url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" }, + { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, + { url = "https://files.pythonhosted.org/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" }, + { url = "https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" }, + { url = "https://files.pythonhosted.org/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" }, + { url = "https://files.pythonhosted.org/packages/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee", size = 8840714, upload-time = "2025-07-14T20:13:32.449Z" }, + { url = "https://files.pythonhosted.org/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87", size = 9656800, upload-time = "2025-07-14T20:13:34.312Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" }, +] + +[[package]] +name = "pywin32-ctypes" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "questionary" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "prompt-toolkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/c6/a8dbf1edcbc236d93348f6e7c437cf09c7356dd27119fcc3be9d70c93bb1/questionary-1.10.0.tar.gz", hash = "sha256:600d3aefecce26d48d97eee936fdb66e4bc27f934c3ab6dd1e292c4f43946d90", size = 23530, upload-time = "2021-07-15T10:11:01.435Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/00/151ff8314078efa3087c23b4b7c473f08f601dff7c62bfb894dd462e0fc9/questionary-1.10.0-py3-none-any.whl", hash = "sha256:fecfcc8cca110fda9d561cb83f1e97ecbb93c613ff857f655818839dac74ce90", size = 31443, upload-time = "2021-07-15T10:11:00.246Z" }, +] + +[[package]] +name = "readme-renderer" +version = "43.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "docutils" }, + { name = "nh3" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/b5/536c775084d239df6345dccf9b043419c7e3308bc31be4c7882196abc62e/readme_renderer-43.0.tar.gz", hash = "sha256:1818dd28140813509eeed8d62687f7cd4f7bad90d4db586001c5dc09d4fde311", size = 31768, upload-time = "2024-02-26T16:10:59.415Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/be/3ea20dc38b9db08387cf97997a85a7d51527ea2057d71118feb0aa8afa55/readme_renderer-43.0-py3-none-any.whl", hash = "sha256:19db308d86ecd60e5affa3b2a98f017af384678c63c88e5d4556a380e674f3f9", size = 13301, upload-time = "2024-02-26T16:10:57.945Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "requests-toolbelt" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, +] + +[[package]] +name = "rfc3986" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c", size = 49026, upload-time = "2022-01-10T00:52:30.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", size = 31326, upload-time = "2022-01-10T00:52:29.594Z" }, +] + +[[package]] +name = "rich" +version = "14.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", size = 310458, upload-time = "2026-02-19T17:23:13.732Z" }, +] + +[[package]] +name = "ruff" +version = "0.12.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a8/f0/e0965dd709b8cabe6356811c0ee8c096806bb57d20b5019eb4e48a117410/ruff-0.12.12.tar.gz", hash = "sha256:b86cd3415dbe31b3b46a71c598f4c4b2f550346d1ccf6326b347cc0c8fd063d6", size = 5359915, upload-time = "2025-09-04T16:50:18.273Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/09/79/8d3d687224d88367b51c7974cec1040c4b015772bfbeffac95face14c04a/ruff-0.12.12-py3-none-linux_armv6l.whl", hash = "sha256:de1c4b916d98ab289818e55ce481e2cacfaad7710b01d1f990c497edf217dafc", size = 12116602, upload-time = "2025-09-04T16:49:18.892Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c3/6e599657fe192462f94861a09aae935b869aea8a1da07f47d6eae471397c/ruff-0.12.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7acd6045e87fac75a0b0cdedacf9ab3e1ad9d929d149785903cff9bb69ad9727", size = 12868393, upload-time = "2025-09-04T16:49:23.043Z" }, + { url = "https://files.pythonhosted.org/packages/e8/d2/9e3e40d399abc95336b1843f52fc0daaceb672d0e3c9290a28ff1a96f79d/ruff-0.12.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:abf4073688d7d6da16611f2f126be86523a8ec4343d15d276c614bda8ec44edb", size = 12036967, upload-time = "2025-09-04T16:49:26.04Z" }, + { url = "https://files.pythonhosted.org/packages/e9/03/6816b2ed08836be272e87107d905f0908be5b4a40c14bfc91043e76631b8/ruff-0.12.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:968e77094b1d7a576992ac078557d1439df678a34c6fe02fd979f973af167577", size = 12276038, upload-time = "2025-09-04T16:49:29.056Z" }, + { url = "https://files.pythonhosted.org/packages/9f/d5/707b92a61310edf358a389477eabd8af68f375c0ef858194be97ca5b6069/ruff-0.12.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42a67d16e5b1ffc6d21c5f67851e0e769517fb57a8ebad1d0781b30888aa704e", size = 11901110, upload-time = "2025-09-04T16:49:32.07Z" }, + { url = "https://files.pythonhosted.org/packages/9d/3d/f8b1038f4b9822e26ec3d5b49cf2bc313e3c1564cceb4c1a42820bf74853/ruff-0.12.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b216ec0a0674e4b1214dcc998a5088e54eaf39417327b19ffefba1c4a1e4971e", size = 13668352, upload-time = "2025-09-04T16:49:35.148Z" }, + { url = "https://files.pythonhosted.org/packages/98/0e/91421368ae6c4f3765dd41a150f760c5f725516028a6be30e58255e3c668/ruff-0.12.12-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:59f909c0fdd8f1dcdbfed0b9569b8bf428cf144bec87d9de298dcd4723f5bee8", size = 14638365, upload-time = "2025-09-04T16:49:38.892Z" }, + { url = "https://files.pythonhosted.org/packages/74/5d/88f3f06a142f58ecc8ecb0c2fe0b82343e2a2b04dcd098809f717cf74b6c/ruff-0.12.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ac93d87047e765336f0c18eacad51dad0c1c33c9df7484c40f98e1d773876f5", size = 14060812, upload-time = "2025-09-04T16:49:42.732Z" }, + { url = "https://files.pythonhosted.org/packages/13/fc/8962e7ddd2e81863d5c92400820f650b86f97ff919c59836fbc4c1a6d84c/ruff-0.12.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01543c137fd3650d322922e8b14cc133b8ea734617c4891c5a9fccf4bfc9aa92", size = 13050208, upload-time = "2025-09-04T16:49:46.434Z" }, + { url = "https://files.pythonhosted.org/packages/53/06/8deb52d48a9a624fd37390555d9589e719eac568c020b27e96eed671f25f/ruff-0.12.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afc2fa864197634e549d87fb1e7b6feb01df0a80fd510d6489e1ce8c0b1cc45", size = 13311444, upload-time = "2025-09-04T16:49:49.931Z" }, + { url = "https://files.pythonhosted.org/packages/2a/81/de5a29af7eb8f341f8140867ffb93f82e4fde7256dadee79016ac87c2716/ruff-0.12.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0c0945246f5ad776cb8925e36af2438e66188d2b57d9cf2eed2c382c58b371e5", size = 13279474, upload-time = "2025-09-04T16:49:53.465Z" }, + { url = "https://files.pythonhosted.org/packages/7f/14/d9577fdeaf791737ada1b4f5c6b59c21c3326f3f683229096cccd7674e0c/ruff-0.12.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a0fbafe8c58e37aae28b84a80ba1817f2ea552e9450156018a478bf1fa80f4e4", size = 12070204, upload-time = "2025-09-04T16:49:56.882Z" }, + { url = "https://files.pythonhosted.org/packages/77/04/a910078284b47fad54506dc0af13839c418ff704e341c176f64e1127e461/ruff-0.12.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b9c456fb2fc8e1282affa932c9e40f5ec31ec9cbb66751a316bd131273b57c23", size = 11880347, upload-time = "2025-09-04T16:49:59.729Z" }, + { url = "https://files.pythonhosted.org/packages/df/58/30185fcb0e89f05e7ea82e5817b47798f7fa7179863f9d9ba6fd4fe1b098/ruff-0.12.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5f12856123b0ad0147d90b3961f5c90e7427f9acd4b40050705499c98983f489", size = 12891844, upload-time = "2025-09-04T16:50:02.591Z" }, + { url = "https://files.pythonhosted.org/packages/21/9c/28a8dacce4855e6703dcb8cdf6c1705d0b23dd01d60150786cd55aa93b16/ruff-0.12.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:26a1b5a2bf7dd2c47e3b46d077cd9c0fc3b93e6c6cc9ed750bd312ae9dc302ee", size = 13360687, upload-time = "2025-09-04T16:50:05.8Z" }, + { url = "https://files.pythonhosted.org/packages/c8/fa/05b6428a008e60f79546c943e54068316f32ec8ab5c4f73e4563934fbdc7/ruff-0.12.12-py3-none-win32.whl", hash = "sha256:173be2bfc142af07a01e3a759aba6f7791aa47acf3604f610b1c36db888df7b1", size = 12052870, upload-time = "2025-09-04T16:50:09.121Z" }, + { url = "https://files.pythonhosted.org/packages/85/60/d1e335417804df452589271818749d061b22772b87efda88354cf35cdb7a/ruff-0.12.12-py3-none-win_amd64.whl", hash = "sha256:e99620bf01884e5f38611934c09dd194eb665b0109104acae3ba6102b600fd0d", size = 13178016, upload-time = "2025-09-04T16:50:12.559Z" }, + { url = "https://files.pythonhosted.org/packages/28/7e/61c42657f6e4614a4258f1c3b0c5b93adc4d1f8575f5229d1906b483099b/ruff-0.12.12-py3-none-win_arm64.whl", hash = "sha256:2a8199cab4ce4d72d158319b63370abf60991495fb733db96cd923a34c52d093", size = 12256762, upload-time = "2025-09-04T16:50:15.737Z" }, +] + +[[package]] +name = "secretstorage" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "jeepney" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" }, +] + +[[package]] +name = "semver" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/a9/b61190916030ee9af83de342e101f192bbb436c59be20a4cb0cdb7256ece/semver-2.13.0.tar.gz", hash = "sha256:fa0fe2722ee1c3f57eac478820c3a5ae2f624af8264cbdf9000c980ff7f75e3f", size = 45816, upload-time = "2020-10-20T20:16:54.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/70/b84f9944a03964a88031ef6ac219b6c91e8ba2f373362329d8770ef36f02/semver-2.13.0-py2.py3-none-any.whl", hash = "sha256:ced8b23dceb22134307c1b8abfa523da14198793d9787ac838e70e29e77458d4", size = 12901, upload-time = "2020-10-20T20:16:52.583Z" }, +] + +[[package]] +name = "setuptools" +version = "82.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/f3/748f4d6f65d1756b9ae577f329c951cda23fb900e4de9f70900ced962085/setuptools-82.0.0.tar.gz", hash = "sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb", size = 1144893, upload-time = "2026-02-08T15:08:40.206Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/c6/76dc613121b793286a3f91621d7b75a2b493e0390ddca50f11993eadf192/setuptools-82.0.0-py3-none-any.whl", hash = "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0", size = 1003468, upload-time = "2026-02-08T15:08:38.723Z" }, +] + +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, +] + +[[package]] +name = "smmap" +version = "5.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/44/cd/a040c4b3119bbe532e5b0732286f805445375489fceaec1f48306068ee3b/smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5", size = 22329, upload-time = "2025-01-02T07:14:40.909Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e", size = 24303, upload-time = "2025-01-02T07:14:38.724Z" }, +] + +[[package]] +name = "snowballstemmer" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575, upload-time = "2025-05-09T16:34:51.843Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, +] + +[[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, upload-time = "2021-05-16T22:03:42.897Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, +] + +[[package]] +name = "soupsieve" +version = "2.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, +] + +[[package]] +name = "sphinx" +version = "6.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "alabaster" }, + { name = "babel" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "docutils" }, + { name = "imagesize" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pygments" }, + { name = "requests" }, + { name = "snowballstemmer" }, + { name = "sphinxcontrib-applehelp" }, + { name = "sphinxcontrib-devhelp" }, + { name = "sphinxcontrib-htmlhelp" }, + { name = "sphinxcontrib-jsmath" }, + { name = "sphinxcontrib-qthelp" }, + { name = "sphinxcontrib-serializinghtml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0f/6d/392defcc95ca48daf62aecb89550143e97a4651275e62a3d7755efe35a3a/Sphinx-6.2.1.tar.gz", hash = "sha256:6d56a34697bb749ffa0152feafc4b19836c755d90a7c59b72bc7dfd371b9cc6b", size = 6681092, upload-time = "2023-04-25T11:01:40.914Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/d8/45ba6097c39ba44d9f0e1462fb232e13ca4ddb5aea93a385dcfa964687da/sphinx-6.2.1-py3-none-any.whl", hash = "sha256:97787ff1fa3256a3eef9eda523a63dbf299f7b47e053cfcf684a1c2a8380c912", size = 3024615, upload-time = "2023-04-25T11:01:08.562Z" }, +] + +[[package]] +name = "sphinx-click" +version = "4.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "docutils" }, + { name = "sphinx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/bf/8e5c3e7865d909a64ed2bd89dcc835f3c542fec857c8bdf38ee8b682af14/sphinx-click-4.4.0.tar.gz", hash = "sha256:cc67692bd28f482c7f01531c61b64e9d2f069bfcf3d24cbbb51d4a84a749fa48", size = 25564, upload-time = "2022-12-06T13:00:57.766Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/cd/00689d6d6e20159509499c79b76c143a2ac5fdcd5c44089119e47e3d674d/sphinx_click-4.4.0-py3-none-any.whl", hash = "sha256:2821c10a68fc9ee6ce7c92fad26540d8d8c8f45e6d7258f0e4fb7529ae8fab49", size = 9289, upload-time = "2022-12-06T13:00:56.496Z" }, +] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, +] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" }, +] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, +] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" }, +] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" }, +] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, +] + +[[package]] +name = "sphinxnotes-markdown-builder" +version = "0.5.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "html2text" }, + { name = "pydash" }, + { name = "sphinx" }, + { name = "unify" }, + { name = "yapf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/75/cb8db5a62f39dd5d05210dafea1364fdbe49750839e10cdc9c122b34bfca/sphinxnotes-markdown-builder-0.5.7.tar.gz", hash = "sha256:ad3e88fa1052d1a9bc4b75d7ae389ce51ffa896963bb19643e01b9120ca17ee9", size = 17901, upload-time = "2023-12-24T03:37:44.053Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/1a/379ffb196cb026c7d7bbe459f462bf12b482b75abe9405f81dea16c1d612/sphinxnotes_markdown_builder-0.5.7-py2.py3-none-any.whl", hash = "sha256:e1c49c31f72c36b29defc69fb05b7087b736355474b8806c814306ad3b42e2b8", size = 18606, upload-time = "2023-12-24T03:37:42.292Z" }, +] + +[[package]] +name = "termcolor" +version = "3.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/46/79/cf31d7a93a8fdc6aa0fbb665be84426a8c5a557d9240b6239e9e11e35fc5/termcolor-3.3.0.tar.gz", hash = "sha256:348871ca648ec6a9a983a13ab626c0acce02f515b9e1983332b17af7979521c5", size = 14434, upload-time = "2025-12-29T12:55:21.882Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl", hash = "sha256:cf642efadaf0a8ebbbf4bc7a31cec2f9b5f21a9f726f4ccbb08192c9c26f43a5", size = 7734, upload-time = "2025-12-29T12:55:20.718Z" }, +] + +[[package]] +name = "textual" +version = "3.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py", extra = ["linkify", "plugins"] }, + { name = "platformdirs" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/af/83/c99c252c3fad2f7010ceb476a31af042eec71da441ffeef75bb590bc2e9e/textual-3.7.1.tar.gz", hash = "sha256:a76ba0c8a6c194ef24fd5c3681ebfddca55e7127c064a014128c84fbd7f5d271", size = 1604038, upload-time = "2025-07-09T09:04:45.477Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/f1/8929fcce6dc983f7a260d0f3ddd2a69b74ba17383dbe57a7e0a9e085e8be/textual-3.7.1-py3-none-any.whl", hash = "sha256:ab5d153f4f65e77017977fa150d0376409e0acf5f1d2e25e2e4ab9de6c0d61ff", size = 691472, upload-time = "2025-07-09T09:04:43.626Z" }, +] + +[[package]] +name = "tomli" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/d9/3dc2289e1f3b32eb19b9785b6a006b28ee99acb37d1d47f78d4c10e28bf8/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867", size = 153663, upload-time = "2026-01-11T11:21:45.27Z" }, + { url = "https://files.pythonhosted.org/packages/51/32/ef9f6845e6b9ca392cd3f64f9ec185cc6f09f0a2df3db08cbe8809d1d435/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9", size = 148469, upload-time = "2026-01-11T11:21:46.873Z" }, + { url = "https://files.pythonhosted.org/packages/d6/c2/506e44cce89a8b1b1e047d64bd495c22c9f71f21e05f380f1a950dd9c217/tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95", size = 236039, upload-time = "2026-01-11T11:21:48.503Z" }, + { url = "https://files.pythonhosted.org/packages/b3/40/e1b65986dbc861b7e986e8ec394598187fa8aee85b1650b01dd925ca0be8/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76", size = 243007, upload-time = "2026-01-11T11:21:49.456Z" }, + { url = "https://files.pythonhosted.org/packages/9c/6f/6e39ce66b58a5b7ae572a0f4352ff40c71e8573633deda43f6a379d56b3e/tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d", size = 240875, upload-time = "2026-01-11T11:21:50.755Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ad/cb089cb190487caa80204d503c7fd0f4d443f90b95cf4ef5cf5aa0f439b0/tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576", size = 246271, upload-time = "2026-01-11T11:21:51.81Z" }, + { url = "https://files.pythonhosted.org/packages/0b/63/69125220e47fd7a3a27fd0de0c6398c89432fec41bc739823bcc66506af6/tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a", size = 96770, upload-time = "2026-01-11T11:21:52.647Z" }, + { url = "https://files.pythonhosted.org/packages/1e/0d/a22bb6c83f83386b0008425a6cd1fa1c14b5f3dd4bad05e98cf3dbbf4a64/tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa", size = 107626, upload-time = "2026-01-11T11:21:53.459Z" }, + { url = "https://files.pythonhosted.org/packages/2f/6d/77be674a3485e75cacbf2ddba2b146911477bd887dda9d8c9dfb2f15e871/tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614", size = 94842, upload-time = "2026-01-11T11:21:54.831Z" }, + { url = "https://files.pythonhosted.org/packages/3c/43/7389a1869f2f26dba52404e1ef13b4784b6b37dac93bac53457e3ff24ca3/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", size = 154894, upload-time = "2026-01-11T11:21:56.07Z" }, + { url = "https://files.pythonhosted.org/packages/e9/05/2f9bf110b5294132b2edf13fe6ca6ae456204f3d749f623307cbb7a946f2/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", size = 149053, upload-time = "2026-01-11T11:21:57.467Z" }, + { url = "https://files.pythonhosted.org/packages/e8/41/1eda3ca1abc6f6154a8db4d714a4d35c4ad90adc0bcf700657291593fbf3/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", size = 243481, upload-time = "2026-01-11T11:21:58.661Z" }, + { url = "https://files.pythonhosted.org/packages/d2/6d/02ff5ab6c8868b41e7d4b987ce2b5f6a51d3335a70aa144edd999e055a01/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", size = 251720, upload-time = "2026-01-11T11:22:00.178Z" }, + { url = "https://files.pythonhosted.org/packages/7b/57/0405c59a909c45d5b6f146107c6d997825aa87568b042042f7a9c0afed34/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", size = 247014, upload-time = "2026-01-11T11:22:01.238Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0e/2e37568edd944b4165735687cbaf2fe3648129e440c26d02223672ee0630/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", size = 251820, upload-time = "2026-01-11T11:22:02.727Z" }, + { url = "https://files.pythonhosted.org/packages/5a/1c/ee3b707fdac82aeeb92d1a113f803cf6d0f37bdca0849cb489553e1f417a/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", size = 97712, upload-time = "2026-01-11T11:22:03.777Z" }, + { url = "https://files.pythonhosted.org/packages/69/13/c07a9177d0b3bab7913299b9278845fc6eaaca14a02667c6be0b0a2270c8/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", size = 108296, upload-time = "2026-01-11T11:22:04.86Z" }, + { url = "https://files.pythonhosted.org/packages/18/27/e267a60bbeeee343bcc279bb9e8fbed0cbe224bc7b2a3dc2975f22809a09/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", size = 94553, upload-time = "2026-01-11T11:22:05.854Z" }, + { url = "https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0", size = 154915, upload-time = "2026-01-11T11:22:06.703Z" }, + { url = "https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e", size = 149038, upload-time = "2026-01-11T11:22:07.56Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8a/6d38870bd3d52c8d1505ce054469a73f73a0fe62c0eaf5dddf61447e32fa/tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4", size = 242245, upload-time = "2026-01-11T11:22:08.344Z" }, + { url = "https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e", size = 250335, upload-time = "2026-01-11T11:22:09.951Z" }, + { url = "https://files.pythonhosted.org/packages/a5/3d/4cdb6f791682b2ea916af2de96121b3cb1284d7c203d97d92d6003e91c8d/tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c", size = 245962, upload-time = "2026-01-11T11:22:11.27Z" }, + { url = "https://files.pythonhosted.org/packages/f2/4a/5f25789f9a460bd858ba9756ff52d0830d825b458e13f754952dd15fb7bb/tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f", size = 250396, upload-time = "2026-01-11T11:22:12.325Z" }, + { url = "https://files.pythonhosted.org/packages/aa/2f/b73a36fea58dfa08e8b3a268750e6853a6aac2a349241a905ebd86f3047a/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86", size = 97530, upload-time = "2026-01-11T11:22:13.865Z" }, + { url = "https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87", size = 108227, upload-time = "2026-01-11T11:22:15.224Z" }, + { url = "https://files.pythonhosted.org/packages/22/c3/b386b832f209fee8073c8138ec50f27b4460db2fdae9ffe022df89a57f9b/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132", size = 94748, upload-time = "2026-01-11T11:22:16.009Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c4/84047a97eb1004418bc10bdbcfebda209fca6338002eba2dc27cc6d13563/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", size = 154725, upload-time = "2026-01-11T11:22:17.269Z" }, + { url = "https://files.pythonhosted.org/packages/a8/5d/d39038e646060b9d76274078cddf146ced86dc2b9e8bbf737ad5983609a0/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", size = 148901, upload-time = "2026-01-11T11:22:18.287Z" }, + { url = "https://files.pythonhosted.org/packages/73/e5/383be1724cb30f4ce44983d249645684a48c435e1cd4f8b5cded8a816d3c/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", size = 243375, upload-time = "2026-01-11T11:22:19.154Z" }, + { url = "https://files.pythonhosted.org/packages/31/f0/bea80c17971c8d16d3cc109dc3585b0f2ce1036b5f4a8a183789023574f2/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", size = 250639, upload-time = "2026-01-11T11:22:20.168Z" }, + { url = "https://files.pythonhosted.org/packages/2c/8f/2853c36abbb7608e3f945d8a74e32ed3a74ee3a1f468f1ffc7d1cb3abba6/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", size = 246897, upload-time = "2026-01-11T11:22:21.544Z" }, + { url = "https://files.pythonhosted.org/packages/49/f0/6c05e3196ed5337b9fe7ea003e95fd3819a840b7a0f2bf5a408ef1dad8ed/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", size = 254697, upload-time = "2026-01-11T11:22:23.058Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f5/2922ef29c9f2951883525def7429967fc4d8208494e5ab524234f06b688b/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", size = 98567, upload-time = "2026-01-11T11:22:24.033Z" }, + { url = "https://files.pythonhosted.org/packages/7b/31/22b52e2e06dd2a5fdbc3ee73226d763b184ff21fc24e20316a44ccc4d96b/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", size = 108556, upload-time = "2026-01-11T11:22:25.378Z" }, + { url = "https://files.pythonhosted.org/packages/48/3d/5058dff3255a3d01b705413f64f4306a141a8fd7a251e5a495e3f192a998/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", size = 96014, upload-time = "2026-01-11T11:22:26.138Z" }, + { url = "https://files.pythonhosted.org/packages/b8/4e/75dab8586e268424202d3a1997ef6014919c941b50642a1682df43204c22/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", size = 163339, upload-time = "2026-01-11T11:22:27.143Z" }, + { url = "https://files.pythonhosted.org/packages/06/e3/b904d9ab1016829a776d97f163f183a48be6a4deb87304d1e0116a349519/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", size = 159490, upload-time = "2026-01-11T11:22:28.399Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5a/fc3622c8b1ad823e8ea98a35e3c632ee316d48f66f80f9708ceb4f2a0322/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", size = 269398, upload-time = "2026-01-11T11:22:29.345Z" }, + { url = "https://files.pythonhosted.org/packages/fd/33/62bd6152c8bdd4c305ad9faca48f51d3acb2df1f8791b1477d46ff86e7f8/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", size = 276515, upload-time = "2026-01-11T11:22:30.327Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ff/ae53619499f5235ee4211e62a8d7982ba9e439a0fb4f2f351a93d67c1dd2/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", size = 273806, upload-time = "2026-01-11T11:22:32.56Z" }, + { url = "https://files.pythonhosted.org/packages/47/71/cbca7787fa68d4d0a9f7072821980b39fbb1b6faeb5f5cf02f4a5559fa28/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", size = 281340, upload-time = "2026-01-11T11:22:33.505Z" }, + { url = "https://files.pythonhosted.org/packages/f5/00/d595c120963ad42474cf6ee7771ad0d0e8a49d0f01e29576ee9195d9ecdf/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087", size = 108106, upload-time = "2026-01-11T11:22:34.451Z" }, + { url = "https://files.pythonhosted.org/packages/de/69/9aa0c6a505c2f80e519b43764f8b4ba93b5a0bbd2d9a9de6e2b24271b9a5/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", size = 120504, upload-time = "2026-01-11T11:22:35.764Z" }, + { url = "https://files.pythonhosted.org/packages/b3/9f/f1668c281c58cfae01482f7114a4b88d345e4c140386241a1a24dcc9e7bc/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", size = 99561, upload-time = "2026-01-11T11:22:36.624Z" }, + { url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" }, +] + +[[package]] +name = "tomli-w" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, +] + +[[package]] +name = "tomlkit" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/af/14b24e41977adb296d6bd1fb59402cf7d60ce364f90c890bd2ec65c43b5a/tomlkit-0.14.0.tar.gz", hash = "sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064", size = 187167, upload-time = "2026-01-13T01:14:53.304Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl", hash = "sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680", size = 39310, upload-time = "2026-01-13T01:14:51.965Z" }, +] + +[[package]] +name = "tqdm" +version = "4.67.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, +] + +[[package]] +name = "twine" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, + { name = "importlib-metadata" }, + { name = "keyring" }, + { name = "pkginfo" }, + { name = "readme-renderer" }, + { name = "requests" }, + { name = "requests-toolbelt" }, + { name = "rfc3986" }, + { name = "tqdm" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d1/3e/ce331d7e215abdc16c53e65f8506bfccf4840ce191b709a37b8c83cc32c7/twine-3.8.0.tar.gz", hash = "sha256:8efa52658e0ae770686a13b675569328f1fba9837e5de1867bfe5f46a9aefe19", size = 214568, upload-time = "2022-02-02T18:50:23.428Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/74/ea7dfb86223695fd8efa256a24d1520729dde79a4e628ee6879f0f136d40/twine-3.8.0-py3-none-any.whl", hash = "sha256:d0550fca9dc19f3d5e8eadfce0c227294df0a2a951251a4385797c8a6198b7c8", size = 36057, upload-time = "2022-02-02T18:50:21.723Z" }, +] + +[[package]] +name = "types-pyyaml" +version = "6.0.12.20250915" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/69/3c51b36d04da19b92f9e815be12753125bd8bc247ba0470a982e6979e71c/types_pyyaml-6.0.12.20250915.tar.gz", hash = "sha256:0f8b54a528c303f0e6f7165687dd33fafa81c807fcac23f632b63aa624ced1d3", size = 17522, upload-time = "2025-09-15T03:01:00.728Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/e0/1eed384f02555dde685fff1a1ac805c1c7dcb6dd019c916fe659b1c1f9ec/types_pyyaml-6.0.12.20250915-py3-none-any.whl", hash = "sha256:e7d4d9e064e89a3b3cae120b4990cd370874d2bf12fa5f46c97018dd5d3c9ab6", size = 20338, upload-time = "2025-09-15T03:00:59.218Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "typing-validation" +version = "1.2.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ba/c0/374639373a99b62f51c3204521235906dca1ed1886e73f65d6664465b187/typing_validation-1.2.12.tar.gz", hash = "sha256:7ea9463a18bd04922e799cac1954f687e68e9564773f81db491536852ffe1d54", size = 774523, upload-time = "2025-03-18T14:54:49.4Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/7b/29a088c5be56f40e0b1e611c460681f411ce79f0083d2cd3b233a35b7c4d/typing_validation-1.2.12-py3-none-any.whl", hash = "sha256:d68e22a41bf2b98ae91e5d6407db56e9ef83e9e5600164a7aff64aaa082fc232", size = 20657, upload-time = "2025-03-18T14:54:47.529Z" }, +] + +[[package]] +name = "uc-micro-py" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/78/67/9a363818028526e2d4579334460df777115bdec1bb77c08f9db88f6389f2/uc_micro_py-2.0.0.tar.gz", hash = "sha256:c53691e495c8db60e16ffc4861a35469b0ba0821fe409a8a7a0a71864d33a811", size = 6611, upload-time = "2026-03-01T06:31:27.526Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/73/d21edf5b204d1467e06500080a50f79d49ef2b997c79123a536d4a17d97c/uc_micro_py-2.0.0-py3-none-any.whl", hash = "sha256:3603a3859af53e5a39bc7677713c78ea6589ff188d70f4fee165db88e22b242c", size = 6383, upload-time = "2026-03-01T06:31:26.257Z" }, +] + +[[package]] +name = "unify" +version = "0.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "untokenize" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/92/f7ab4a788a3efbf83cddeb0f78595fcddd690ef0f55371a525d0f7c237ad/unify-0.5.tar.gz", hash = "sha256:8ddce812b2457212b7598fe574c9e6eb3ad69710f445391338270c7f8a71723c", size = 4363, upload-time = "2019-08-07T13:46:09.142Z" } + +[[package]] +name = "untokenize" +version = "0.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/46/e7cea8159199096e1df52da20a57a6665da80c37fb8aeb848a3e47442c32/untokenize-0.1.1.tar.gz", hash = "sha256:3865dbbbb8efb4bb5eaa72f1be7f3e0be00ea8b7f125c69cbd1f5fda926f37a2", size = 3099, upload-time = "2014-02-08T16:30:40.631Z" } + +[[package]] +name = "urllib3" +version = "2.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, +] + +[[package]] +name = "virtualenv" +version = "21.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, + { name = "python-discovery" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2f/c9/18d4b36606d6091844daa3bd93cf7dc78e6f5da21d9f21d06c221104b684/virtualenv-21.1.0.tar.gz", hash = "sha256:1990a0188c8f16b6b9cf65c9183049007375b26aad415514d377ccacf1e4fb44", size = 5840471, upload-time = "2026-02-27T08:49:29.702Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/55/896b06bf93a49bec0f4ae2a6f1ed12bd05c8860744ac3a70eda041064e4d/virtualenv-21.1.0-py3-none-any.whl", hash = "sha256:164f5e14c5587d170cf98e60378eb91ea35bf037be313811905d3a24ea33cc07", size = 5825072, upload-time = "2026-02-27T08:49:27.516Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/a2/8e3becb46433538a38726c948d3399905a4c7cabd0df578ede5dc51f0ec2/wcwidth-0.6.0.tar.gz", hash = "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159", size = 159684, upload-time = "2026-02-06T19:19:40.919Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/5a/199c59e0a824a3db2b89c5d2dade7ab5f9624dbf6448dc291b46d5ec94d3/wcwidth-0.6.0-py3-none-any.whl", hash = "sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad", size = 94189, upload-time = "2026-02-06T19:19:39.646Z" }, +] + +[[package]] +name = "wheel" +version = "0.46.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/89/24/a2eb353a6edac9a0303977c4cb048134959dd2a51b48a269dfc9dde00c8a/wheel-0.46.3.tar.gz", hash = "sha256:e3e79874b07d776c40bd6033f8ddf76a7dad46a7b8aa1b2787a83083519a1803", size = 60605, upload-time = "2026-01-22T12:39:49.136Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/22/b76d483683216dde3d67cba61fb2444be8d5be289bf628c13fc0fd90e5f9/wheel-0.46.3-py3-none-any.whl", hash = "sha256:4b399d56c9d9338230118d705d9737a2a468ccca63d5e813e2a4fc7815d8bc4d", size = 30557, upload-time = "2026-01-22T12:39:48.099Z" }, +] + +[[package]] +name = "yapf" +version = "0.43.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/23/97/b6f296d1e9cc1ec25c7604178b48532fa5901f721bcf1b8d8148b13e5588/yapf-0.43.0.tar.gz", hash = "sha256:00d3aa24bfedff9420b2e0d5d9f5ab6d9d4268e72afbf59bb3fa542781d5218e", size = 254907, upload-time = "2024-11-14T00:11:41.584Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/81/6acd6601f61e31cfb8729d3da6d5df966f80f374b78eff83760714487338/yapf-0.43.0-py3-none-any.whl", hash = "sha256:224faffbc39c428cb095818cf6ef5511fdab6f7430a10783fdfb292ccf2852ca", size = 256158, upload-time = "2024-11-14T00:11:39.37Z" }, +] + +[[package]] +name = "zipp" +version = "3.23.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, +] From 3d8c0d395737990616ade800202007a5926d7406 Mon Sep 17 00:00:00 2001 From: David Rojas Date: Wed, 11 Mar 2026 17:31:14 -0500 Subject: [PATCH 12/19] feat(docs): starlight migration (#711) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: decoupling from algosdk; installing latest algokit utils * chore: update to latest alpha 4 with get prefixes stripped from clients * build: bump algokit-utils to 5.0.0a7 * feat(docs): initialize Starlight scaffold in docs/ Bootstrap Astro Starlight using the official template. Adds package.json, tsconfig.json, content.config.ts, and .gitignore for the docs site. Includes remark-github-alerts for callout box support and the AlgoKit favicon. * feat(docs): add astro.config.mjs with sidebar and branding Configure Starlight for algorandfoundation.github.io/algokit-cli/ with full sidebar structure covering tutorials, features, concepts, architecture decisions, and auto-generated CLI reference. Adds cli-reference.css for sphinx-click output styling. * feat(docs): add splash home page * feat(docs): migrate hand-written markdown content to Starlight Move all 44 docs pages into docs/src/content/docs/ with Starlight frontmatter, correct absolute internal links, and updated image paths. Copy all image assets to docs/public/images/. Build produces 46 pages cleanly. * docs: update pyproject.toml poe tasks and dependency groups * chore: fix .gitignore — remove bare *.md and obsolete Sphinx entry * ci: add build-docs composite action * ci: add check-docs workflow * ci: add deploy-docs job to cd.yaml for GitHub Pages * chore: remove obsolete source dirs migrated to Starlight * fix(docs): resolve sphinx-build path * ci: added temp preview docs for pr preview * chore: removed git ignored files * chore: formatted code * fix: add build docs github action * refactor: moved docs deps to the docs group * chore: formatted code * fix: linting errors * chore: formatted code * fix(ci): updated docs command * docs: aligned titles in the sidebar * chore(docs): added bash fencing to code blocks * fix: add private key validation and standardize algokit_common imports * chore: removed unused code and files * fix: lint failure --------- Co-authored-by: Altynbek Orumbayev Co-authored-by: Daniel McGregor --- .github/actions/build-docs/action.yml | 31 + .github/workflows/cd.yaml | 31 + .github/workflows/check-docs.yaml | 14 + .github/workflows/check-python.yaml | 2 +- .github/workflows/pr.yaml | 4 + .gitignore | 3 - .idea/runConfigurations/Run_AlgoKit_CLI.xml | 23 - docs/.gitignore | 23 + docs/astro.config.mjs | 107 + docs/cli/index.md | 1669 ------- docs/cli_build.py | 111 + docs/features/tasks.md | 16 - docs/package.json | 21 + docs/pnpm-lock.yaml | 4409 +++++++++++++++++ docs/public/favicon.svg | 20 + .../modular_templates.jpg | Bin .../scenario_1.jpg | Bin .../scenario_2.jpg | Bin .../2024-01-13_native_binaries/image_1.png | Bin .../2024-01-13_native_binaries/image_2.png | Bin .../images}/algokit-intro-video-thumbnail.jpg | Bin docs/{imgs => public/images}/algokit-map.png | Bin .../images}/algokitartifacts.png | Bin .../images}/algokitcodetour.png | Bin .../images}/algokitplayground.png | Bin docs/{imgs => public/images}/banner.png | Bin .../images}/lifecycle.jpg | Bin docs/{imgs => public/images}/localnet.png | Bin docs/src/content.config.ts | 7 + .../2022-11-14_sandbox-approach.md | 6 +- .../2022-11-22_beaker-testing-strategy.md | 4 +- ...3-01-11_beaker_productionisation_review.md | 6 +- .../2023-01-11_brew_install.md | 4 +- .../2023-01-12_smart-contract-deployment.md | 14 +- .../2023-06-06_frontend-templates.md | 12 +- .../2023-07-19_advanced_generate_command.md | 10 +- .../2024-01-13_native_binaries.md | 8 +- .../2024-01-23_init-wizard-v2.md | 6 +- .../2024-01-31_binary_distribution.md | 8 +- .../2024-03-06_local_dev_ui_packaging.md | 4 +- .../docs/concepts/output-stability.md} | 4 +- docs/src/content/docs/features/compile.md | 170 + .../content/docs}/features/completions.md | 28 +- .../{ => src/content/docs}/features/config.md | 22 +- .../content/docs}/features/dispenser.md | 32 +- docs/src/content/docs/features/doctor.md | 57 + .../content/docs}/features/explore.md | 10 +- docs/src/content/docs/features/generate.md | 181 + docs/{ => src/content/docs}/features/goal.md | 32 +- docs/{ => src/content/docs}/features/init.md | 26 +- .../content/docs}/features/localnet.md | 12 +- .../content/docs/features/overview.md} | 34 +- .../content/docs}/features/project.md | 18 +- .../docs}/features/project/bootstrap.md | 30 +- .../content/docs}/features/project/deploy.md | 38 +- .../content/docs}/features/project/link.md | 16 +- .../content/docs}/features/project/list.md | 14 +- .../content/docs}/features/project/run.md | 20 +- docs/src/content/docs/features/tasks.md | 18 + .../content/docs}/features/tasks/analyze.md | 4 +- .../content/docs}/features/tasks/ipfs.md | 14 +- .../content/docs}/features/tasks/mint.md | 10 +- .../content/docs}/features/tasks/nfd.md | 12 +- .../content/docs}/features/tasks/opt.md | 12 +- .../content/docs}/features/tasks/send.md | 14 +- .../content/docs}/features/tasks/sign.md | 16 +- .../content/docs}/features/tasks/transfer.md | 14 +- .../docs}/features/tasks/vanity_address.md | 18 +- .../content/docs}/features/tasks/wallet.md | 8 +- docs/src/content/docs/index.mdx | 76 + .../docs}/tutorials/algokit-template.md | 6 +- docs/src/content/docs/tutorials/intro.md | 173 + .../docs}/tutorials/smart-contracts.md | 4 +- docs/src/styles/cli-reference.css | 27 + docs/tsconfig.json | 5 + poetry.lock | 3389 +++++++++++++ pyproject.toml | 18 +- src/algokit/core/address_utils.py | 5 + src/algokit/core/tasks/mint/mint.py | 2 +- tests/tasks/test_wallet.py | 2 +- uv.lock | 10 +- 81 files changed, 9213 insertions(+), 1961 deletions(-) create mode 100644 .github/actions/build-docs/action.yml create mode 100644 .github/workflows/check-docs.yaml delete mode 100644 .idea/runConfigurations/Run_AlgoKit_CLI.xml create mode 100644 docs/.gitignore create mode 100644 docs/astro.config.mjs delete mode 100644 docs/cli/index.md create mode 100644 docs/cli_build.py delete mode 100644 docs/features/tasks.md create mode 100644 docs/package.json create mode 100644 docs/pnpm-lock.yaml create mode 100644 docs/public/favicon.svg rename docs/{architecture-decisions/assets => public/images}/2023-06-06_frontend-templates/modular_templates.jpg (100%) rename docs/{architecture-decisions/assets => public/images}/2023-06-06_frontend-templates/scenario_1.jpg (100%) rename docs/{architecture-decisions/assets => public/images}/2023-06-06_frontend-templates/scenario_2.jpg (100%) rename docs/{architecture-decisions/assets => public/images}/2024-01-13_native_binaries/image_1.png (100%) rename docs/{architecture-decisions/assets => public/images}/2024-01-13_native_binaries/image_2.png (100%) rename docs/{imgs => public/images}/algokit-intro-video-thumbnail.jpg (100%) rename docs/{imgs => public/images}/algokit-map.png (100%) rename docs/{imgs => public/images}/algokitartifacts.png (100%) rename docs/{imgs => public/images}/algokitcodetour.png (100%) rename docs/{imgs => public/images}/algokitplayground.png (100%) rename docs/{imgs => public/images}/banner.png (100%) rename docs/{architecture-decisions => public/images}/lifecycle.jpg (100%) rename docs/{imgs => public/images}/localnet.png (100%) create mode 100644 docs/src/content.config.ts rename docs/{ => src/content/docs}/architecture-decisions/2022-11-14_sandbox-approach.md (95%) rename docs/{ => src/content/docs}/architecture-decisions/2022-11-22_beaker-testing-strategy.md (99%) rename docs/{ => src/content/docs}/architecture-decisions/2023-01-11_beaker_productionisation_review.md (99%) rename docs/{ => src/content/docs}/architecture-decisions/2023-01-11_brew_install.md (99%) rename docs/{ => src/content/docs}/architecture-decisions/2023-01-12_smart-contract-deployment.md (97%) rename docs/{ => src/content/docs}/architecture-decisions/2023-06-06_frontend-templates.md (97%) rename docs/{ => src/content/docs}/architecture-decisions/2023-07-19_advanced_generate_command.md (93%) rename docs/{ => src/content/docs}/architecture-decisions/2024-01-13_native_binaries.md (98%) rename docs/{ => src/content/docs}/architecture-decisions/2024-01-23_init-wizard-v2.md (97%) rename docs/{ => src/content/docs}/architecture-decisions/2024-01-31_binary_distribution.md (97%) rename docs/{ => src/content/docs}/architecture-decisions/2024-03-06_local_dev_ui_packaging.md (99%) rename docs/{articles/output_stability.md => src/content/docs/concepts/output-stability.md} (96%) create mode 100644 docs/src/content/docs/features/compile.md rename docs/{ => src/content/docs}/features/completions.md (65%) rename docs/{ => src/content/docs}/features/config.md (80%) rename docs/{ => src/content/docs}/features/dispenser.md (85%) create mode 100644 docs/src/content/docs/features/doctor.md rename docs/{ => src/content/docs}/features/explore.md (56%) create mode 100644 docs/src/content/docs/features/generate.md rename docs/{ => src/content/docs}/features/goal.md (94%) rename docs/{ => src/content/docs}/features/init.md (90%) rename docs/{ => src/content/docs}/features/localnet.md (96%) rename docs/{algokit.md => src/content/docs/features/overview.md} (71%) rename docs/{ => src/content/docs}/features/project.md (88%) rename docs/{ => src/content/docs}/features/project/bootstrap.md (96%) rename docs/{ => src/content/docs}/features/project/deploy.md (90%) rename docs/{ => src/content/docs}/features/project/link.md (88%) rename docs/{ => src/content/docs}/features/project/list.md (90%) rename docs/{ => src/content/docs}/features/project/run.md (95%) create mode 100644 docs/src/content/docs/features/tasks.md rename docs/{ => src/content/docs}/features/tasks/analyze.md (97%) rename docs/{ => src/content/docs}/features/tasks/ipfs.md (87%) rename docs/{ => src/content/docs}/features/tasks/mint.md (95%) rename docs/{ => src/content/docs}/features/tasks/nfd.md (83%) rename docs/{ => src/content/docs}/features/tasks/opt.md (82%) rename docs/{ => src/content/docs}/features/tasks/send.md (82%) rename docs/{ => src/content/docs}/features/tasks/sign.md (86%) rename docs/{ => src/content/docs}/features/tasks/transfer.md (66%) rename docs/{ => src/content/docs}/features/tasks/vanity_address.md (77%) rename docs/{ => src/content/docs}/features/tasks/wallet.md (95%) create mode 100644 docs/src/content/docs/index.mdx rename docs/{ => src/content/docs}/tutorials/algokit-template.md (98%) create mode 100644 docs/src/content/docs/tutorials/intro.md rename docs/{ => src/content/docs}/tutorials/smart-contracts.md (80%) create mode 100644 docs/src/styles/cli-reference.css create mode 100644 docs/tsconfig.json create mode 100644 poetry.lock diff --git a/.github/actions/build-docs/action.yml b/.github/actions/build-docs/action.yml new file mode 100644 index 000000000..0af248b28 --- /dev/null +++ b/.github/actions/build-docs/action.yml @@ -0,0 +1,31 @@ +name: "Build Documentation" +description: "Generate CLI reference via sphinx-click and build Starlight site" + +runs: + using: "composite" + steps: + - name: Setup Python environment + uses: algorandfoundation/algokit-shared-config/.github/actions/setup-algokit-python@main + with: + install-algokit: "false" + + - name: Set up Node.js 22 + uses: actions/setup-node@v4 + with: + node-version: "22" + + - uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: Install docs dependencies + shell: bash + run: cd docs && pnpm install --frozen-lockfile + + - name: Generate CLI reference + shell: bash + run: uv run poe docs-cli + + - name: Build Starlight site + shell: bash + run: cd docs && pnpm run build \ No newline at end of file diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml index ac1224500..cc1891977 100644 --- a/.github/workflows/cd.yaml +++ b/.github/workflows/cd.yaml @@ -159,3 +159,34 @@ jobs: artifactName: algokit-cli release_version: ${{ needs.release.outputs.release_version }} secrets: inherit + + deploy-docs: + name: Deploy Documentation + needs: release + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + concurrency: + group: deploy-docs + cancel-in-progress: true + permissions: + contents: read + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Build documentation + uses: ./.github/actions/build-docs + + - name: Upload to GitHub Pages + uses: actions/upload-pages-artifact@v3 + with: + path: docs/dist + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/check-docs.yaml b/.github/workflows/check-docs.yaml new file mode 100644 index 000000000..2269877bb --- /dev/null +++ b/.github/workflows/check-docs.yaml @@ -0,0 +1,14 @@ +name: Check Documentation + +on: + workflow_call: + +jobs: + check-docs: + runs-on: "ubuntu-latest" + steps: + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Build documentation + uses: ./.github/actions/build-docs \ No newline at end of file diff --git a/.github/workflows/check-python.yaml b/.github/workflows/check-python.yaml index e799e5305..a88ce90e8 100644 --- a/.github/workflows/check-python.yaml +++ b/.github/workflows/check-python.yaml @@ -38,5 +38,5 @@ jobs: - name: Check docs are up to date run: | set -o pipefail - uv run poe docs + uv run poe docs-cli [ $(git status --porcelain docs/ | wc -l) -eq "0" ] diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 5be8dec68..24cd4c7c4 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -17,6 +17,10 @@ jobs: name: Check Python uses: ./.github/workflows/check-python.yaml + pr-docs: + name: Check Docs + uses: ./.github/workflows/check-docs.yaml + pr-build: name: Build & Test Python needs: pr-check diff --git a/.gitignore b/.gitignore index 962bf8de0..02417d5f4 100644 --- a/.gitignore +++ b/.gitignore @@ -172,7 +172,6 @@ cython_debug/ #Sphinx .doctrees/ -docs/cli/temp.md # Miscellaneous ci_token.txt @@ -181,6 +180,4 @@ ci_token.txt temp/ -*.md - mise.toml diff --git a/.idea/runConfigurations/Run_AlgoKit_CLI.xml b/.idea/runConfigurations/Run_AlgoKit_CLI.xml deleted file mode 100644 index c8e1763e0..000000000 --- a/.idea/runConfigurations/Run_AlgoKit_CLI.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..9d60680c9 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,23 @@ +# build output +dist/ +# generated types +.astro/ + +# dependencies +node_modules/ + +# auto-generated CLI reference docs (built by sphinx-click) +src/content/docs/cli/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store \ No newline at end of file diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs new file mode 100644 index 000000000..690dc215b --- /dev/null +++ b/docs/astro.config.mjs @@ -0,0 +1,107 @@ +// @ts-check +import starlight from "@astrojs/starlight"; +import { defineConfig } from "astro/config"; +import remarkGithubAlerts from "remark-github-alerts"; + +export default defineConfig({ + site: "https://algorandfoundation.github.io", + base: "/algokit-cli/", + trailingSlash: "always", + markdown: { + remarkPlugins: [remarkGithubAlerts], + }, + integrations: [ + starlight({ + title: "AlgoKit CLI", + tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 4 }, + customCss: [ + "./src/styles/cli-reference.css", + "remark-github-alerts/styles/github-colors-light.css", + "remark-github-alerts/styles/github-colors-dark-media.css", + "remark-github-alerts/styles/github-base.css", + ], + social: [ + { + icon: "github", + label: "GitHub", + href: "https://github.com/algorandfoundation/algokit-cli", + }, + { + icon: "discord", + label: "Discord", + href: "https://discord.gg/algorand", + }, + ], + sidebar: [ + { label: "Home", link: "/" }, + { + label: "Getting Started", + items: [ + { slug: "tutorials/intro" }, + { slug: "tutorials/smart-contracts" }, + { slug: "tutorials/algokit-template" }, + ], + }, + { + label: "Features", + items: [ + { slug: "features/overview" }, + { slug: "features/init" }, + { slug: "features/localnet" }, + { slug: "features/compile" }, + { slug: "features/generate" }, + { slug: "features/config" }, + { slug: "features/doctor" }, + { slug: "features/explore" }, + { slug: "features/dispenser" }, + { slug: "features/goal" }, + { slug: "features/completions" }, + { + label: "AlgoKit Project", + collapsed: true, + items: [ + { slug: "features/project" }, + { slug: "features/project/bootstrap" }, + { slug: "features/project/deploy" }, + { slug: "features/project/link" }, + { slug: "features/project/list" }, + { slug: "features/project/run" }, + ], + }, + { + label: "AlgoKit Task", + collapsed: true, + items: [ + { slug: "features/tasks" }, + { slug: "features/tasks/analyze" }, + { slug: "features/tasks/ipfs" }, + { slug: "features/tasks/mint" }, + { slug: "features/tasks/nfd" }, + { slug: "features/tasks/opt" }, + { slug: "features/tasks/send" }, + { slug: "features/tasks/sign" }, + { slug: "features/tasks/transfer" }, + { slug: "features/tasks/vanity_address" }, + { slug: "features/tasks/wallet" }, + ], + }, + ], + }, + { + label: "Concepts", + items: [{ slug: "concepts/output-stability" }], + }, + { + label: "Architecture Decisions", + collapsed: true, + autogenerate: { directory: "architecture-decisions" }, + }, + { + label: "CLI Reference", + collapsed: true, + items: [{ slug: "cli", label: "AlgoKit CLI" }], + }, + ], + }), + ], +}); diff --git a/docs/cli/index.md b/docs/cli/index.md deleted file mode 100644 index dd63c6e58..000000000 --- a/docs/cli/index.md +++ /dev/null @@ -1,1669 +0,0 @@ -# AlgoKit CLI Reference Documentation - - -- [algokit](#algokit) - - [Options](#options) - - [--version](#--version) - - [-v, --verbose](#-v---verbose) - - [--color, --no-color](#--color---no-color) - - [--skip-version-check](#--skip-version-check) - - [compile](#compile) - - [Options](#options-1) - - [-v, --version ](#-v---version-) - - [py](#py) - - [Arguments](#arguments) - - [PUYAPY_ARGS](#puyapy_args) - - [python](#python) - - [Arguments](#arguments-1) - - [PUYAPY_ARGS](#puyapy_args-1) - - [ts](#ts) - - [Arguments](#arguments-2) - - [PUYATS_ARGS](#puyats_args) - - [typescript](#typescript) - - [Arguments](#arguments-3) - - [PUYATS_ARGS](#puyats_args-1) - - [completions](#completions) - - [install](#install) - - [Options](#options-2) - - [--shell ](#--shell-) - - [uninstall](#uninstall) - - [Options](#options-3) - - [--shell ](#--shell--1) - - [config](#config) - - [container-engine](#container-engine) - - [Options](#options-4) - - [-f, --force](#-f---force) - - [Arguments](#arguments-4) - - [ENGINE](#engine) - - [js-package-manager](#js-package-manager) - - [Arguments](#arguments-5) - - [PACKAGE_MANAGER](#package_manager) - - [py-package-manager](#py-package-manager) - - [Arguments](#arguments-6) - - [PACKAGE_MANAGER](#package_manager-1) - - [version-prompt](#version-prompt) - - [Arguments](#arguments-7) - - [ENABLE](#enable) - - [dispenser](#dispenser) - - [fund](#fund) - - [Options](#options-5) - - [-r, --receiver ](#-r---receiver-) - - [-a, --amount ](#-a---amount-) - - [--whole-units](#--whole-units) - - [limit](#limit) - - [Options](#options-6) - - [--whole-units](#--whole-units-1) - - [login](#login) - - [Options](#options-7) - - [--ci](#--ci) - - [-o, --output ](#-o---output-) - - [-f, --file ](#-f---file-) - - [logout](#logout) - - [refund](#refund) - - [Options](#options-8) - - [-t, --txID ](#-t---txid-) - - [doctor](#doctor) - - [Options](#options-9) - - [-c, --copy-to-clipboard](#-c---copy-to-clipboard) - - [explore](#explore) - - [Arguments](#arguments-8) - - [NETWORK](#network) - - [generate](#generate) - - [client](#client) - - [Options](#options-10) - - [-o, --output ](#-o---output--1) - - [-l, --language ](#-l---language-) - - [-v, --version ](#-v---version--1) - - [Arguments](#arguments-9) - - [APP_SPEC_PATH_OR_DIR](#app_spec_path_or_dir) - - [ARGS](#args) - - [goal](#goal) - - [Options](#options-11) - - [--console](#--console) - - [--interactive](#--interactive) - - [Arguments](#arguments-10) - - [GOAL_ARGS](#goal_args) - - [init](#init) - - [Options](#options-12) - - [-n, --name ](#-n---name-) - - [-t, --template ](#-t---template-) - - [--template-url ](#--template-url-) - - [--template-url-ref ](#--template-url-ref-) - - [--UNSAFE-SECURITY-accept-template-url](#--unsafe-security-accept-template-url) - - [--git, --no-git](#--git---no-git) - - [--defaults](#--defaults) - - [--bootstrap, --no-bootstrap](#--bootstrap---no-bootstrap) - - [--ide, --no-ide](#--ide---no-ide) - - [--workspace, --no-workspace](#--workspace---no-workspace) - - [-a, --answer ](#-a---answer--) - - [example](#example) - - [Options](#options-13) - - [-l, --list](#-l---list) - - [Arguments](#arguments-11) - - [EXAMPLE_ID](#example_id) - - [localnet](#localnet) - - [codespace](#codespace) - - [Options](#options-14) - - [-m, --machine ](#-m---machine-) - - [-a, --algod-port ](#-a---algod-port-) - - [-i, --indexer-port ](#-i---indexer-port-) - - [-k, --kmd-port ](#-k---kmd-port-) - - [-n, --codespace-name ](#-n---codespace-name-) - - [-r, --repo-url ](#-r---repo-url-) - - [-t, --timeout ](#-t---timeout-) - - [-f, --force](#-f---force-1) - - [config](#config-1) - - [Options](#options-15) - - [-f, --force](#-f---force-2) - - [Arguments](#arguments-12) - - [ENGINE](#engine-1) - - [console](#console) - - [explore](#explore-1) - - [logs](#logs) - - [Options](#options-16) - - [--follow, -f](#--follow--f) - - [--tail ](#--tail-) - - [reset](#reset) - - [Options](#options-17) - - [--update, --no-update](#--update---no-update) - - [-P, --config-dir ](#-p---config-dir-) - - [--check](#--check) - - [start](#start) - - [Options](#options-18) - - [-n, --name ](#-n---name--1) - - [-P, --config-dir ](#-p---config-dir--1) - - [-d, --dev, --no-dev](#-d---dev---no-dev) - - [--force](#--force) - - [--check](#--check-1) - - [status](#status) - - [Options](#options-19) - - [--check](#--check-2) - - [stop](#stop) - - [project](#project) - - [bootstrap](#bootstrap) - - [Options](#options-20) - - [--force](#--force-1) - - [Options](#options-21) - - [--interactive, --no-ci, --non-interactive, --ci](#--interactive---no-ci---non-interactive---ci) - - [-p, --project-name ](#-p---project-name-) - - [-t, --type ](#-t---type-) - - [Options](#options-22) - - [--interactive, --non-interactive, --ci](#--interactive---non-interactive---ci) - - [Options](#options-23) - - [--ci, --no-ci](#--ci---no-ci) - - [Options](#options-24) - - [--ci, --no-ci](#--ci---no-ci-1) - - [deploy](#deploy) - - [Options](#options-25) - - [-C, -c, --command ](#-c--c---command-) - - [--interactive, --non-interactive, --ci](#--interactive---non-interactive---ci-1) - - [-P, --path ](#-p---path-) - - [--deployer ](#--deployer-) - - [--dispenser ](#--dispenser-) - - [-p, --project-name ](#-p---project-name--1) - - [Arguments](#arguments-13) - - [ENVIRONMENT_NAME](#environment_name) - - [EXTRA_ARGS](#extra_args) - - [link](#link) - - [Options](#options-26) - - [-p, --project-name ](#-p---project-name--2) - - [-l, --language ](#-l---language--1) - - [-a, --all](#-a---all) - - [-f, --fail-fast](#-f---fail-fast) - - [-v, --version ](#-v---version--2) - - [list](#list) - - [Arguments](#arguments-14) - - [WORKSPACE_PATH](#workspace_path) - - [run](#run) - - [task](#task) - - [analyze](#analyze) - - [Options](#options-27) - - [-r, --recursive](#-r---recursive) - - [--force](#--force-2) - - [--diff](#--diff) - - [-o, --output ](#-o---output--2) - - [-e, --exclude ](#-e---exclude-) - - [Arguments](#arguments-15) - - [INPUT_PATHS](#input_paths) - - [ipfs](#ipfs) - - [Options](#options-28) - - [-f, --file ](#-f---file--1) - - [-n, --name ](#-n---name--2) - - [mint](#mint) - - [Options](#options-29) - - [--creator ](#--creator-) - - [--name ](#--name-) - - [-u, --unit ](#-u---unit-) - - [-t, --total ](#-t---total-) - - [-d, --decimals ](#-d---decimals-) - - [--nft, --ft](#--nft---ft) - - [-i, --image ](#-i---image-) - - [-m, --metadata ](#-m---metadata-) - - [--mutable, --immutable](#--mutable---immutable) - - [-n, --network ](#-n---network-) - - [nfd-lookup](#nfd-lookup) - - [Options](#options-30) - - [-o, --output ](#-o---output--3) - - [Arguments](#arguments-16) - - [VALUE](#value) - - [opt-in](#opt-in) - - [Options](#options-31) - - [-a, --account ](#-a---account-) - - [-n, --network ](#-n---network--1) - - [Arguments](#arguments-17) - - [ASSET_IDS](#asset_ids) - - [opt-out](#opt-out) - - [Options](#options-32) - - [-a, --account ](#-a---account--1) - - [--all](#--all) - - [-n, --network ](#-n---network--2) - - [Arguments](#arguments-18) - - [ASSET_IDS](#asset_ids-1) - - [send](#send) - - [Options](#options-33) - - [-f, --file ](#-f---file--2) - - [-t, --transaction ](#-t---transaction-) - - [-n, --network ](#-n---network--3) - - [sign](#sign) - - [Options](#options-34) - - [-a, --account ](#-a---account--2) - - [-f, --file ](#-f---file--3) - - [-t, --transaction ](#-t---transaction--1) - - [-o, --output ](#-o---output--4) - - [--force](#--force-3) - - [transfer](#transfer) - - [Options](#options-35) - - [-s, --sender ](#-s---sender-) - - [-r, --receiver ](#-r---receiver--1) - - [--asset, --id ](#--asset---id-) - - [-a, --amount ](#-a---amount--1) - - [--whole-units](#--whole-units-2) - - [-n, --network ](#-n---network--4) - - [vanity-address](#vanity-address) - - [Options](#options-36) - - [-m, --match ](#-m---match-) - - [-o, --output ](#-o---output--5) - - [-a, --alias ](#-a---alias-) - - [--file-path ](#--file-path-) - - [-f, --force](#-f---force-3) - - [Arguments](#arguments-19) - - [KEYWORD](#keyword) - - [wallet](#wallet) - - [Options](#options-37) - - [-a, --address ](#-a---address-) - - [-m, --mnemonic](#-m---mnemonic) - - [-f, --force](#-f---force-4) - - [Arguments](#arguments-20) - - [ALIAS_NAME](#alias_name) - - [Arguments](#arguments-21) - - [ALIAS](#alias) - - [Options](#options-38) - - [-f, --force](#-f---force-5) - - [Arguments](#arguments-22) - - [ALIAS](#alias-1) - - [Options](#options-39) - - [-f, --force](#-f---force-6) - -# algokit - -AlgoKit is your one-stop shop to develop applications on the Algorand blockchain. - -If you are getting started, please see the quick start tutorial: [https://dev.algorand.co/getting-started/algokit-quick-start/](https://dev.algorand.co/getting-started/algokit-quick-start/). - -```shell -algokit [OPTIONS] COMMAND [ARGS]... -``` - -### Options - - -### --version -Show the version and exit. - - -### -v, --verbose -Enable logging of DEBUG messages to the console. - - -### --color, --no-color -Force enable or disable of console output styling. - - -### --skip-version-check -Skip version checking and prompting. - -## compile - -Compile smart contracts and smart signatures written in a supported high-level language -to a format deployable on the Algorand Virtual Machine (AVM). - -```shell -algokit compile [OPTIONS] COMMAND [ARGS]... -``` - -### Options - - -### -v, --version -The compiler version to pin to, for example, 1.0.0. If no version is specified, AlgoKit checks if the compiler is installed and runs the installed version. If the compiler is not installed, AlgoKit runs the latest version. If a version is specified, AlgoKit checks if an installed version matches and runs the installed version. Otherwise, AlgoKit runs the specified version. - -### py - -Compile Algorand Python contract(s) using the PuyaPy compiler. - -```shell -algokit compile py [OPTIONS] [PUYAPY_ARGS]... -``` - -### Arguments - - -### PUYAPY_ARGS -Optional argument(s) - -### python - -Compile Algorand Python contract(s) using the PuyaPy compiler. - -```shell -algokit compile python [OPTIONS] [PUYAPY_ARGS]... -``` - -### Arguments - - -### PUYAPY_ARGS -Optional argument(s) - -### ts - -Compile Algorand TypeScript contract(s) using the PuyaTs compiler. - -```shell -algokit compile ts [OPTIONS] [PUYATS_ARGS]... -``` - -### Arguments - - -### PUYATS_ARGS -Optional argument(s) - -### typescript - -Compile Algorand TypeScript contract(s) using the PuyaTs compiler. - -```shell -algokit compile typescript [OPTIONS] [PUYATS_ARGS]... -``` - -### Arguments - - -### PUYATS_ARGS -Optional argument(s) - -## completions - -Install and Uninstall AlgoKit shell integrations. - -```shell -algokit completions [OPTIONS] COMMAND [ARGS]... -``` - -### install - -Install shell completions, this command will attempt to update the interactive profile script -for the current shell to support algokit completions. To specify a specific shell use --shell. - -```shell -algokit completions install [OPTIONS] -``` - -### Options - - -### --shell -Specify shell to install algokit completions for. - - -* **Options** - - bash | zsh - - -### uninstall - -Uninstall shell completions, this command will attempt to update the interactive profile script -for the current shell to remove any algokit completions that have been added. -To specify a specific shell use --shell. - -```shell -algokit completions uninstall [OPTIONS] -``` - -### Options - - -### --shell -Specify shell to install algokit completions for. - - -* **Options** - - bash | zsh - - -## config - -Configure settings used by AlgoKit - -```shell -algokit config [OPTIONS] COMMAND [ARGS]... -``` - -### container-engine - -Set the default container engine for use by AlgoKit CLI to run LocalNet images. - -```shell -algokit config container-engine [OPTIONS] [[docker|podman]] -``` - -### Options - - -### -f, --force -Skip confirmation prompts. Defaults to 'yes' to all prompts. - -### Arguments - - -### ENGINE -Optional argument - -### js-package-manager - -Set the default JavaScript package manager for use by AlgoKit CLI. - -```shell -algokit config js-package-manager [OPTIONS] [[npm|pnpm]] -``` - -### Arguments - - -### PACKAGE_MANAGER -Optional argument - -### py-package-manager - -Set the default Python package manager for use by AlgoKit CLI. - -```shell -algokit config py-package-manager [OPTIONS] [[poetry|uv]] -``` - -### Arguments - - -### PACKAGE_MANAGER -Optional argument - -### version-prompt - -Controls whether AlgoKit checks and prompts for new versions. -Set to [disable] to prevent AlgoKit performing this check permanently, or [enable] to resume checking. -If no argument is provided then outputs current setting. - -Also see --skip-version-check which can be used to disable check for a single command. - -```shell -algokit config version-prompt [OPTIONS] [[enable|disable]] -``` - -### Arguments - - -### ENABLE -Optional argument - -## dispenser - -Interact with the AlgoKit TestNet Dispenser. - -```shell -algokit dispenser [OPTIONS] COMMAND [ARGS]... -``` - -### fund - -Fund your wallet address with TestNet ALGOs. - -```shell -algokit dispenser fund [OPTIONS] -``` - -### Options - - -### -r, --receiver -**Required** Address or alias of the receiver to fund with TestNet ALGOs. - - -### -a, --amount -**Required** Amount to fund. Defaults to microAlgos. - - -### --whole-units -Use whole units (Algos) instead of smallest divisible units (microAlgos). Disabled by default. - -### limit - -Get information about current fund limit on your account. Resets daily. - -```shell -algokit dispenser limit [OPTIONS] -``` - -### Options - - -### --whole-units -Use whole units (Algos) instead of smallest divisible units (microAlgos). Disabled by default. - -### login - -Login to your Dispenser API account. - -```shell -algokit dispenser login [OPTIONS] -``` - -### Options - - -### --ci -Generate an access token for CI. Issued for 30 days. - - -### -o, --output -Choose the output method for the access token. Defaults to stdout. Only applicable when --ci flag is set. - - -* **Options** - - stdout | file - - - -### -f, --file -Output filename where you want to store the generated access token.Defaults to algokit_ci_token.txt. Only applicable when --ci flag is set and --output mode is file. - -### logout - -Logout of your Dispenser API account. - -```shell -algokit dispenser logout [OPTIONS] -``` - -### refund - -Refund ALGOs back to the dispenser wallet address. - -```shell -algokit dispenser refund [OPTIONS] -``` - -### Options - - -### -t, --txID -**Required** Transaction ID of your refund operation. - -## doctor - -Diagnose potential environment issues that may affect AlgoKit. - -Will search the system for AlgoKit dependencies and show their versions, as well as identifying any -potential issues. - -```shell -algokit doctor [OPTIONS] -``` - -### Options - - -### -c, --copy-to-clipboard -Copy the contents of the doctor message (in Markdown format) in your clipboard. - -## explore - -Explore the specified network using lora. - -```shell -algokit explore [OPTIONS] [[localnet|testnet|mainnet]] -``` - -### Arguments - - -### NETWORK -Optional argument - -## generate - -Generate code for an Algorand project. - -```shell -algokit generate [OPTIONS] COMMAND [ARGS]... -``` - -### client - -Create a typed ApplicationClient from an ARC-32/56 application.json - -Supply the path to an application specification file or a directory to recursively search -for "application.json" files - -```shell -algokit generate client [OPTIONS] [APP_SPEC_PATH_OR_DIR] [ARGS]... -``` - -### Options - - -### -o, --output -Path to the output file. The following tokens can be used to substitute into the output path: {contract_name}, {app_spec_dir} - - -### -l, --language -Programming language of the generated client code - - -* **Options** - - python | typescript - - - -### -v, --version -The client generator version to pin to, for example, 1.0.0. If no version is specified, AlgoKit checks if the client generator is installed and runs the installed version. If the client generator is not installed, AlgoKit runs the latest version. If a version is specified, AlgoKit checks if an installed version matches and runs the installed version. Otherwise, AlgoKit runs the specified version. - -### Arguments - - -### APP_SPEC_PATH_OR_DIR -Optional argument - - -### ARGS -Optional argument(s) - -## goal - -Run the Algorand goal CLI against the AlgoKit LocalNet. - -Look at [https://dev.algorand.co/algokit/algokit-cli/goal](https://dev.algorand.co/algokit/algokit-cli/goal) for more information. - -```shell -algokit goal [OPTIONS] [GOAL_ARGS]... -``` - -### Options - - -### --console -Open a Bash console so you can execute multiple goal commands and/or interact with a filesystem. - - -### --interactive -Force running the goal command in interactive mode. - -### Arguments - - -### GOAL_ARGS -Optional argument(s) - -## init - -Initializes a new project from a template, including prompting -for template specific questions to be used in template rendering. - -Templates can be default templates shipped with AlgoKit, or custom -templates in public Git repositories. - -Includes ability to initialise Git repository, run algokit project bootstrap and -automatically open Visual Studio Code. - -This should be run in the parent directory that you want the project folder -created in. - -By default, the --workspace flag creates projects within a workspace structure or integrates them into an existing -one, promoting organized management of multiple projects. Alternatively, -to disable this behavior use the --no-workspace flag, which ensures -the new project is created in a standalone target directory. This is -suitable for isolated projects or when workspace integration is unnecessary. - -```shell -algokit init [OPTIONS] COMMAND [ARGS]... -``` - -### Options - - -### -n, --name -Name of the project / directory / repository to create. - - -### -t, --template -Name of an official template to use. To choose interactively, run this command with no arguments. - - -* **Options** - - tealscript | typescript | python | react | fullstack | base - - - -### --template-url -URL to a git repo with a custom project template. - - -### --template-url-ref -Specific tag, branch or commit to use on git repo specified with --template-url. Defaults to latest. - - -### --UNSAFE-SECURITY-accept-template-url -Accept the specified template URL, acknowledging the security implications of arbitrary code execution trusting an unofficial template. - - -### --git, --no-git -Initialise git repository in directory after creation. - - -### --defaults -Automatically choose default answers without asking when creating this template. - - -### --bootstrap, --no-bootstrap -Whether to run algokit project bootstrap to install and configure the new project's dependencies locally. - - -### --ide, --no-ide -Whether to open an IDE for you if the IDE and IDE config are detected. Supported IDEs: VS Code. - - -### --workspace, --no-workspace -Whether to prefer structuring standalone projects as part of a workspace. An AlgoKit workspace is a conventional project structure that allows managing multiple standalone projects in a monorepo. - - -### -a, --answer -Answers key/value pairs to pass to the template. - -### example - -Initialize a new project from an example template. - -Allows you to quickly create a new project by copying one of the official AlgoKit example templates. -If no example ID is provided, launches an interactive selector to choose from available examples. -The example will be copied to a new directory in your current location. - -```shell -algokit init example [OPTIONS] [EXAMPLE_ID] -``` - -### Options - - -### -l, --list -List all available examples - -### Arguments - - -### EXAMPLE_ID -Optional argument - -## localnet - -Manage the AlgoKit LocalNet. - -```shell -algokit localnet [OPTIONS] COMMAND [ARGS]... -``` - -### codespace - -Manage the AlgoKit LocalNet in GitHub Codespaces. - -```shell -algokit localnet codespace [OPTIONS] -``` - -### Options - - -### -m, --machine -The GitHub Codespace machine type to use. Defaults to base tier. - - -* **Options** - - basicLinux32gb | standardLinux32gb | premiumLinux | largePremiumLinux - - - -### -a, --algod-port -The port for the Algorand daemon. Defaults to 4001. - - -### -i, --indexer-port -The port for the Algorand indexer. Defaults to 8980. - - -### -k, --kmd-port -The port for the Algorand kmd. Defaults to 4002. - - -### -n, --codespace-name -The name of the codespace. Defaults to 'algokit-localnet_timestamp'. - - -### -r, --repo-url -The URL of the repository. Defaults to algokit base template repo. - - -### -t, --timeout -Default max runtime timeout in minutes. Upon hitting the timeout a codespace will be shutdown to prevent accidental spending over GitHub Codespaces quota. Defaults to 4 hours. - - -### -f, --force -Force delete previously used codespaces with {CODESPACE_NAME_PREFIX}\* name prefix and skip prompts. Defaults to explicitly prompting for confirmation. - -### config - -Set the default container engine for use by AlgoKit CLI to run LocalNet images. - -```shell -algokit localnet config [OPTIONS] [[docker|podman]] -``` - -### Options - - -### -f, --force -Skip confirmation prompts. Defaults to 'yes' to all prompts. - -### Arguments - - -### ENGINE -Optional argument - -### console - -Run the Algorand goal CLI against the AlgoKit LocalNet via a Bash console so you can execute multiple goal commands and/or interact with a filesystem. - -```shell -algokit localnet console [OPTIONS] -``` - -### explore - -Explore the AlgoKit LocalNet using lora. - -```shell -algokit localnet explore [OPTIONS] -``` - -### logs - -See the output of the Docker containers. - -```shell -algokit localnet logs [OPTIONS] -``` - -### Options - - -### --follow, -f -Follow log output. - - -### --tail -Number of lines to show from the end of the logs for each container. - - -* **Default** - - `all` - - -### reset - -Reset the AlgoKit LocalNet. - -```shell -algokit localnet reset [OPTIONS] -``` - -### Options - - -### --update, --no-update -Enable or disable updating to the latest available LocalNet version, default: don't update - - -### -P, --config-dir -Specify the custom localnet configuration directory. - - -### --check -Force check the Docker registry for new LocalNet image versions, ignoring the version check cache. - -### start - -Start the AlgoKit LocalNet. - -```shell -algokit localnet start [OPTIONS] -``` - -### Options - - -### -n, --name -Specify a name for a custom LocalNet instance. AlgoKit will not manage the configuration of named LocalNet instances, allowing developers to configure it in any way they need. Defaults to 'sandbox'. - - -### -P, --config-dir -Specify the custom localnet configuration directory. Defaults to '~/.config' on UNIX and 'C:\\Users\\USERNAME\\AppData\\Roaming' on Windows. - - -### -d, --dev, --no-dev -Control whether to launch 'algod' in developer mode or not. Defaults to 'yes'. - - -### --force -Ignore the prompt to stop the LocalNet if it's already running. - - -### --check -Force check the Docker registry for new LocalNet image versions, ignoring the version check cache. - -### status - -Check the status of the AlgoKit LocalNet. - -```shell -algokit localnet status [OPTIONS] -``` - -### Options - - -### --check -Force check the Docker registry for new LocalNet image versions, ignoring the version check cache. - -### stop - -Stop the AlgoKit LocalNet. - -```shell -algokit localnet stop [OPTIONS] -``` - -## project - -Provides a suite of commands for managing your AlgoKit project. -This includes initializing project dependencies, deploying smart contracts, -and executing predefined or custom commands within your project environment. - -```shell -algokit project [OPTIONS] COMMAND [ARGS]... -``` - -### bootstrap - -Expedited initial setup for any developer by installing and configuring dependencies and other -key development environment setup activities. - -```shell -algokit project bootstrap [OPTIONS] COMMAND [ARGS]... -``` - -### Options - - -### --force -Continue even if minimum AlgoKit version is not met - -#### all - -Runs all bootstrap sub-commands in the current directory and immediate sub directories. - -```shell -algokit project bootstrap all [OPTIONS] -``` - -### Options - - -### --interactive, --no-ci, --non-interactive, --ci -Enable/disable interactive prompts. If the CI environment variable is set, defaults to non-interactive - - -### -p, --project-name -(Optional) Projects to execute the command on. Defaults to all projects found in the current directory. - - -### -t, --type -(Optional) Limit execution to specific project types if executing from workspace. - - -* **Options** - - ProjectType.FRONTEND | ProjectType.CONTRACT | ProjectType.BACKEND - - -#### env - -Copies .env.template file to .env in the current working directory and prompts for any unspecified values. - -```shell -algokit project bootstrap env [OPTIONS] -``` - -### Options - - -### --interactive, --non-interactive, --ci -Enable/disable interactive prompts. If the CI environment variable is set, defaults to non-interactive - -#### npm - -Runs npm install in the current working directory to install Node.js dependencies. - -```shell -algokit project bootstrap npm [OPTIONS] -``` - -### Options - - -### --ci, --no-ci -Run 'npm ci' instead of 'npm install' in CI mode (clean install). - -#### pnpm - -Runs pnpm install in the current working directory to install Node.js dependencies. - -```shell -algokit project bootstrap pnpm [OPTIONS] -``` - -### Options - - -### --ci, --no-ci -Run 'pnpm install --frozen-lockfile' instead of 'pnpm install' in CI mode (clean install with frozen lockfile). - -#### poetry - -Installs Python Poetry (if not present) and runs poetry install in the current working directory to install Python dependencies. - -```shell -algokit project bootstrap poetry [OPTIONS] -``` - -#### uv - -Installs UV (if not present) and runs uv sync in the current working directory to install Python dependencies. - -```shell -algokit project bootstrap uv [OPTIONS] -``` - -### deploy - -Deploy smart contracts from AlgoKit compliant repository. - -```shell -algokit project deploy [OPTIONS] [ENVIRONMENT_NAME] [EXTRA_ARGS]... -``` - -### Options - - -### -C, -c, --command -Custom deploy command. If not provided, will load the deploy command from .algokit.toml file. - - -### --interactive, --non-interactive, --ci -Enable/disable interactive prompts. Defaults to non-interactive if the CI environment variable is set. Interactive MainNet deployments prompt for confirmation. - - -### -P, --path -Specify the project directory. If not provided, current working directory will be used. - - -### --deployer -(Optional) Alias of the deployer account. Otherwise, will prompt the deployer mnemonic if specified in .algokit.toml file. - - -### --dispenser -(Optional) Alias of the dispenser account. Otherwise, will prompt the dispenser mnemonic if specified in .algokit.toml file. - - -### -p, --project-name -(Optional) Projects to execute the command on. Defaults to all projects found in the current directory. Option is mutually exclusive with command. - -### Arguments - - -### ENVIRONMENT_NAME -Optional argument - - -### EXTRA_ARGS -Optional argument(s) - -### link - -Automatically invoke 'algokit generate client' on contract projects available in the workspace. -Must be invoked from the root of a standalone 'frontend' typed project. - -```shell -algokit project link [OPTIONS] -``` - -### Options - - -### -p, --project-name -Specify contract projects for the command. Defaults to all in the current workspace. - - -### -l, --language -Programming language of the generated client code - - -* **Options** - - python | typescript - - - -### -a, --all -Link all contract projects with the frontend project Option is mutually exclusive with project_name. - - -### -f, --fail-fast -Exit immediately if at least one client generation process fails - - -### -v, --version -The client generator version to pin to, for example, 1.0.0. If no version is specified, AlgoKit checks if the client generator is installed and runs the installed version. If the client generator is not installed, AlgoKit runs the latest version. If a version is specified, AlgoKit checks if an installed version matches and runs the installed version. Otherwise, AlgoKit runs the specified version. - -### list - -List all projects in the workspace - -```shell -algokit project list [OPTIONS] [WORKSPACE_PATH] -``` - -### Arguments - - -### WORKSPACE_PATH -Optional argument - -### run - -Define custom commands and manage their execution in you projects. - -```shell -algokit project run [OPTIONS] COMMAND [ARGS]... -``` - -## task - -Collection of useful tasks to help you develop on Algorand. - -```shell -algokit task [OPTIONS] COMMAND [ARGS]... -``` - -### analyze - -Analyze TEAL programs for common vulnerabilities using Tealer. This task uses a third party tool to suggest improvements for your TEAL programs, but remember to always test your smart contracts code, follow modern software engineering practices and use the guidelines for smart contract development. This should not be used as a substitute for an actual audit. For full list of available detectors, please refer to [https://github.com/crytic/tealer?tab=readme-ov-file#detectors](https://github.com/crytic/tealer?tab=readme-ov-file#detectors) - -```shell -algokit task analyze [OPTIONS] INPUT_PATHS... -``` - -### Options - - -### -r, --recursive -Recursively search for all TEAL files within the provided directory. - - -### --force -Force verification without the disclaimer confirmation prompt. - - -### --diff -Exit with a non-zero code if differences are found between current and last reports. Reports are generated each run, but with this flag execution fails if the current report doesn't match the last report. Reports are stored in the .algokit/static-analysis/snapshots folder by default. Use --output for a custom path. - - -### -o, --output -Directory path where to store the results of the static analysis. Defaults to .algokit/static-analysis/snapshots. - - -### -e, --exclude -Exclude specific vulnerabilities from the analysis. Supports multiple exclusions in a single run. - -### Arguments - - -### INPUT_PATHS -Required argument(s) - -### ipfs - -Upload files to IPFS using Pinata provider. - -```shell -algokit task ipfs [OPTIONS] COMMAND [ARGS]... -``` - -#### login - -Login to Pinata ipfs provider. You will be prompted for your JWT. - -```shell -algokit task ipfs login [OPTIONS] -``` - -#### logout - -Logout of Pinata ipfs provider. - -```shell -algokit task ipfs logout [OPTIONS] -``` - -#### upload - -Upload a file to Pinata ipfs provider. Please note, max file size is 100MB. - -```shell -algokit task ipfs upload [OPTIONS] -``` - -### Options - - -### -f, --file -**Required** Path to the file to upload. - - -### -n, --name -Human readable name for this upload, for use in file listings. - -### mint - -Mint new fungible or non-fungible assets on Algorand. - -```shell -algokit task mint [OPTIONS] -``` - -### Options - - -### --creator -**Required** Address or alias of the asset creator. - - -### --name -Asset name. - - -### -u, --unit -**Required** Unit name of the asset. - - -### -t, --total -Total supply of the asset. Defaults to 1. - - -### -d, --decimals -Number of decimals. Defaults to 0. - - -### --nft, --ft -Whether the asset should be validated as NFT or FT. Refers to NFT by default and validates canonical -definitions of pure or fractional NFTs as per ARC3 standard. - - -### -i, --image -**Required** Path to the asset image file to be uploaded to IPFS. - - -### -m, --metadata -Path to the ARC19 compliant asset metadata file to be uploaded to IPFS. If not provided, -a default metadata object will be generated automatically based on asset-name, decimals and image. -For more details refer to [https://arc.algorand.foundation/ARCs/arc-0003#json-metadata-file-schema](https://arc.algorand.foundation/ARCs/arc-0003#json-metadata-file-schema). - - -### --mutable, --immutable -Whether the asset should be mutable or immutable. Refers to ARC19 by default. - - -### -n, --network -Network to use. Refers to localnet by default. - - -* **Options** - - localnet | testnet | mainnet - - -### nfd-lookup - -Perform a lookup via NFD domain or address, returning the associated address or domain respectively. - -```shell -algokit task nfd-lookup [OPTIONS] VALUE -``` - -### Options - - -### -o, --output -Output format for NFD API response. Defaults to address|domain resolved. - - -* **Options** - - full | tiny | address - - -### Arguments - - -### VALUE -Required argument - -### opt-in - -Opt-in to an asset(s). This is required before you can receive an asset. Use -n to specify localnet, testnet, or mainnet. To supply multiple asset IDs, separate them with a whitespace. - -```shell -algokit task opt-in [OPTIONS] ASSET_IDS... -``` - -### Options - - -### -a, --account -**Required** Address or alias of the signer account. - - -### -n, --network -Network to use. Refers to localnet by default. - - -* **Options** - - localnet | testnet | mainnet - - -### Arguments - - -### ASSET_IDS -Required argument(s) - -### opt-out - -opt-out of an asset(s). You can only opt out of an asset with a zero balance. Use -n to specify localnet, testnet, or mainnet. To supply multiple asset IDs, separate them with a whitespace. - -```shell -algokit task opt-out [OPTIONS] [ASSET_IDS]... -``` - -### Options - - -### -a, --account -**Required** Address or alias of the signer account. - - -### --all -Opt-out of all assets with zero balance. - - -### -n, --network -Network to use. Refers to localnet by default. - - -* **Options** - - localnet | testnet | mainnet - - -### Arguments - - -### ASSET_IDS -Optional argument(s) - -### send - -Send a signed transaction to the given network. - -```shell -algokit task send [OPTIONS] -``` - -### Options - - -### -f, --file -Single or multiple message pack encoded signed transactions from binary file to send. Option is mutually exclusive with transaction. - - -### -t, --transaction -Base64 encoded signed transaction to send. Option is mutually exclusive with file. - - -### -n, --network -Network to use. Refers to localnet by default. - - -* **Options** - - localnet | testnet | mainnet - - -### sign - -Sign goal clerk compatible Algorand transaction(s). - -```shell -algokit task sign [OPTIONS] -``` - -### Options - - -### -a, --account -**Required** Address or alias of the signer account. - - -### -f, --file -Single or multiple message pack encoded transactions from binary file to sign. Option is mutually exclusive with transaction. - - -### -t, --transaction -Single base64 encoded transaction object to sign. Option is mutually exclusive with file. - - -### -o, --output -The output file path to store signed transaction(s). - - -### --force -Force signing without confirmation. - -### transfer - -Transfer algos or assets from one account to another. - -```shell -algokit task transfer [OPTIONS] -``` - -### Options - - -### -s, --sender -**Required** Address or alias of the sender account. - - -### -r, --receiver -**Required** Address or alias to an account that will receive the asset(s). - - -### --asset, --id -Asset ID to transfer. Defaults to 0 (Algo). - - -### -a, --amount -**Required** Amount to transfer. - - -### --whole-units -Use whole units (Algos | ASAs) instead of smallest divisible units (for example, microAlgos). Disabled by default. - - -### -n, --network -Network to use. Refers to localnet by default. - - -* **Options** - - localnet | testnet | mainnet - - -### vanity-address - -Generate a vanity Algorand address. Your KEYWORD can only include letters A - Z and numbers 2 - 7. -Keeping your KEYWORD under 5 characters will usually result in faster generation. -Note: The longer the KEYWORD, the longer it may take to generate a matching address. -Please be patient if you choose a long keyword. - -```shell -algokit task vanity-address [OPTIONS] KEYWORD -``` - -### Options - - -### -m, --match -Location where the keyword will be included. Default is start. - - -* **Options** - - start | anywhere | end - - - -### -o, --output -How the output will be presented. - - -* **Options** - - stdout | alias | file - - - -### -a, --alias -Alias for the address. Required if output is "alias". - - -### --file-path -File path where to dump the output. Required if output is "file". - - -### -f, --force -Allow overwriting an aliases without confirmation, if output option is 'alias'. - -### Arguments - - -### KEYWORD -Required argument - -### wallet - -Create short aliases for your addresses and accounts on AlgoKit CLI. - -```shell -algokit task wallet [OPTIONS] COMMAND [ARGS]... -``` - -#### add - -Add an address or account to be stored against a named alias (at most 50 aliases). - -```shell -algokit task wallet add [OPTIONS] ALIAS_NAME -``` - -### Options - - -### -a, --address
-**Required** The address of the account. - - -### -m, --mnemonic -If specified then prompt the user for a mnemonic phrase interactively using masked input. - - -### -f, --force -Allow overwriting an existing alias. - -### Arguments - - -### ALIAS_NAME -Required argument - -#### get - -Get an address or account stored against a named alias. - -```shell -algokit task wallet get [OPTIONS] ALIAS -``` - -### Arguments - - -### ALIAS -Required argument - -#### list - -List all addresses and accounts stored against a named alias. - -```shell -algokit task wallet list [OPTIONS] -``` - -#### remove - -Remove an address or account stored against a named alias. - -```shell -algokit task wallet remove [OPTIONS] ALIAS -``` - -### Options - - -### -f, --force -Allow removing an alias without confirmation. - -### Arguments - - -### ALIAS -Required argument - -#### reset - -Remove all aliases. - -```shell -algokit task wallet reset [OPTIONS] -``` - -### Options - - -### -f, --force -Allow removing all aliases without confirmation. diff --git a/docs/cli_build.py b/docs/cli_build.py new file mode 100644 index 000000000..155497a52 --- /dev/null +++ b/docs/cli_build.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +"""Generate CLI reference markdown from Click source using Sphinx + sphinx-click, +then post-process the output for Starlight consumption. + +Run via: uv run poe docs-cli +Or directly: uv run --group docs python docs/cli_build.py +""" + +from __future__ import annotations + +import re +import shutil +import subprocess +import sys +from pathlib import Path + +DOCS_DIR = Path(__file__).resolve().parent +REPO_ROOT = DOCS_DIR.parent +CLI_OUT = DOCS_DIR / "src" / "content" / "docs" / "cli" + + +def _clean_cli_output() -> None: + """Remove previous CLI reference output.""" + print("==> Cleaning previous CLI output...") + if CLI_OUT.exists(): + shutil.rmtree(CLI_OUT) + CLI_OUT.mkdir(parents=True, exist_ok=True) + + +def _run_sphinx_build() -> None: + """Run Sphinx markdown build to generate CLI reference docs.""" + print("==> Running Sphinx + sphinx-click build...") + result = subprocess.run( + [ + "uv", + "run", + "--group", + "docs", + "sphinx-build", + "-b", + "markdown", + "-E", # force fresh build (don't reuse cached environment) + "-q", # quiet + "docs/sphinx", + str(CLI_OUT), + ], + check=False, + cwd=str(REPO_ROOT), + capture_output=True, + text=True, + ) + if result.returncode != 0: + print(f"ERROR: Sphinx build failed (exit code {result.returncode})", file=sys.stderr) + if result.stderr: + print(result.stderr, file=sys.stderr) + if result.stdout: + print(result.stdout, file=sys.stderr) + sys.exit(1) + + +def _remove_sphinx_artifacts() -> None: + """Remove Sphinx build artifacts not needed by Starlight.""" + print("==> Removing Sphinx artifacts...") + for name in [".buildinfo"]: + p = CLI_OUT / name + if p.exists(): + p.unlink() + doctrees = CLI_OUT / ".doctrees" + if doctrees.exists(): + shutil.rmtree(doctrees) + + +def _inject_frontmatter() -> None: + """Inject Starlight frontmatter into the generated CLI reference page.""" + print("==> Injecting Starlight frontmatter...") + index_md = CLI_OUT / "index.md" + if not index_md.exists(): + print("ERROR: Expected index.md not found after Sphinx build.", file=sys.stderr) + sys.exit(1) + + content = index_md.read_text(encoding="utf-8") + + # Extract title from H1 if present, otherwise use a default + title = "AlgoKit CLI Reference" + h1_match = re.match(r"^#\s+(.+)$", content, re.MULTILINE) + if h1_match: + title = h1_match.group(1).strip() + # Strip the H1 line — Starlight renders frontmatter title as H1 + content = re.sub(r"^#\s+[^\n]+\n(\n)?", "", content, count=1) + + escaped_title = title.replace('"', '\\"') + index_md.write_text( + f'---\ntitle: "{escaped_title}"\n---\n\n{content}', + encoding="utf-8", + ) + + +def main() -> None: + """Run the full CLI docs build pipeline.""" + _clean_cli_output() + _run_sphinx_build() + _remove_sphinx_artifacts() + _inject_frontmatter() + + file_count = sum(1 for _ in CLI_OUT.rglob("*.md")) + print(f"==> CLI reference generated at: {CLI_OUT}") + print(f" {file_count} markdown file(s)") + + +if __name__ == "__main__": + main() diff --git a/docs/features/tasks.md b/docs/features/tasks.md deleted file mode 100644 index 9e4c286b6..000000000 --- a/docs/features/tasks.md +++ /dev/null @@ -1,16 +0,0 @@ -# AlgoKit Tasks - -AlgoKit Tasks are a collection of handy tasks that can be used to perform various operations on Algorand blockchain. - -## Features - -- [Wallet Aliasing](./tasks/wallet.md) - Manage your Algorand addresses and accounts effortlessly with the AlgoKit Wallet feature. This feature allows you to create short aliases for your addresses and accounts on AlgoKit CLI. -- [Vanity Address Generation](./tasks/vanity_address.md) - Generate vanity addresses for your Algorand accounts with the AlgoKit Vanity feature. This feature allows you to generate Algorand addresses which contains a specific keyword of your choice. -- [Transfer Assets or Algos](./tasks/transfer.md) - Transfer Algos or Assets from one account to another with the AlgoKit Transfer feature. This feature allows you to transfer Algos or Assets from one account to another on Algorand blockchain. -- [Opt-(in|out) Assets](./tasks/opt.md) - Opt-in or opt-out of Algorand Asset(s). Supports single or multiple assets. -- [Signing transactions](./tasks/sign.md) - Sign goal clerk compatible Algorand transactions. -- [Sending transactions](./tasks/send.md) - Send signed goal clerk compatible Algorand transactions. -- [NFD lookups](./tasks/nfd.md) - Perform a lookup via NFD domain or address, returning the associated address or domain respectively using the AlgoKit CLI. -- [IPFS uploads](./tasks/ipfs.md) - Upload files to IPFS. -- [Asset minting](./tasks/mint.md) - Mint new fungible or non-fungible assets on Algorand. -- [Analyze TEAL code](./tasks/analyze.md) - Analyze TEAL code using [`tealer`](https://github.com/crytic/tealer) integration for common vulnerabilities. diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 000000000..aaf1c26ed --- /dev/null +++ b/docs/package.json @@ -0,0 +1,21 @@ +{ + "name": "docs", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "engines": { + "node": ">=20" + }, + "dependencies": { + "@astrojs/starlight": "^0.37.6", + "astro": "^5.6.1", + "remark-github-alerts": "^0.1.1", + "sharp": "^0.34.2" + } +} diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml new file mode 100644 index 000000000..4baff2b3b --- /dev/null +++ b/docs/pnpm-lock.yaml @@ -0,0 +1,4409 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@astrojs/starlight': + specifier: ^0.37.6 + version: 0.37.7(astro@5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3)) + astro: + specifier: ^5.6.1 + version: 5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3) + remark-github-alerts: + specifier: ^0.1.1 + version: 0.1.1(@types/mdast@4.0.4)(unified@11.0.5) + sharp: + specifier: ^0.34.2 + version: 0.34.5 + +packages: + + '@astrojs/compiler@2.13.1': + resolution: {integrity: sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==} + + '@astrojs/internal-helpers@0.7.6': + resolution: {integrity: sha512-GOle7smBWKfMSP8osUIGOlB5kaHdQLV3foCsf+5Q9Wsuu+C6Fs3Ez/ttXmhjZ1HkSgsogcM1RXSjjOVieHq16Q==} + + '@astrojs/markdown-remark@6.3.11': + resolution: {integrity: sha512-hcaxX/5aC6lQgHeGh1i+aauvSwIT6cfyFjKWvExYSxUhZZBBdvCliOtu06gbQyhbe0pGJNoNmqNlQZ5zYUuIyQ==} + + '@astrojs/mdx@4.3.14': + resolution: {integrity: sha512-FBrqJQORVm+rkRa2TS5CjU9PBA6hkhrwLVBSS9A77gN2+iehvjq1w6yya/d0YKC7osiVorKkr3Qd9wNbl0ZkGA==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + peerDependencies: + astro: ^5.0.0 + + '@astrojs/prism@3.3.0': + resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + + '@astrojs/sitemap@3.7.1': + resolution: {integrity: sha512-IzQqdTeskaMX+QDZCzMuJIp8A8C1vgzMBp/NmHNnadepHYNHcxQdGLQZYfkbd2EbRXUfOS+UDIKx8sKg0oWVdw==} + + '@astrojs/starlight@0.37.7': + resolution: {integrity: sha512-KyBnou8aKIlPJUSNx6a1SN7XyH22oj/VAvTGC+Edld4Bnei1A//pmCRTBvSrSeoGrdUjK0ErFUfaEhhO1bPfDg==} + peerDependencies: + astro: ^5.5.0 + + '@astrojs/telemetry@3.3.0': + resolution: {integrity: sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.0': + resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@capsizecss/unpack@4.0.0': + resolution: {integrity: sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==} + engines: {node: '>=18'} + + '@ctrl/tinycolor@4.2.0': + resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} + engines: {node: '>=14'} + + '@emnapi/runtime@1.8.1': + resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} + + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.27.3': + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.27.3': + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.27.3': + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.27.3': + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.27.3': + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.3': + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.27.3': + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.3': + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.27.3': + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.27.3': + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.27.3': + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.27.3': + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.27.3': + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.27.3': + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.3': + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.27.3': + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.27.3': + resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-arm64@0.27.3': + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.3': + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-arm64@0.27.3': + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.3': + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/openharmony-arm64@0.27.3': + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.27.3': + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.27.3': + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.27.3': + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.27.3': + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@expressive-code/core@0.41.7': + resolution: {integrity: sha512-ck92uZYZ9Wba2zxkiZLsZGi9N54pMSAVdrI9uW3Oo9AtLglD5RmrdTwbYPCT2S/jC36JGB2i+pnQtBm/Ib2+dg==} + + '@expressive-code/plugin-frames@0.41.7': + resolution: {integrity: sha512-diKtxjQw/979cTglRFaMCY/sR6hWF0kSMg8jsKLXaZBSfGS0I/Hoe7Qds3vVEgeoW+GHHQzMcwvgx/MOIXhrTA==} + + '@expressive-code/plugin-shiki@0.41.7': + resolution: {integrity: sha512-DL605bLrUOgqTdZ0Ot5MlTaWzppRkzzqzeGEu7ODnHF39IkEBbFdsC7pbl3LbUQ1DFtnfx6rD54k/cdofbW6KQ==} + + '@expressive-code/plugin-text-markers@0.41.7': + resolution: {integrity: sha512-Ewpwuc5t6eFdZmWlFyeuy3e1PTQC0jFvw2Q+2bpcWXbOZhPLsT7+h8lsSIJxb5mS7wZko7cKyQ2RLYDyK6Fpmw==} + + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.4': + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-arm@1.2.4': + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-ppc64@1.2.4': + resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-riscv64@1.2.4': + resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-s390x@1.2.4': + resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-x64@1.2.4': + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-linux-arm64@0.34.5': + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-arm@0.34.5': + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-ppc64@0.34.5': + resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-riscv64@0.34.5': + resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-s390x@0.34.5': + resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-x64@0.34.5': + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-linuxmusl-arm64@0.34.5': + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-linuxmusl-x64@0.34.5': + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-wasm32@0.34.5': + resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.5': + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@mdx-js/mdx@3.1.1': + resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==} + + '@oslojs/encoding@1.1.0': + resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + + '@pagefind/darwin-arm64@1.4.0': + resolution: {integrity: sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==} + cpu: [arm64] + os: [darwin] + + '@pagefind/darwin-x64@1.4.0': + resolution: {integrity: sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==} + cpu: [x64] + os: [darwin] + + '@pagefind/default-ui@1.4.0': + resolution: {integrity: sha512-wie82VWn3cnGEdIjh4YwNESyS1G6vRHwL6cNjy9CFgNnWW/PGRjsLq300xjVH5sfPFK3iK36UxvIBymtQIEiSQ==} + + '@pagefind/freebsd-x64@1.4.0': + resolution: {integrity: sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==} + cpu: [x64] + os: [freebsd] + + '@pagefind/linux-arm64@1.4.0': + resolution: {integrity: sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==} + cpu: [arm64] + os: [linux] + + '@pagefind/linux-x64@1.4.0': + resolution: {integrity: sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==} + cpu: [x64] + os: [linux] + + '@pagefind/windows-x64@1.4.0': + resolution: {integrity: sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==} + cpu: [x64] + os: [win32] + + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.59.0': + resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.59.0': + resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.59.0': + resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.59.0': + resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.59.0': + resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.59.0': + resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.59.0': + resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.59.0': + resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.59.0': + resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.59.0': + resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.59.0': + resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.59.0': + resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.59.0': + resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.59.0': + resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} + cpu: [x64] + os: [win32] + + '@shikijs/core@3.23.0': + resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==} + + '@shikijs/engine-javascript@3.23.0': + resolution: {integrity: sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==} + + '@shikijs/engine-oniguruma@3.23.0': + resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==} + + '@shikijs/langs@3.23.0': + resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==} + + '@shikijs/themes@3.23.0': + resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} + + '@shikijs/types@3.23.0': + resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/js-yaml@4.0.9': + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/nlcst@2.0.3': + resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} + + '@types/node@24.12.0': + resolution: {integrity: sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==} + + '@types/sax@1.2.7': + resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} + + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-iterate@2.0.1: + resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} + + astring@1.9.0: + resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} + hasBin: true + + astro-expressive-code@0.41.7: + resolution: {integrity: sha512-hUpogGc6DdAd+I7pPXsctyYPRBJDK7Q7d06s4cyP0Vz3OcbziP3FNzN0jZci1BpCvLn9675DvS7B9ctKKX64JQ==} + peerDependencies: + astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta + + astro@5.18.1: + resolution: {integrity: sha512-m4VWilWZ+Xt6NPoYzC4CgGZim/zQUO7WFL0RHCH0AiEavF1153iC3+me2atDvXpf/yX4PyGUeD8wZLq1cirT3g==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} + hasBin: true + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + base-64@1.0.0: + resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} + + bcp-47-match@2.0.3: + resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==} + + bcp-47@2.1.0: + resolution: {integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + boxen@8.0.1: + resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} + engines: {node: '>=18'} + + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + collapse-white-space@2.1.0: + resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + + common-ancestor-path@1.0.1: + resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} + + cookie-es@1.2.2: + resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + crossws@0.3.5: + resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-selector-parser@3.3.0: + resolution: {integrity: sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g==} + + css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.3.0: + resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + deterministic-object-hash@2.0.2: + resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==} + engines: {node: '>=18'} + + devalue@5.6.3: + resolution: {integrity: sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg==} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diff@8.0.3: + resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} + engines: {node: '>=0.3.1'} + + direction@2.0.1: + resolution: {integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==} + hasBin: true + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dset@3.1.4: + resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} + engines: {node: '>=4'} + + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + esast-util-from-estree@2.0.0: + resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} + + esast-util-from-js@2.0.1: + resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==} + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + + esbuild@0.27.3: + resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} + engines: {node: '>=18'} + hasBin: true + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + estree-util-attach-comments@3.0.0: + resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==} + + estree-util-build-jsx@3.0.1: + resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==} + + estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + + estree-util-scope@1.0.0: + resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==} + + estree-util-to-js@2.0.0: + resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==} + + estree-util-visit@2.0.0: + resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + expressive-code@0.41.7: + resolution: {integrity: sha512-2wZjC8OQ3TaVEMcBtYY4Va3lo6J+Ai9jf3d4dbhURMJcU4Pbqe6EcHe424MIZI0VHUA1bR6xdpoHYi3yxokWqA==} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + flattie@1.1.1: + resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} + engines: {node: '>=8'} + + fontace@0.4.1: + resolution: {integrity: sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==} + + fontkitten@1.0.3: + resolution: {integrity: sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==} + engines: {node: '>=20'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + + h3@1.15.6: + resolution: {integrity: sha512-oi15ESLW5LRthZ+qPCi5GNasY/gvynSKUQxgiovrY63bPAtG59wtM+LSrlcwvOHAXzGrXVLnI97brbkdPF9WoQ==} + + hast-util-embedded@3.0.0: + resolution: {integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==} + + hast-util-format@1.1.0: + resolution: {integrity: sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==} + + hast-util-from-html@2.0.3: + resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} + + hast-util-from-parse5@8.0.3: + resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==} + + hast-util-has-property@3.0.0: + resolution: {integrity: sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==} + + hast-util-is-body-ok-link@3.0.1: + resolution: {integrity: sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==} + + hast-util-is-element@3.0.0: + resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} + + hast-util-minify-whitespace@1.0.1: + resolution: {integrity: sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==} + + hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + + hast-util-phrasing@3.0.1: + resolution: {integrity: sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==} + + hast-util-raw@9.1.0: + resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==} + + hast-util-select@6.0.4: + resolution: {integrity: sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==} + + hast-util-to-estree@3.1.3: + resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==} + + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-to-jsx-runtime@2.3.6: + resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} + + hast-util-to-parse5@8.0.1: + resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==} + + hast-util-to-string@3.0.1: + resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==} + + hast-util-to-text@4.0.2: + resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + hastscript@9.0.1: + resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==} + + html-escaper@3.0.3: + resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + html-whitespace-sensitive-tag-names@3.0.1: + resolution: {integrity: sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==} + + http-cache-semantics@4.2.0: + resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + + i18next@23.16.8: + resolution: {integrity: sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==} + + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + + inline-style-parser@0.2.7: + resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} + + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + + is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + + is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + klona@2.0.6: + resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} + engines: {node: '>= 8'} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + lru-cache@11.2.6: + resolution: {integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==} + engines: {node: 20 || >=22} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + magicast@0.5.2: + resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} + + markdown-extensions@2.0.0: + resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} + engines: {node: '>=16'} + + markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + + mdast-util-definitions@6.0.0: + resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} + + mdast-util-directive@3.1.0: + resolution: {integrity: sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==} + + mdast-util-find-and-replace@3.0.2: + resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} + + mdast-util-from-markdown@2.0.3: + resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==} + + mdast-util-gfm-autolink-literal@2.0.1: + resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} + + mdast-util-gfm-footnote@2.1.0: + resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==} + + mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + + mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + + mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + + mdast-util-gfm@3.1.0: + resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} + + mdast-util-mdx-expression@2.0.1: + resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} + + mdast-util-mdx-jsx@3.2.0: + resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} + + mdast-util-mdx@3.0.0: + resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} + + mdast-util-mdxjs-esm@2.0.1: + resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} + + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + + micromark-extension-directive@3.0.2: + resolution: {integrity: sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==} + + micromark-extension-gfm-autolink-literal@2.1.0: + resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} + + micromark-extension-gfm-footnote@2.1.0: + resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} + + micromark-extension-gfm-strikethrough@2.1.0: + resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} + + micromark-extension-gfm-table@2.1.1: + resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} + + micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + + micromark-extension-gfm-task-list-item@2.1.0: + resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} + + micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + + micromark-extension-mdx-expression@3.0.1: + resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==} + + micromark-extension-mdx-jsx@3.0.2: + resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==} + + micromark-extension-mdx-md@2.0.0: + resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} + + micromark-extension-mdxjs-esm@3.0.0: + resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==} + + micromark-extension-mdxjs@3.0.0: + resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-mdx-expression@2.0.3: + resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==} + + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-events-to-acorn@2.0.3: + resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + neotraverse@0.6.18: + resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} + engines: {node: '>= 10'} + + nlcst-to-string@4.0.0: + resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==} + + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + + node-mock-http@1.0.4: + resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + ofetch@1.5.1: + resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} + + ohash@2.0.11: + resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + + oniguruma-parser@0.12.1: + resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==} + + oniguruma-to-es@4.3.4: + resolution: {integrity: sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==} + + p-limit@6.2.0: + resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==} + engines: {node: '>=18'} + + p-queue@8.1.1: + resolution: {integrity: sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==} + engines: {node: '>=18'} + + p-timeout@6.1.4: + resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==} + engines: {node: '>=14.16'} + + package-manager-detector@1.6.0: + resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} + + pagefind@1.4.0: + resolution: {integrity: sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==} + hasBin: true + + parse-entities@4.0.2: + resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} + + parse-latin@7.0.0: + resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + piccolore@0.1.3: + resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss@8.5.8: + resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} + engines: {node: ^10 || ^12 || >=14} + + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + + radix3@1.1.2: + resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + + recma-build-jsx@1.0.0: + resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} + + recma-jsx@1.0.1: + resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + recma-parse@1.0.0: + resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==} + + recma-stringify@1.0.0: + resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.1.0: + resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} + + rehype-expressive-code@0.41.7: + resolution: {integrity: sha512-25f8ZMSF1d9CMscX7Cft0TSQIqdwjce2gDOvQ+d/w0FovsMwrSt3ODP4P3Z7wO1jsIJ4eYyaDRnIR/27bd/EMQ==} + + rehype-format@5.0.1: + resolution: {integrity: sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==} + + rehype-parse@9.0.1: + resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==} + + rehype-raw@7.0.0: + resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} + + rehype-recma@1.0.0: + resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==} + + rehype-stringify@10.0.1: + resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==} + + rehype@13.0.2: + resolution: {integrity: sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==} + + remark-directive@3.0.1: + resolution: {integrity: sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==} + + remark-gfm@4.0.1: + resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} + + remark-github-alerts@0.1.1: + resolution: {integrity: sha512-A0NLfeAuu76ymiGIoEoBcHmqlPcdLFq+FoCGiWlzu8vkyhscyDv+pAkMA9paGr+OHpzpFflZKnsqOCvMESG/Uw==} + peerDependencies: + '@types/mdast': ^4.0.0 + unified: ^11.0.0 + + remark-mdx@3.1.1: + resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==} + + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-rehype@11.1.2: + resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==} + + remark-smartypants@3.0.2: + resolution: {integrity: sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==} + engines: {node: '>=16.0.0'} + + remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + + retext-latin@4.0.0: + resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==} + + retext-smartypants@6.2.0: + resolution: {integrity: sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==} + + retext-stringify@4.0.0: + resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==} + + retext@9.0.0: + resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} + + rollup@4.59.0: + resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + sax@1.5.0: + resolution: {integrity: sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==} + engines: {node: '>=11.0.0'} + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + sharp@0.34.5: + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shiki@3.23.0: + resolution: {integrity: sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + sitemap@9.0.1: + resolution: {integrity: sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==} + engines: {node: '>=20.19.5', npm: '>=10.8.2'} + hasBin: true + + smol-toml@1.6.0: + resolution: {integrity: sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==} + engines: {node: '>= 18'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + stream-replace-string@2.0.0: + resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + style-to-js@1.1.21: + resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==} + + style-to-object@1.0.14: + resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} + + svgo@4.0.1: + resolution: {integrity: sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==} + engines: {node: '>=16'} + hasBin: true + + tiny-inflate@1.0.3: + resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + + tsconfck@3.1.6: + resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.3: + resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + + ultrahtml@1.6.0: + resolution: {integrity: sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==} + + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unifont@0.7.4: + resolution: {integrity: sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==} + + unist-util-find-after@5.0.0: + resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} + + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-modify-children@4.0.0: + resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==} + + unist-util-position-from-estree@2.0.0: + resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-children@3.0.0: + resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + + unstorage@1.17.4: + resolution: {integrity: sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==} + peerDependencies: + '@azure/app-configuration': ^1.8.0 + '@azure/cosmos': ^4.2.0 + '@azure/data-tables': ^13.3.0 + '@azure/identity': ^4.6.0 + '@azure/keyvault-secrets': ^4.9.0 + '@azure/storage-blob': ^12.26.0 + '@capacitor/preferences': ^6 || ^7 || ^8 + '@deno/kv': '>=0.9.0' + '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 + '@planetscale/database': ^1.19.0 + '@upstash/redis': ^1.34.3 + '@vercel/blob': '>=0.27.1' + '@vercel/functions': ^2.2.12 || ^3.0.0 + '@vercel/kv': ^1 || ^2 || ^3 + aws4fetch: ^1.0.20 + db0: '>=0.2.1' + idb-keyval: ^6.2.1 + ioredis: ^5.4.2 + uploadthing: ^7.4.4 + peerDependenciesMeta: + '@azure/app-configuration': + optional: true + '@azure/cosmos': + optional: true + '@azure/data-tables': + optional: true + '@azure/identity': + optional: true + '@azure/keyvault-secrets': + optional: true + '@azure/storage-blob': + optional: true + '@capacitor/preferences': + optional: true + '@deno/kv': + optional: true + '@netlify/blobs': + optional: true + '@planetscale/database': + optional: true + '@upstash/redis': + optional: true + '@vercel/blob': + optional: true + '@vercel/functions': + optional: true + '@vercel/kv': + optional: true + aws4fetch: + optional: true + db0: + optional: true + idb-keyval: + optional: true + ioredis: + optional: true + uploadthing: + optional: true + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vfile-location@5.0.3: + resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} + + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite@6.4.1: + resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitefu@1.1.2: + resolution: {integrity: sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0 + peerDependenciesMeta: + vite: + optional: true + + web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + + which-pm-runs@1.1.0: + resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} + engines: {node: '>=4'} + + widest-line@5.0.0: + resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} + engines: {node: '>=18'} + + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + + xxhash-wasm@1.1.0: + resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yocto-queue@1.2.2: + resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} + engines: {node: '>=12.20'} + + yocto-spinner@0.2.3: + resolution: {integrity: sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==} + engines: {node: '>=18.19'} + + yoctocolors@2.1.2: + resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + engines: {node: '>=18'} + + zod-to-json-schema@3.25.1: + resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} + peerDependencies: + zod: ^3.25 || ^4 + + zod-to-ts@1.2.0: + resolution: {integrity: sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==} + peerDependencies: + typescript: ^4.9.4 || ^5.0.2 + zod: ^3 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@astrojs/compiler@2.13.1': {} + + '@astrojs/internal-helpers@0.7.6': {} + + '@astrojs/markdown-remark@6.3.11': + dependencies: + '@astrojs/internal-helpers': 0.7.6 + '@astrojs/prism': 3.3.0 + github-slugger: 2.0.0 + hast-util-from-html: 2.0.3 + hast-util-to-text: 4.0.2 + import-meta-resolve: 4.2.0 + js-yaml: 4.1.1 + mdast-util-definitions: 6.0.0 + rehype-raw: 7.0.0 + rehype-stringify: 10.0.1 + remark-gfm: 4.0.1 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + remark-smartypants: 3.0.2 + shiki: 3.23.0 + smol-toml: 1.6.0 + unified: 11.0.5 + unist-util-remove-position: 5.0.0 + unist-util-visit: 5.1.0 + unist-util-visit-parents: 6.0.2 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/mdx@4.3.14(astro@5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3))': + dependencies: + '@astrojs/markdown-remark': 6.3.11 + '@mdx-js/mdx': 3.1.1 + acorn: 8.16.0 + astro: 5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3) + es-module-lexer: 1.7.0 + estree-util-visit: 2.0.0 + hast-util-to-html: 9.0.5 + piccolore: 0.1.3 + rehype-raw: 7.0.0 + remark-gfm: 4.0.1 + remark-smartypants: 3.0.2 + source-map: 0.7.6 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/prism@3.3.0': + dependencies: + prismjs: 1.30.0 + + '@astrojs/sitemap@3.7.1': + dependencies: + sitemap: 9.0.1 + stream-replace-string: 2.0.0 + zod: 4.3.6 + + '@astrojs/starlight@0.37.7(astro@5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3))': + dependencies: + '@astrojs/markdown-remark': 6.3.11 + '@astrojs/mdx': 4.3.14(astro@5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3)) + '@astrojs/sitemap': 3.7.1 + '@pagefind/default-ui': 1.4.0 + '@types/hast': 3.0.4 + '@types/js-yaml': 4.0.9 + '@types/mdast': 4.0.4 + astro: 5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3) + astro-expressive-code: 0.41.7(astro@5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3)) + bcp-47: 2.1.0 + hast-util-from-html: 2.0.3 + hast-util-select: 6.0.4 + hast-util-to-string: 3.0.1 + hastscript: 9.0.1 + i18next: 23.16.8 + js-yaml: 4.1.1 + klona: 2.0.6 + magic-string: 0.30.21 + mdast-util-directive: 3.1.0 + mdast-util-to-markdown: 2.1.2 + mdast-util-to-string: 4.0.0 + pagefind: 1.4.0 + rehype: 13.0.2 + rehype-format: 5.0.1 + remark-directive: 3.0.1 + ultrahtml: 1.6.0 + unified: 11.0.5 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/telemetry@3.3.0': + dependencies: + ci-info: 4.4.0 + debug: 4.4.3 + dlv: 1.1.3 + dset: 3.1.4 + is-docker: 3.0.0 + is-wsl: 3.1.1 + which-pm-runs: 1.1.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/parser@7.29.0': + dependencies: + '@babel/types': 7.29.0 + + '@babel/runtime@7.28.6': {} + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@capsizecss/unpack@4.0.0': + dependencies: + fontkitten: 1.0.3 + + '@ctrl/tinycolor@4.2.0': {} + + '@emnapi/runtime@1.8.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/aix-ppc64@0.27.3': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.27.3': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-arm@0.27.3': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/android-x64@0.27.3': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.27.3': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.27.3': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.27.3': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.27.3': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.27.3': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-arm@0.27.3': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.27.3': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.27.3': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.27.3': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.27.3': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.27.3': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.27.3': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/linux-x64@0.27.3': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.27.3': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.27.3': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.27.3': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.27.3': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.27.3': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.27.3': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.27.3': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.27.3': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + + '@esbuild/win32-x64@0.27.3': + optional: true + + '@expressive-code/core@0.41.7': + dependencies: + '@ctrl/tinycolor': 4.2.0 + hast-util-select: 6.0.4 + hast-util-to-html: 9.0.5 + hast-util-to-text: 4.0.2 + hastscript: 9.0.1 + postcss: 8.5.8 + postcss-nested: 6.2.0(postcss@8.5.8) + unist-util-visit: 5.1.0 + unist-util-visit-parents: 6.0.2 + + '@expressive-code/plugin-frames@0.41.7': + dependencies: + '@expressive-code/core': 0.41.7 + + '@expressive-code/plugin-shiki@0.41.7': + dependencies: + '@expressive-code/core': 0.41.7 + shiki: 3.23.0 + + '@expressive-code/plugin-text-markers@0.41.7': + dependencies: + '@expressive-code/core': 0.41.7 + + '@img/colour@1.1.0': {} + + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true + + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true + + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true + + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.8.1 + optional: true + + '@img/sharp-win32-arm64@0.34.5': + optional: true + + '@img/sharp-win32-ia32@0.34.5': + optional: true + + '@img/sharp-win32-x64@0.34.5': + optional: true + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@mdx-js/mdx@3.1.1': + dependencies: + '@types/estree': 1.0.8 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdx': 2.0.13 + acorn: 8.16.0 + collapse-white-space: 2.1.0 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + estree-util-scope: 1.0.0 + estree-walker: 3.0.3 + hast-util-to-jsx-runtime: 2.3.6 + markdown-extensions: 2.0.0 + recma-build-jsx: 1.0.0 + recma-jsx: 1.0.1(acorn@8.16.0) + recma-stringify: 1.0.0 + rehype-recma: 1.0.0 + remark-mdx: 3.1.1 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + source-map: 0.7.6 + unified: 11.0.5 + unist-util-position-from-estree: 2.0.0 + unist-util-stringify-position: 4.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@oslojs/encoding@1.1.0': {} + + '@pagefind/darwin-arm64@1.4.0': + optional: true + + '@pagefind/darwin-x64@1.4.0': + optional: true + + '@pagefind/default-ui@1.4.0': {} + + '@pagefind/freebsd-x64@1.4.0': + optional: true + + '@pagefind/linux-arm64@1.4.0': + optional: true + + '@pagefind/linux-x64@1.4.0': + optional: true + + '@pagefind/windows-x64@1.4.0': + optional: true + + '@rollup/pluginutils@5.3.0(rollup@4.59.0)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.59.0 + + '@rollup/rollup-android-arm-eabi@4.59.0': + optional: true + + '@rollup/rollup-android-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-x64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.59.0': + optional: true + + '@rollup/rollup-openbsd-x64@4.59.0': + optional: true + + '@rollup/rollup-openharmony-arm64@4.59.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.59.0': + optional: true + + '@shikijs/core@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 4.3.4 + + '@shikijs/engine-oniguruma@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/themes@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/types@3.23.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/vscode-textmate@10.0.2': {} + + '@types/debug@4.1.12': + dependencies: + '@types/ms': 2.1.0 + + '@types/estree-jsx@1.0.5': + dependencies: + '@types/estree': 1.0.8 + + '@types/estree@1.0.8': {} + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/js-yaml@4.0.9': {} + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdx@2.0.13': {} + + '@types/ms@2.1.0': {} + + '@types/nlcst@2.0.3': + dependencies: + '@types/unist': 3.0.3 + + '@types/node@24.12.0': + dependencies: + undici-types: 7.16.0 + + '@types/sax@1.2.7': + dependencies: + '@types/node': 24.12.0 + + '@types/unist@2.0.11': {} + + '@types/unist@3.0.3': {} + + '@ungap/structured-clone@1.3.0': {} + + acorn-jsx@5.3.2(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn@8.16.0: {} + + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@6.2.3: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@5.0.2: {} + + argparse@2.0.1: {} + + aria-query@5.3.2: {} + + array-iterate@2.0.1: {} + + astring@1.9.0: {} + + astro-expressive-code@0.41.7(astro@5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3)): + dependencies: + astro: 5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3) + rehype-expressive-code: 0.41.7 + + astro@5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3): + dependencies: + '@astrojs/compiler': 2.13.1 + '@astrojs/internal-helpers': 0.7.6 + '@astrojs/markdown-remark': 6.3.11 + '@astrojs/telemetry': 3.3.0 + '@capsizecss/unpack': 4.0.0 + '@oslojs/encoding': 1.1.0 + '@rollup/pluginutils': 5.3.0(rollup@4.59.0) + acorn: 8.16.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + boxen: 8.0.1 + ci-info: 4.4.0 + clsx: 2.1.1 + common-ancestor-path: 1.0.1 + cookie: 1.1.1 + cssesc: 3.0.0 + debug: 4.4.3 + deterministic-object-hash: 2.0.2 + devalue: 5.6.3 + diff: 8.0.3 + dlv: 1.1.3 + dset: 3.1.4 + es-module-lexer: 1.7.0 + esbuild: 0.27.3 + estree-walker: 3.0.3 + flattie: 1.1.1 + fontace: 0.4.1 + github-slugger: 2.0.0 + html-escaper: 3.0.3 + http-cache-semantics: 4.2.0 + import-meta-resolve: 4.2.0 + js-yaml: 4.1.1 + magic-string: 0.30.21 + magicast: 0.5.2 + mrmime: 2.0.1 + neotraverse: 0.6.18 + p-limit: 6.2.0 + p-queue: 8.1.1 + package-manager-detector: 1.6.0 + piccolore: 0.1.3 + picomatch: 4.0.3 + prompts: 2.4.2 + rehype: 13.0.2 + semver: 7.7.4 + shiki: 3.23.0 + smol-toml: 1.6.0 + svgo: 4.0.1 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tsconfck: 3.1.6(typescript@5.9.3) + ultrahtml: 1.6.0 + unifont: 0.7.4 + unist-util-visit: 5.1.0 + unstorage: 1.17.4 + vfile: 6.0.3 + vite: 6.4.1(@types/node@24.12.0) + vitefu: 1.1.2(vite@6.4.1(@types/node@24.12.0)) + xxhash-wasm: 1.1.0 + yargs-parser: 21.1.1 + yocto-spinner: 0.2.3 + zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) + zod-to-ts: 1.2.0(typescript@5.9.3)(zod@3.25.76) + optionalDependencies: + sharp: 0.34.5 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@types/node' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - db0 + - idb-keyval + - ioredis + - jiti + - less + - lightningcss + - rollup + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - uploadthing + - yaml + + axobject-query@4.1.0: {} + + bail@2.0.2: {} + + base-64@1.0.0: {} + + bcp-47-match@2.0.3: {} + + bcp-47@2.1.0: + dependencies: + is-alphabetical: 2.0.1 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + + boolbase@1.0.0: {} + + boxen@8.0.1: + dependencies: + ansi-align: 3.0.1 + camelcase: 8.0.0 + chalk: 5.6.2 + cli-boxes: 3.0.0 + string-width: 7.2.0 + type-fest: 4.41.0 + widest-line: 5.0.0 + wrap-ansi: 9.0.2 + + camelcase@8.0.0: {} + + ccount@2.0.1: {} + + chalk@5.6.2: {} + + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + character-entities@2.0.2: {} + + character-reference-invalid@2.0.1: {} + + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + + ci-info@4.4.0: {} + + cli-boxes@3.0.0: {} + + clsx@2.1.1: {} + + collapse-white-space@2.1.0: {} + + comma-separated-tokens@2.0.3: {} + + commander@11.1.0: {} + + common-ancestor-path@1.0.1: {} + + cookie-es@1.2.2: {} + + cookie@1.1.1: {} + + crossws@0.3.5: + dependencies: + uncrypto: 0.1.3 + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-selector-parser@3.3.0: {} + + css-tree@2.2.1: + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.2.1 + + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + + css-what@6.2.2: {} + + cssesc@3.0.0: {} + + csso@5.0.5: + dependencies: + css-tree: 2.2.1 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decode-named-character-reference@1.3.0: + dependencies: + character-entities: 2.0.2 + + defu@6.1.4: {} + + dequal@2.0.3: {} + + destr@2.0.5: {} + + detect-libc@2.1.2: {} + + deterministic-object-hash@2.0.2: + dependencies: + base-64: 1.0.0 + + devalue@5.6.3: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + diff@8.0.3: {} + + direction@2.0.1: {} + + dlv@1.1.3: {} + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dset@3.1.4: {} + + emoji-regex@10.6.0: {} + + emoji-regex@8.0.0: {} + + entities@4.5.0: {} + + entities@6.0.1: {} + + es-module-lexer@1.7.0: {} + + esast-util-from-estree@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + unist-util-position-from-estree: 2.0.0 + + esast-util-from-js@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + acorn: 8.16.0 + esast-util-from-estree: 2.0.0 + vfile-message: 4.0.3 + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + + esbuild@0.27.3: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.3 + '@esbuild/android-arm': 0.27.3 + '@esbuild/android-arm64': 0.27.3 + '@esbuild/android-x64': 0.27.3 + '@esbuild/darwin-arm64': 0.27.3 + '@esbuild/darwin-x64': 0.27.3 + '@esbuild/freebsd-arm64': 0.27.3 + '@esbuild/freebsd-x64': 0.27.3 + '@esbuild/linux-arm': 0.27.3 + '@esbuild/linux-arm64': 0.27.3 + '@esbuild/linux-ia32': 0.27.3 + '@esbuild/linux-loong64': 0.27.3 + '@esbuild/linux-mips64el': 0.27.3 + '@esbuild/linux-ppc64': 0.27.3 + '@esbuild/linux-riscv64': 0.27.3 + '@esbuild/linux-s390x': 0.27.3 + '@esbuild/linux-x64': 0.27.3 + '@esbuild/netbsd-arm64': 0.27.3 + '@esbuild/netbsd-x64': 0.27.3 + '@esbuild/openbsd-arm64': 0.27.3 + '@esbuild/openbsd-x64': 0.27.3 + '@esbuild/openharmony-arm64': 0.27.3 + '@esbuild/sunos-x64': 0.27.3 + '@esbuild/win32-arm64': 0.27.3 + '@esbuild/win32-ia32': 0.27.3 + '@esbuild/win32-x64': 0.27.3 + + escape-string-regexp@5.0.0: {} + + estree-util-attach-comments@3.0.0: + dependencies: + '@types/estree': 1.0.8 + + estree-util-build-jsx@3.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + estree-walker: 3.0.3 + + estree-util-is-identifier-name@3.0.0: {} + + estree-util-scope@1.0.0: + dependencies: + '@types/estree': 1.0.8 + devlop: 1.1.0 + + estree-util-to-js@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + astring: 1.9.0 + source-map: 0.7.6 + + estree-util-visit@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/unist': 3.0.3 + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + eventemitter3@5.0.4: {} + + expressive-code@0.41.7: + dependencies: + '@expressive-code/core': 0.41.7 + '@expressive-code/plugin-frames': 0.41.7 + '@expressive-code/plugin-shiki': 0.41.7 + '@expressive-code/plugin-text-markers': 0.41.7 + + extend@3.0.2: {} + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + flattie@1.1.1: {} + + fontace@0.4.1: + dependencies: + fontkitten: 1.0.3 + + fontkitten@1.0.3: + dependencies: + tiny-inflate: 1.0.3 + + fsevents@2.3.3: + optional: true + + get-east-asian-width@1.5.0: {} + + github-slugger@2.0.0: {} + + h3@1.15.6: + dependencies: + cookie-es: 1.2.2 + crossws: 0.3.5 + defu: 6.1.4 + destr: 2.0.5 + iron-webcrypto: 1.2.1 + node-mock-http: 1.0.4 + radix3: 1.1.2 + ufo: 1.6.3 + uncrypto: 0.1.3 + + hast-util-embedded@3.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-is-element: 3.0.0 + + hast-util-format@1.1.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-embedded: 3.0.0 + hast-util-minify-whitespace: 1.0.1 + hast-util-phrasing: 3.0.1 + hast-util-whitespace: 3.0.0 + html-whitespace-sensitive-tag-names: 3.0.1 + unist-util-visit-parents: 6.0.2 + + hast-util-from-html@2.0.3: + dependencies: + '@types/hast': 3.0.4 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.3 + parse5: 7.3.0 + vfile: 6.0.3 + vfile-message: 4.0.3 + + hast-util-from-parse5@8.0.3: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + devlop: 1.1.0 + hastscript: 9.0.1 + property-information: 7.1.0 + vfile: 6.0.3 + vfile-location: 5.0.3 + web-namespaces: 2.0.1 + + hast-util-has-property@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-is-body-ok-link@3.0.1: + dependencies: + '@types/hast': 3.0.4 + + hast-util-is-element@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-minify-whitespace@1.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-embedded: 3.0.0 + hast-util-is-element: 3.0.0 + hast-util-whitespace: 3.0.0 + unist-util-is: 6.0.1 + + hast-util-parse-selector@4.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-phrasing@3.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-embedded: 3.0.0 + hast-util-has-property: 3.0.0 + hast-util-is-body-ok-link: 3.0.1 + hast-util-is-element: 3.0.0 + + hast-util-raw@9.1.0: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + '@ungap/structured-clone': 1.3.0 + hast-util-from-parse5: 8.0.3 + hast-util-to-parse5: 8.0.1 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + parse5: 7.3.0 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-select@6.0.4: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + bcp-47-match: 2.0.3 + comma-separated-tokens: 2.0.3 + css-selector-parser: 3.3.0 + devlop: 1.1.0 + direction: 2.0.1 + hast-util-has-property: 3.0.0 + hast-util-to-string: 3.0.1 + hast-util-whitespace: 3.0.0 + nth-check: 2.1.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + unist-util-visit: 5.1.0 + zwitch: 2.0.4 + + hast-util-to-estree@3.1.3: + dependencies: + '@types/estree': 1.0.8 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-attach-comments: 3.0.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + style-to-js: 1.1.21 + unist-util-position: 5.0.0 + zwitch: 2.0.4 + transitivePeerDependencies: + - supports-color + + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-to-jsx-runtime@2.3.6: + dependencies: + '@types/estree': 1.0.8 + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + style-to-js: 1.1.21 + unist-util-position: 5.0.0 + vfile-message: 4.0.3 + transitivePeerDependencies: + - supports-color + + hast-util-to-parse5@8.0.1: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-to-string@3.0.1: + dependencies: + '@types/hast': 3.0.4 + + hast-util-to-text@4.0.2: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + hast-util-is-element: 3.0.0 + unist-util-find-after: 5.0.0 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hastscript@9.0.1: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + + html-escaper@3.0.3: {} + + html-void-elements@3.0.0: {} + + html-whitespace-sensitive-tag-names@3.0.1: {} + + http-cache-semantics@4.2.0: {} + + i18next@23.16.8: + dependencies: + '@babel/runtime': 7.28.6 + + import-meta-resolve@4.2.0: {} + + inline-style-parser@0.2.7: {} + + iron-webcrypto@1.2.1: {} + + is-alphabetical@2.0.1: {} + + is-alphanumerical@2.0.1: + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + + is-decimal@2.0.1: {} + + is-docker@3.0.0: {} + + is-fullwidth-code-point@3.0.0: {} + + is-hexadecimal@2.0.1: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-plain-obj@4.1.0: {} + + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + kleur@3.0.3: {} + + klona@2.0.6: {} + + longest-streak@3.1.0: {} + + lru-cache@11.2.6: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magicast@0.5.2: + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + source-map-js: 1.2.1 + + markdown-extensions@2.0.0: {} + + markdown-table@3.0.4: {} + + mdast-util-definitions@6.0.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + unist-util-visit: 5.1.0 + + mdast-util-directive@3.1.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 + stringify-entities: 4.0.4 + unist-util-visit-parents: 6.0.2 + transitivePeerDependencies: + - supports-color + + mdast-util-find-and-replace@3.0.2: + dependencies: + '@types/mdast': 4.0.4 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + mdast-util-from-markdown@2.0.3: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.2 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-autolink-literal@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.2 + micromark-util-character: 2.1.1 + + mdast-util-gfm-footnote@2.1.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + micromark-util-normalize-identifier: 2.0.1 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-strikethrough@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-table@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + markdown-table: 3.0.4 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-task-list-item@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm@3.1.0: + dependencies: + mdast-util-from-markdown: 2.0.3 + mdast-util-gfm-autolink-literal: 2.0.1 + mdast-util-gfm-footnote: 2.1.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-expression@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-jsx@3.2.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 + stringify-entities: 4.0.4 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.3 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx@3.0.0: + dependencies: + mdast-util-from-markdown: 2.0.3 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdxjs-esm@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.1 + + mdast-util-to-hast@13.2.1: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + + mdast-util-to-markdown@2.1.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 + unist-util-visit: 5.1.0 + zwitch: 2.0.4 + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + mdn-data@2.0.28: {} + + mdn-data@2.27.1: {} + + micromark-core-commonmark@2.0.3: + dependencies: + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-directive@3.0.2: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + parse-entities: 4.0.2 + + micromark-extension-gfm-autolink-literal@2.1.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-footnote@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-strikethrough@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-table@2.1.1: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-tagfilter@2.0.0: + dependencies: + micromark-util-types: 2.0.2 + + micromark-extension-gfm-task-list-item@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm@3.0.0: + dependencies: + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-strikethrough: 2.1.0 + micromark-extension-gfm-table: 2.1.1 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.1.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-mdx-expression@3.0.1: + dependencies: + '@types/estree': 1.0.8 + devlop: 1.1.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-mdx-jsx@3.0.2: + dependencies: + '@types/estree': 1.0.8 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.3 + + micromark-extension-mdx-md@2.0.0: + dependencies: + micromark-util-types: 2.0.2 + + micromark-extension-mdxjs-esm@3.0.0: + dependencies: + '@types/estree': 1.0.8 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.3 + + micromark-extension-mdxjs@3.0.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + micromark-extension-mdx-expression: 3.0.1 + micromark-extension-mdx-jsx: 3.0.2 + micromark-extension-mdx-md: 2.0.0 + micromark-extension-mdxjs-esm: 3.0.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-destination@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-label@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-mdx-expression@2.0.3: + dependencies: + '@types/estree': 1.0.8 + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.3 + + micromark-factory-space@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.2 + + micromark-factory-title@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-whitespace@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-combine-extensions@2.0.1: + dependencies: + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-decode-numeric-character-reference@2.0.2: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.3.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 + + micromark-util-encode@2.0.1: {} + + micromark-util-events-to-acorn@2.0.3: + dependencies: + '@types/estree': 1.0.8 + '@types/unist': 3.0.3 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.3 + + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.2 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + + micromark@4.0.2: + dependencies: + '@types/debug': 4.1.12 + debug: 4.4.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + transitivePeerDependencies: + - supports-color + + mrmime@2.0.1: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + neotraverse@0.6.18: {} + + nlcst-to-string@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + + node-fetch-native@1.6.7: {} + + node-mock-http@1.0.4: {} + + normalize-path@3.0.0: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + ofetch@1.5.1: + dependencies: + destr: 2.0.5 + node-fetch-native: 1.6.7 + ufo: 1.6.3 + + ohash@2.0.11: {} + + oniguruma-parser@0.12.1: {} + + oniguruma-to-es@4.3.4: + dependencies: + oniguruma-parser: 0.12.1 + regex: 6.1.0 + regex-recursion: 6.0.2 + + p-limit@6.2.0: + dependencies: + yocto-queue: 1.2.2 + + p-queue@8.1.1: + dependencies: + eventemitter3: 5.0.4 + p-timeout: 6.1.4 + + p-timeout@6.1.4: {} + + package-manager-detector@1.6.0: {} + + pagefind@1.4.0: + optionalDependencies: + '@pagefind/darwin-arm64': 1.4.0 + '@pagefind/darwin-x64': 1.4.0 + '@pagefind/freebsd-x64': 1.4.0 + '@pagefind/linux-arm64': 1.4.0 + '@pagefind/linux-x64': 1.4.0 + '@pagefind/windows-x64': 1.4.0 + + parse-entities@4.0.2: + dependencies: + '@types/unist': 2.0.11 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.3.0 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + + parse-latin@7.0.0: + dependencies: + '@types/nlcst': 2.0.3 + '@types/unist': 3.0.3 + nlcst-to-string: 4.0.0 + unist-util-modify-children: 4.0.0 + unist-util-visit-children: 3.0.0 + vfile: 6.0.3 + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + piccolore@0.1.3: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + postcss-nested@6.2.0(postcss@8.5.8): + dependencies: + postcss: 8.5.8 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss@8.5.8: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prismjs@1.30.0: {} + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + property-information@7.1.0: {} + + radix3@1.1.2: {} + + readdirp@5.0.0: {} + + recma-build-jsx@1.0.0: + dependencies: + '@types/estree': 1.0.8 + estree-util-build-jsx: 3.0.1 + vfile: 6.0.3 + + recma-jsx@1.0.1(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + estree-util-to-js: 2.0.0 + recma-parse: 1.0.0 + recma-stringify: 1.0.0 + unified: 11.0.5 + + recma-parse@1.0.0: + dependencies: + '@types/estree': 1.0.8 + esast-util-from-js: 2.0.1 + unified: 11.0.5 + vfile: 6.0.3 + + recma-stringify@1.0.0: + dependencies: + '@types/estree': 1.0.8 + estree-util-to-js: 2.0.0 + unified: 11.0.5 + vfile: 6.0.3 + + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.1.0: + dependencies: + regex-utilities: 2.3.0 + + rehype-expressive-code@0.41.7: + dependencies: + expressive-code: 0.41.7 + + rehype-format@5.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-format: 1.1.0 + + rehype-parse@9.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-from-html: 2.0.3 + unified: 11.0.5 + + rehype-raw@7.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-raw: 9.1.0 + vfile: 6.0.3 + + rehype-recma@1.0.0: + dependencies: + '@types/estree': 1.0.8 + '@types/hast': 3.0.4 + hast-util-to-estree: 3.1.3 + transitivePeerDependencies: + - supports-color + + rehype-stringify@10.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + unified: 11.0.5 + + rehype@13.0.2: + dependencies: + '@types/hast': 3.0.4 + rehype-parse: 9.0.1 + rehype-stringify: 10.0.1 + unified: 11.0.5 + + remark-directive@3.0.1: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-directive: 3.1.0 + micromark-extension-directive: 3.0.2 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-gfm@4.0.1: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-gfm: 3.1.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-github-alerts@0.1.1(@types/mdast@4.0.4)(unified@11.0.5): + dependencies: + '@types/mdast': 4.0.4 + unified: 11.0.5 + unist-util-visit: 5.1.0 + + remark-mdx@3.1.1: + dependencies: + mdast-util-mdx: 3.0.0 + micromark-extension-mdxjs: 3.0.0 + transitivePeerDependencies: + - supports-color + + remark-parse@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.3 + micromark-util-types: 2.0.2 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-rehype@11.1.2: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + mdast-util-to-hast: 13.2.1 + unified: 11.0.5 + vfile: 6.0.3 + + remark-smartypants@3.0.2: + dependencies: + retext: 9.0.0 + retext-smartypants: 6.2.0 + unified: 11.0.5 + unist-util-visit: 5.1.0 + + remark-stringify@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.2 + unified: 11.0.5 + + retext-latin@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + parse-latin: 7.0.0 + unified: 11.0.5 + + retext-smartypants@6.2.0: + dependencies: + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unist-util-visit: 5.1.0 + + retext-stringify@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unified: 11.0.5 + + retext@9.0.0: + dependencies: + '@types/nlcst': 2.0.3 + retext-latin: 4.0.0 + retext-stringify: 4.0.0 + unified: 11.0.5 + + rollup@4.59.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.59.0 + '@rollup/rollup-android-arm64': 4.59.0 + '@rollup/rollup-darwin-arm64': 4.59.0 + '@rollup/rollup-darwin-x64': 4.59.0 + '@rollup/rollup-freebsd-arm64': 4.59.0 + '@rollup/rollup-freebsd-x64': 4.59.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 + '@rollup/rollup-linux-arm-musleabihf': 4.59.0 + '@rollup/rollup-linux-arm64-gnu': 4.59.0 + '@rollup/rollup-linux-arm64-musl': 4.59.0 + '@rollup/rollup-linux-loong64-gnu': 4.59.0 + '@rollup/rollup-linux-loong64-musl': 4.59.0 + '@rollup/rollup-linux-ppc64-gnu': 4.59.0 + '@rollup/rollup-linux-ppc64-musl': 4.59.0 + '@rollup/rollup-linux-riscv64-gnu': 4.59.0 + '@rollup/rollup-linux-riscv64-musl': 4.59.0 + '@rollup/rollup-linux-s390x-gnu': 4.59.0 + '@rollup/rollup-linux-x64-gnu': 4.59.0 + '@rollup/rollup-linux-x64-musl': 4.59.0 + '@rollup/rollup-openbsd-x64': 4.59.0 + '@rollup/rollup-openharmony-arm64': 4.59.0 + '@rollup/rollup-win32-arm64-msvc': 4.59.0 + '@rollup/rollup-win32-ia32-msvc': 4.59.0 + '@rollup/rollup-win32-x64-gnu': 4.59.0 + '@rollup/rollup-win32-x64-msvc': 4.59.0 + fsevents: 2.3.3 + + sax@1.5.0: {} + + semver@7.7.4: {} + + sharp@0.34.5: + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.7.4 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-ppc64': 0.34.5 + '@img/sharp-linux-riscv64': 0.34.5 + '@img/sharp-linux-s390x': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-wasm32': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-ia32': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 + + shiki@3.23.0: + dependencies: + '@shikijs/core': 3.23.0 + '@shikijs/engine-javascript': 3.23.0 + '@shikijs/engine-oniguruma': 3.23.0 + '@shikijs/langs': 3.23.0 + '@shikijs/themes': 3.23.0 + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + sisteransi@1.0.5: {} + + sitemap@9.0.1: + dependencies: + '@types/node': 24.12.0 + '@types/sax': 1.2.7 + arg: 5.0.2 + sax: 1.5.0 + + smol-toml@1.6.0: {} + + source-map-js@1.2.1: {} + + source-map@0.7.6: {} + + space-separated-tokens@2.0.2: {} + + stream-replace-string@2.0.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + style-to-js@1.1.21: + dependencies: + style-to-object: 1.0.14 + + style-to-object@1.0.14: + dependencies: + inline-style-parser: 0.2.7 + + svgo@4.0.1: + dependencies: + commander: 11.1.0 + css-select: 5.2.2 + css-tree: 3.2.1 + css-what: 6.2.2 + csso: 5.0.5 + picocolors: 1.1.1 + sax: 1.5.0 + + tiny-inflate@1.0.3: {} + + tinyexec@1.0.2: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + trim-lines@3.0.1: {} + + trough@2.2.0: {} + + tsconfck@3.1.6(typescript@5.9.3): + optionalDependencies: + typescript: 5.9.3 + + tslib@2.8.1: + optional: true + + type-fest@4.41.0: {} + + typescript@5.9.3: {} + + ufo@1.6.3: {} + + ultrahtml@1.6.0: {} + + uncrypto@0.1.3: {} + + undici-types@7.16.0: {} + + unified@11.0.5: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unifont@0.7.4: + dependencies: + css-tree: 3.2.1 + ofetch: 1.5.1 + ohash: 2.0.11 + + unist-util-find-after@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-modify-children@4.0.0: + dependencies: + '@types/unist': 3.0.3 + array-iterate: 2.0.1 + + unist-util-position-from-estree@2.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-remove-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-visit: 5.1.0 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-children@3.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + unstorage@1.17.4: + dependencies: + anymatch: 3.1.3 + chokidar: 5.0.0 + destr: 2.0.5 + h3: 1.15.6 + lru-cache: 11.2.6 + node-fetch-native: 1.6.7 + ofetch: 1.5.1 + ufo: 1.6.3 + + util-deprecate@1.0.2: {} + + vfile-location@5.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile: 6.0.3 + + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + + vite@6.4.1(@types/node@24.12.0): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.8 + rollup: 4.59.0 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.12.0 + fsevents: 2.3.3 + + vitefu@1.1.2(vite@6.4.1(@types/node@24.12.0)): + optionalDependencies: + vite: 6.4.1(@types/node@24.12.0) + + web-namespaces@2.0.1: {} + + which-pm-runs@1.1.0: {} + + widest-line@5.0.0: + dependencies: + string-width: 7.2.0 + + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.2.0 + + xxhash-wasm@1.1.0: {} + + yargs-parser@21.1.1: {} + + yocto-queue@1.2.2: {} + + yocto-spinner@0.2.3: + dependencies: + yoctocolors: 2.1.2 + + yoctocolors@2.1.2: {} + + zod-to-json-schema@3.25.1(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod-to-ts@1.2.0(typescript@5.9.3)(zod@3.25.76): + dependencies: + typescript: 5.9.3 + zod: 3.25.76 + + zod@3.25.76: {} + + zod@4.3.6: {} + + zwitch@2.0.4: {} diff --git a/docs/public/favicon.svg b/docs/public/favicon.svg new file mode 100644 index 000000000..9e3b41ffa --- /dev/null +++ b/docs/public/favicon.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + diff --git a/docs/architecture-decisions/assets/2023-06-06_frontend-templates/modular_templates.jpg b/docs/public/images/2023-06-06_frontend-templates/modular_templates.jpg similarity index 100% rename from docs/architecture-decisions/assets/2023-06-06_frontend-templates/modular_templates.jpg rename to docs/public/images/2023-06-06_frontend-templates/modular_templates.jpg diff --git a/docs/architecture-decisions/assets/2023-06-06_frontend-templates/scenario_1.jpg b/docs/public/images/2023-06-06_frontend-templates/scenario_1.jpg similarity index 100% rename from docs/architecture-decisions/assets/2023-06-06_frontend-templates/scenario_1.jpg rename to docs/public/images/2023-06-06_frontend-templates/scenario_1.jpg diff --git a/docs/architecture-decisions/assets/2023-06-06_frontend-templates/scenario_2.jpg b/docs/public/images/2023-06-06_frontend-templates/scenario_2.jpg similarity index 100% rename from docs/architecture-decisions/assets/2023-06-06_frontend-templates/scenario_2.jpg rename to docs/public/images/2023-06-06_frontend-templates/scenario_2.jpg diff --git a/docs/architecture-decisions/assets/2024-01-13_native_binaries/image_1.png b/docs/public/images/2024-01-13_native_binaries/image_1.png similarity index 100% rename from docs/architecture-decisions/assets/2024-01-13_native_binaries/image_1.png rename to docs/public/images/2024-01-13_native_binaries/image_1.png diff --git a/docs/architecture-decisions/assets/2024-01-13_native_binaries/image_2.png b/docs/public/images/2024-01-13_native_binaries/image_2.png similarity index 100% rename from docs/architecture-decisions/assets/2024-01-13_native_binaries/image_2.png rename to docs/public/images/2024-01-13_native_binaries/image_2.png diff --git a/docs/imgs/algokit-intro-video-thumbnail.jpg b/docs/public/images/algokit-intro-video-thumbnail.jpg similarity index 100% rename from docs/imgs/algokit-intro-video-thumbnail.jpg rename to docs/public/images/algokit-intro-video-thumbnail.jpg diff --git a/docs/imgs/algokit-map.png b/docs/public/images/algokit-map.png similarity index 100% rename from docs/imgs/algokit-map.png rename to docs/public/images/algokit-map.png diff --git a/docs/imgs/algokitartifacts.png b/docs/public/images/algokitartifacts.png similarity index 100% rename from docs/imgs/algokitartifacts.png rename to docs/public/images/algokitartifacts.png diff --git a/docs/imgs/algokitcodetour.png b/docs/public/images/algokitcodetour.png similarity index 100% rename from docs/imgs/algokitcodetour.png rename to docs/public/images/algokitcodetour.png diff --git a/docs/imgs/algokitplayground.png b/docs/public/images/algokitplayground.png similarity index 100% rename from docs/imgs/algokitplayground.png rename to docs/public/images/algokitplayground.png diff --git a/docs/imgs/banner.png b/docs/public/images/banner.png similarity index 100% rename from docs/imgs/banner.png rename to docs/public/images/banner.png diff --git a/docs/architecture-decisions/lifecycle.jpg b/docs/public/images/lifecycle.jpg similarity index 100% rename from docs/architecture-decisions/lifecycle.jpg rename to docs/public/images/lifecycle.jpg diff --git a/docs/imgs/localnet.png b/docs/public/images/localnet.png similarity index 100% rename from docs/imgs/localnet.png rename to docs/public/images/localnet.png diff --git a/docs/src/content.config.ts b/docs/src/content.config.ts new file mode 100644 index 000000000..d9ee8c9d1 --- /dev/null +++ b/docs/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/docs/architecture-decisions/2022-11-14_sandbox-approach.md b/docs/src/content/docs/architecture-decisions/2022-11-14_sandbox-approach.md similarity index 95% rename from docs/architecture-decisions/2022-11-14_sandbox-approach.md rename to docs/src/content/docs/architecture-decisions/2022-11-14_sandbox-approach.md index 0658720dc..236a6c350 100644 --- a/docs/architecture-decisions/2022-11-14_sandbox-approach.md +++ b/docs/src/content/docs/architecture-decisions/2022-11-14_sandbox-approach.md @@ -1,4 +1,6 @@ -# AlgoKit sandbox approach +--- +title: "AlgoKit sandbox approach" +--- - **Status**: Approved - **Owner:** Rob Moore @@ -23,7 +25,7 @@ In order for AlgoKit to facilitate a productive development experience it needs ## Principles -- **[AlgoKit Guiding Principles](../../docs/algokit.md#Guiding-Principles)** - specifically Seamless onramp, Leverage existing ecosystem, Meet devs where they are +- **[AlgoKit Guiding Principles](/algokit-cli/features/overview/#Guiding-Principles)** - specifically Seamless onramp, Leverage existing ecosystem, Meet devs where they are - **Lightweight** - the solution should have as low an impact as possible on resources on the developers machine - **Fast** - the solution should start quickly, which makes for a nicer experience locally and also allows it to be used for continuous integration automation testing diff --git a/docs/architecture-decisions/2022-11-22_beaker-testing-strategy.md b/docs/src/content/docs/architecture-decisions/2022-11-22_beaker-testing-strategy.md similarity index 99% rename from docs/architecture-decisions/2022-11-22_beaker-testing-strategy.md rename to docs/src/content/docs/architecture-decisions/2022-11-22_beaker-testing-strategy.md index 57597c919..fe808c1ca 100644 --- a/docs/architecture-decisions/2022-11-22_beaker-testing-strategy.md +++ b/docs/src/content/docs/architecture-decisions/2022-11-22_beaker-testing-strategy.md @@ -1,4 +1,6 @@ -# Beaker testing strategy +--- +title: "Beaker testing strategy" +--- - **Status**: Draft - **Owner:** Rob Moore diff --git a/docs/architecture-decisions/2023-01-11_beaker_productionisation_review.md b/docs/src/content/docs/architecture-decisions/2023-01-11_beaker_productionisation_review.md similarity index 99% rename from docs/architecture-decisions/2023-01-11_beaker_productionisation_review.md rename to docs/src/content/docs/architecture-decisions/2023-01-11_beaker_productionisation_review.md index 7039d9554..8bc852826 100644 --- a/docs/architecture-decisions/2023-01-11_beaker_productionisation_review.md +++ b/docs/src/content/docs/architecture-decisions/2023-01-11_beaker_productionisation_review.md @@ -1,4 +1,6 @@ -# Beaker productionisation review +--- +title: "Beaker productionisation review" +--- - **Status**: Approved - **Owners:** Rob Moore, Adam Chidlow @@ -226,7 +228,7 @@ The deferment of the `compile()` call is actually a necessary part of recommenda The immediate `compile()` has issues such as requiring implementors (i.e. subclasses) to call `super().__init__()` as a **final** step in their own `__init__` method - any code that runs after the super init call will have no effect on the application produced! -Immediate compilation also reduces the control the user has over the output. Although currently the only parameter that `compile` takes is a `client`, it might be useful to add (optional) parameters here to control the compilation. For example, if you can pass in the list of optimisations that should be applied, that allows you to have [output stability](../articles/output_stability.md) of your smart contract code if new optimisations are added in the future. +Immediate compilation also reduces the control the user has over the output. Although currently the only parameter that `compile` takes is a `client`, it might be useful to add (optional) parameters here to control the compilation. For example, if you can pass in the list of optimisations that should be applied, that allows you to have [output stability](/algokit-cli/concepts/output-stability/) of your smart contract code if new optimisations are added in the future. The separation of compiled state outside of `Application` simplifies the design, and can be done mostly transparently to end-users. diff --git a/docs/architecture-decisions/2023-01-11_brew_install.md b/docs/src/content/docs/architecture-decisions/2023-01-11_brew_install.md similarity index 99% rename from docs/architecture-decisions/2023-01-11_brew_install.md rename to docs/src/content/docs/architecture-decisions/2023-01-11_brew_install.md index 552d4a077..c1f02aac1 100644 --- a/docs/architecture-decisions/2023-01-11_brew_install.md +++ b/docs/src/content/docs/architecture-decisions/2023-01-11_brew_install.md @@ -1,4 +1,6 @@ -# HomeBrew install strategy +--- +title: "HomeBrew install strategy" +--- - **Status**: Approved - **Owner:** Daniel McGregor diff --git a/docs/architecture-decisions/2023-01-12_smart-contract-deployment.md b/docs/src/content/docs/architecture-decisions/2023-01-12_smart-contract-deployment.md similarity index 97% rename from docs/architecture-decisions/2023-01-12_smart-contract-deployment.md rename to docs/src/content/docs/architecture-decisions/2023-01-12_smart-contract-deployment.md index 9eb56b385..f7bbebf85 100644 --- a/docs/architecture-decisions/2023-01-12_smart-contract-deployment.md +++ b/docs/src/content/docs/architecture-decisions/2023-01-12_smart-contract-deployment.md @@ -1,4 +1,6 @@ -# Smart Contract Deployment +--- +title: "Smart Contract Deployment" +--- - **Status**: Approved - **Owner:** Rob Moore @@ -14,7 +16,7 @@ AlgoKit will provide an end-to-end development and deployment experience that in 1. Development 1. **Write** smart contracts 2. **Transpile** smart contracts with development-time parameters to TEAL Templates - 3. **Verify** the TEAL Templates maintain [output stability](../articles/output_stability.md) and any other static code quality checks + 3. **Verify** the TEAL Templates maintain [output stability](/algokit-cli/concepts/output-stability/) and any other static code quality checks 2. Deployment 1. **Substitute** deploy-time parameters into TEAL Templates to create final TEAL code 2. **Compile** the TEAL to create byte code using algod @@ -23,7 +25,7 @@ AlgoKit will provide an end-to-end development and deployment experience that in 1. **Validate** the deployed app via automated testing of the smart contracts to provide confidence in their correctness 2. **Call** deployed smart contract with runtime parameters to utilise it -![Smart Contract Development Lifecycle](./lifecycle.jpg) +![Smart Contract Development Lifecycle](/algokit-cli/images/lifecycle.jpg) The default Development experience that AlgoKit exposes will be via Beaker, however AlgoKit is modular and extensible so other tooling can also be used. @@ -41,7 +43,7 @@ This decision record covers the different options and high level design for how ## Principles -- [AlgoKit Guiding Principles](../../docs/algokit.md#Guiding-Principles) - specifically: +- [AlgoKit Guiding Principles](/algokit-cli/features/overview/#Guiding-Principles) - specifically: - **Cohesive developer tool suite** - **Seamless onramp** - **Secure by default** @@ -74,7 +76,7 @@ There are two key considerations to help answer this question: 1. Should development and deployment be decoupled from each other (i.e. happen at a separate time)? - If we couple development and deployment together then it necessitates that at deploy time you have the same programming environment running that's needed for the smart contract development. So, if you (for instance) were building a smart contract in Python using PyTEAL or Beaker, but deploying the smart contract using TypeScript that means you need a deployment environment that supports both Node.js _and_ Python. This makes it harder to follow the Modular components principle. - If development and deployment are coupled together it rules out using Continuous Delivery since it forces you to build the deployment artifact at the same time as you are deploying it. This means you miss out on the confidence and risk benefit of knowing that when you are deploying to (say) MainNet you are deploying the same artifact that was successfully deployed and tested on (say) TestNet and AlgoKit LocalNet (let alone passes any other checks you decide to run as part of Continuous Integration like automated tests, static code analysis, etc.). - - If development and deployment are coupled together it means we aren't perform an [output stability](../articles/output_stability.md) test so we don't get notified if we make a change that results in a different smart contract (which may then affect things like hashes for smart contract auditing review comparison, unintended introduction of security vulnerabilities, etc.). + - If development and deployment are coupled together it means we aren't perform an [output stability](/algokit-cli/concepts/output-stability/) test so we don't get notified if we make a change that results in a different smart contract (which may then affect things like hashes for smart contract auditing review comparison, unintended introduction of security vulnerabilities, etc.). - Based on all of this, decoupling development and deployment is a very helpful thing for a smart contract and aligns with all of the above-stated principles more closely. 2. Do we need to provide deploy-time parameters? - When deploying a smart contract to a network (say MainNet), there are likely to be certain parameters that will be different from deploying to a different network (say TestNet), e.g.: @@ -281,7 +283,7 @@ The proposed AlgoKit implementation for v1 that provides a balance of flexibilit ### Output stability testing -Ensuring [output stability](../articles/output_stability.md) is useful for smart contract development. It helps ensure that you can refactor code without making an inadvertent change to the smart contract, ensure that a smart contract output isn't changed from any output that is audited, and ensure that there is a clear mechanism to manually review the smart contract output before it's (re-)deployed. +Ensuring [output stability](/algokit-cli/concepts/output-stability/) is useful for smart contract development. It helps ensure that you can refactor code without making an inadvertent change to the smart contract, ensure that a smart contract output isn't changed from any output that is audited, and ensure that there is a clear mechanism to manually review the smart contract output before it's (re-)deployed. There are three broad approaches that could be taken by AlgoKit to help facilitate output stability testing: diff --git a/docs/architecture-decisions/2023-06-06_frontend-templates.md b/docs/src/content/docs/architecture-decisions/2023-06-06_frontend-templates.md similarity index 97% rename from docs/architecture-decisions/2023-06-06_frontend-templates.md rename to docs/src/content/docs/architecture-decisions/2023-06-06_frontend-templates.md index dbe6560fd..b81f9d7b7 100644 --- a/docs/architecture-decisions/2023-06-06_frontend-templates.md +++ b/docs/src/content/docs/architecture-decisions/2023-06-06_frontend-templates.md @@ -1,4 +1,6 @@ -# Frontend Templates +--- +title: "Frontend Templates" +--- - **Status**: Approved - **Owner:** Altynbek Orumbayev @@ -34,7 +36,7 @@ AlgoKit v2 aims provide an end-to-end development and deployment experience that - **Maintainability**: The dApp templating feature should be easy to maintain and extend. This implies that the feature should be implemented in a way that allows for easy addition of new templates and/or modification of existing ones as the complexity and variety of templates scale. - **Seamless onramp**: The dApp templating feature should provide a seamless onramp for developers to get started with dApp development. This implies that the feature should provide a simple and intuitive way to get started with dApp development and deployment. Providing developers a choice on whether they want more flexibility or rely on default recommended practices. -All of the aforementioned requirements should be met in a way that is consistent with the guiding principles of AlgoKit or attempt to find a balanced trade of between the principles that satisfies the requirements. Refer to [AlgoKit Guiding Principles](../../docs/algokit.md#Guiding-Principles) for detailed reference on the principles. +All of the aforementioned requirements should be met in a way that is consistent with the guiding principles of AlgoKit or attempt to find a balanced trade of between the principles that satisfies the requirements. Refer to [AlgoKit Guiding Principles](/algokit-cli/features/overview/#Guiding-Principles) for detailed reference on the principles. ## Explored options @@ -78,7 +80,7 @@ b) Expand on AlgoKit principles of modularity, maintainability and flexibility b The official standalone frontend templates can be build by reusing already established best practices and templates from official backend repositories and by continuing reliance on `copier` for template automation. Another important consideration to keep in mind is that with the introduction of frontend templates we need to establish a clear separation of concerns between the backend and frontend templates to ensure modularity. -![Diagram 1](assets/2023-06-06_frontend-templates/modular_templates.jpg) +![Diagram 1](/algokit-cli/images/2023-06-06_frontend-templates/modular_templates.jpg) As demonstrated on the diagram above, the only glue connecting the backend and frontend is the generated typed client. Neither backend or frontend templates should be concerned with the other but instead provide modular interfaces that clearly indicate to developers on how to integrate the two. From a perspective of a backend template, the typed client shall be seen as a static asset that can be reused by any frontend template. Frontend templates on the other hand are mostly standard web projects with an additional layer of utilities that optionally allow them to be integrated with typed clients produced by backend templates. @@ -86,7 +88,7 @@ As demonstrated on the diagram above, the only glue connecting the backend and f The main scenario to support for this part is to allow developers to use official starter templates to bootstrap end to end dApp projects. -![Diagram 2](assets/2023-06-06_frontend-templates/scenario_1.jpg) +![Diagram 2](/algokit-cli/images/2023-06-06_frontend-templates/scenario_1.jpg) As demonstrated above the dev experience will consist of executing an `algokit init` command for the preferred backends and frontends. @@ -102,7 +104,7 @@ It gives user a choice and responsibility to then decide how to integrate the tw The main scenario to support for this part is to allow developers to use official starter templates to bootstrap end to end dApp projects. -![Diagram 2](assets/2023-06-06_frontend-templates/scenario_2.jpg) +![Diagram 2](/algokit-cli/images/2023-06-06_frontend-templates/scenario_2.jpg) As demonstrated above the user experience will consist of a single execution of `algokit init` command pointed at official full-stack template repository. The full stack templates are responsible for bundling both backend and frontend templates together and providing a seamless onramp for developers to get started with dApp development. The way repositories are bundled should be easy to maintain and should not duplicate individual backend and frontend repositories to avoid redundant maintenance, instead it should expand on metatemplating capabilities of `copier` to allow for efficient reuse of existing standalone backend/frontend templates. diff --git a/docs/architecture-decisions/2023-07-19_advanced_generate_command.md b/docs/src/content/docs/architecture-decisions/2023-07-19_advanced_generate_command.md similarity index 93% rename from docs/architecture-decisions/2023-07-19_advanced_generate_command.md rename to docs/src/content/docs/architecture-decisions/2023-07-19_advanced_generate_command.md index 1eb9d03be..b2810cb54 100644 --- a/docs/architecture-decisions/2023-07-19_advanced_generate_command.md +++ b/docs/src/content/docs/architecture-decisions/2023-07-19_advanced_generate_command.md @@ -1,4 +1,6 @@ -# Advanced `algokit generate` command +--- +title: "Advanced `algokit generate` command" +--- - **Status**: Approved - **Owner:** Altynbek Orumbayev, Inaie Ignacio @@ -9,7 +11,7 @@ ## Context -The [Frontend Templates ADR](./2023-06-06_frontend-templates.md) introduced and expanded on AlgoKit's principles of Modularity and Maintainability by introducing a new set of official templates for quickly bootstrapping standalone `react` and `fullstack` projects showcasing best practices and patterns for building frontend and fullstack applications with Algorand. As a logical next step, we want to enable developers to extend existing projects instantiated from official templates with new files and features. +The [Frontend Templates ADR](/algokit-cli/architecture-decisions/2023-06-06_frontend-templates/) introduced and expanded on AlgoKit's principles of Modularity and Maintainability by introducing a new set of official templates for quickly bootstrapping standalone `react` and `fullstack` projects showcasing best practices and patterns for building frontend and fullstack applications with Algorand. As a logical next step, we want to enable developers to extend existing projects instantiated from official templates with new files and features. ## Requirements @@ -36,7 +38,7 @@ This implies extension of existing starter guidelines available for template bui - **Maintainability**: The `advanced algokit generate` capabilities on `algokit-cli` and related artifacts on respective official templates should be easy to maintain and extend. - **Seamless onramp**: Great developer experience for template builders to create their own `generators` and user experience to use them via `advanced algokit generate` command should be a priority. -All of the aforementioned requirements should be met in a way that is consistent with the guiding principles of AlgoKit or attempt to find a balanced trade of between the principles that satisfies the requirements. Refer to [AlgoKit Guiding Principles](../../docs/algokit.md#Guiding-Principles) for detailed reference on the principles. +All of the aforementioned requirements should be met in a way that is consistent with the guiding principles of AlgoKit or attempt to find a balanced trade of between the principles that satisfies the requirements. Refer to [AlgoKit Guiding Principles](/algokit-cli/features/overview/#Guiding-Principles) for detailed reference on the principles. ## Considered Options @@ -181,7 +183,7 @@ The only distinction between this option and option 1 is that generators are hos - Developing and maintaining generators is significantly more complex due to the need to maintain separate repositories and versioning. - Official maintainers and community template builders need to be put extra effort at keeping generators generic enough to be reused by other templates. Given that templates can vastly differ in type, structure, conventions and patterns, this can be a challenge. -- Given that copier is being considered as a backbone for generators feature, drawbacks outlined for hosting templates on monorepos in the [previous adr](2023-06-06_frontend-templates.md#option-1-monolithic-template) apply here as well. +- Given that copier is being considered as a backbone for generators feature, drawbacks outlined for hosting templates on monorepos in the [previous adr](/algokit-cli/architecture-decisions/2023-06-06_frontend-templates/#option-1-monolithic-template) apply here as well. ## Open questions for reviewers diff --git a/docs/architecture-decisions/2024-01-13_native_binaries.md b/docs/src/content/docs/architecture-decisions/2024-01-13_native_binaries.md similarity index 98% rename from docs/architecture-decisions/2024-01-13_native_binaries.md rename to docs/src/content/docs/architecture-decisions/2024-01-13_native_binaries.md index 7d3316468..a1f35d8cb 100644 --- a/docs/architecture-decisions/2024-01-13_native_binaries.md +++ b/docs/src/content/docs/architecture-decisions/2024-01-13_native_binaries.md @@ -1,4 +1,6 @@ -# AlgoKit CLI native binaries +--- +title: "AlgoKit CLI native binaries" +--- - **Status**: Approved - **Owner:** Altynbek Orumbayev (MakerX), Negar Abbasi (MakerX) @@ -114,7 +116,7 @@ The benchmarking was performed on a MacBook M2 running macOS 14.2.1 and an ARM b | pyinstaller_onefile | 3.031 | 1.466 | 1.875 | | algokit | 0.3126 | 0.6111 | 0.7579 | -![Benchmarking Results](./assets/2024-01-13_native_binaries/image_1.png) +![Benchmarking Results](/algokit-cli/images/2024-01-13_native_binaries/image_1.png) _Figure: Benchmarking results comparing the performance of Nuitka (onefile, onedir modes), PyInstaller (onefile, onedir modes), and pipx installed Algokit CLI on macOS M2, Windows 11 ARM VM, Ubuntu 20 ARM VM._ | Method | Windows (MB) | Ubuntu (MB) | macOS (MB) | @@ -124,7 +126,7 @@ _Figure: Benchmarking results comparing the performance of Nuitka (onefile, oned | pyinstaller_onedir | 46.07 | 52 | 113 | | pyinstaller_onefile | 26.47 | 25 | 45 | -![Bundle sizes](./assets/2024-01-13_native_binaries/image_2.png) +![Bundle sizes](/algokit-cli/images/2024-01-13_native_binaries/image_2.png) _Figure: Bundle sizes of folders with executables build with Nuitka (onefile, onedir modes), PyInstaller (onefile, onedir modes)._ #### Preliminary Observations diff --git a/docs/architecture-decisions/2024-01-23_init-wizard-v2.md b/docs/src/content/docs/architecture-decisions/2024-01-23_init-wizard-v2.md similarity index 97% rename from docs/architecture-decisions/2024-01-23_init-wizard-v2.md rename to docs/src/content/docs/architecture-decisions/2024-01-23_init-wizard-v2.md index 82d88bf0a..1b6f21d1e 100644 --- a/docs/architecture-decisions/2024-01-23_init-wizard-v2.md +++ b/docs/src/content/docs/architecture-decisions/2024-01-23_init-wizard-v2.md @@ -1,4 +1,6 @@ -# AlgoKit Init Wizard Version 2 and Template Enhancements +--- +title: "AlgoKit Init Wizard Version 2 and Template Enhancements" +--- - **Status:** Proposed (Revision 2) - **Owner:** Altynbek Orumbayev @@ -14,7 +16,7 @@ ## Background -This ADR emerges from various discussions aimed at enhancing the `init` wizard version 2 user experience and aligning it with emerging smart contract languages/frameworks to make it more user-friendly and accessible to beginners. It builds upon prior decisions from the [Advanced algokit generate command](./2023-07-19_advanced_generate_command.md) and [Frontend Templates](./2023-06-06_frontend-templates.md) ADRs, integrating feedback from the Algorand Foundation and DevRel team. +This ADR emerges from various discussions aimed at enhancing the `init` wizard version 2 user experience and aligning it with emerging smart contract languages/frameworks to make it more user-friendly and accessible to beginners. It builds upon prior decisions from the [Advanced algokit generate command](/algokit-cli/architecture-decisions/2023-07-19_advanced_generate_command/) and [Frontend Templates](/algokit-cli/architecture-decisions/2023-06-06_frontend-templates/) ADRs, integrating feedback from the Algorand Foundation and DevRel team. ### Main Areas for Improvement diff --git a/docs/architecture-decisions/2024-01-31_binary_distribution.md b/docs/src/content/docs/architecture-decisions/2024-01-31_binary_distribution.md similarity index 97% rename from docs/architecture-decisions/2024-01-31_binary_distribution.md rename to docs/src/content/docs/architecture-decisions/2024-01-31_binary_distribution.md index 9547128e2..9d479896a 100644 --- a/docs/architecture-decisions/2024-01-31_binary_distribution.md +++ b/docs/src/content/docs/architecture-decisions/2024-01-31_binary_distribution.md @@ -1,4 +1,6 @@ -# AlgoKit CLI binary distribution +--- +title: "AlgoKit CLI binary distribution" +--- - **Status**: Approved - **Owner:** Altynbek Orumbayev (MakerX) @@ -9,7 +11,7 @@ ## Context -The following ADR is a continuation of [native binaries](./2024-01-13_native_binaries.md) ADR. With initial workflows implemented, the goal is to determine the best way to distribute the native binaries to the end users. +The following ADR is a continuation of [native binaries](/algokit-cli/architecture-decisions/2024-01-13_native_binaries/) ADR. With initial workflows implemented, the goal is to determine the best way to distribute the native binaries to the end users. ## Requirements @@ -19,7 +21,7 @@ The following ADR is a continuation of [native binaries](./2024-01-13_native_bin ## Technical Constraints - ~~Pyinstaller binaries are dependend on the architecture and the OS. Github Actions mainly support `x86-64` architectures. This means that we need a self hosted runner to build binaries for `arm64` architectures OR use an alternative CI provider which has access to `arm64` and other architectures inside runners.~~ Based on recent announcement made at the date of submission of initial draft of this ADR, GitHub now supports mac os ARM runners on all OSS plans. This means we can target arm64 macos binaries using the default macos runners and potentially reuse them to build arm64 linux binaries using QEMU and/or buildx from Docker. Hence this is no longer a constraint - see [post](https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/). -- Codesigning is a recommended practice for secure distribution and would need to be implemented on top of the initial workflows introduced as part of the implementation of the [native binaries](./2024-01-13_native_binaries.md) ADR. +- Codesigning is a recommended practice for secure distribution and would need to be implemented on top of the initial workflows introduced as part of the implementation of the [native binaries](/algokit-cli/architecture-decisions/2024-01-13_native_binaries/) ADR. ## Options diff --git a/docs/architecture-decisions/2024-03-06_local_dev_ui_packaging.md b/docs/src/content/docs/architecture-decisions/2024-03-06_local_dev_ui_packaging.md similarity index 99% rename from docs/architecture-decisions/2024-03-06_local_dev_ui_packaging.md rename to docs/src/content/docs/architecture-decisions/2024-03-06_local_dev_ui_packaging.md index 9254fc7a9..20a810c17 100644 --- a/docs/architecture-decisions/2024-03-06_local_dev_ui_packaging.md +++ b/docs/src/content/docs/architecture-decisions/2024-03-06_local_dev_ui_packaging.md @@ -1,4 +1,6 @@ -# Local dev UI packaging +--- +title: "Local dev UI packaging" +--- - **Status**: Draft - **Owner:** Patrick Dinh (MakerX), Negar Abbasi (MakerX) diff --git a/docs/articles/output_stability.md b/docs/src/content/docs/concepts/output-stability.md similarity index 96% rename from docs/articles/output_stability.md rename to docs/src/content/docs/concepts/output-stability.md index 31bbe99e2..8d9a30839 100644 --- a/docs/articles/output_stability.md +++ b/docs/src/content/docs/concepts/output-stability.md @@ -1,4 +1,6 @@ -# Smart Contract Output Stability +--- +title: "Smart Contract Output Stability" +--- Smart contracts development is analogous to low level firmware software development; it's a highly constrained environment in terms of both compute power and memory storage, with a high risk of vulnerabilities due to lower level access to memory and less developer-oriented security tooling. Because of this, the assembly language code that is output for a smart contract is important - a seemingly innocuous minor change could inadvertently add a security vulnerability, or could significantly change the execution and memory profile. diff --git a/docs/src/content/docs/features/compile.md b/docs/src/content/docs/features/compile.md new file mode 100644 index 000000000..86ca49a48 --- /dev/null +++ b/docs/src/content/docs/features/compile.md @@ -0,0 +1,170 @@ +--- +title: "AlgoKit Compile" +--- + +The AlgoKit Compile feature enables you to compile smart contracts (apps) and smart signatures (logic signatures) written in a supported high-level language to a format deployable on the Algorand Virtual Machine (AVM). + +When running the compile command, AlgoKit will take care of working out which compiler you need and dynamically resolve it. Additionally, AlgoKit will detect if a matching compiler version is already installed globally on your machine or is included in your project and use that. + +## Prerequisites + +See [Compile Python - Prerequisites](#prerequisites-1) and [Compile TypeScript - Prerequisites](#prerequisites-2) for details. + +## What is Algorand Python & PuyaPy? + +Algorand Python is a semantically and syntactically compatible, typed Python language that works with standard Python tooling and allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM). + +Algorand Python can be deployed to Algorand by using the PuyaPy optimising compiler, which takes Algorand Python and outputs [ARC-32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) application spec files (among other formats) which, [when deployed](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients), will result in AVM bytecode execution semantics that match the given Python code. + +If you want to learn more, check out the [PuyaPy docs](https://github.com/algorandfoundation/puya/blob/main/docs/index.md). + +Below is an example Algorand Python smart contract. + +```py +from algopy import ARC4Contract, arc4 + +class HelloWorldContract(ARC4Contract): + @arc4.abimethod + def hello(self, name: arc4.String) -> arc4.String: + return "Hello, " + name +``` + +For more complex examples, see the [examples](https://github.com/algorandfoundation/puya/tree/main/examples) in the [PuyaPy repo](https://github.com/algorandfoundation/puya). + +## What is Algorand TypeScript & PuyaTs? + +Algorand TypeScript is a typed TypeScript language that allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM). Algorand TypeScript is currently in beta. + +Algorand TypeScript can be deployed to Algorand by using the PuyaTs optimising compiler, which takes Algorand TypeScript and outputs [ARC-32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) application spec files (among other formats) which, [when deployed](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients), will result in AVM bytecode execution semantics that match the given TypeScript code. + +Below is an example Algorand TypeScript smart contract. + +```typescript +import { Contract } from "@algorandfoundation/puya-sdk"; + +class HelloWorldContract extends Contract { + hello(name: string): string { + return "Hello, " + name; + } +} +``` + +## Usage + +Available commands and possible usage are as follows: + +``` +Usage: algokit compile [OPTIONS] COMMAND [ARGS]... + + Compile smart contracts and smart signatures written in a supported high-level language to a format deployable on + the Algorand Virtual Machine (AVM). + +Options: + -v, --version TEXT The compiler version to pin to, for example, 1.0.0. If no version is specified, AlgoKit checks + if the compiler is installed and runs the installed version. If the compiler is not installed, + AlgoKit runs the latest version. If a version is specified, AlgoKit checks if an installed + version matches and runs the installed version. Otherwise, AlgoKit runs the specified version. + -h, --help Show this message and exit. + +Commands: + py Compile Algorand Python contract(s) using the PuyaPy compiler. + python Compile Algorand Python contract(s) using the PuyaPy compiler. + ts Compile Algorand TypeScript contract(s) using the PuyaTs compiler. + typescript Compile Algorand TypeScript contract(s) using the PuyaTs compiler. +``` + +### Compile Python + +The command `algokit compile python` or `algokit compile py` will run the [PuyaPy](https://github.com/algorandfoundation/puya) compiler against the supplied Algorand Python smart contract. + +All arguments supplied to the command are passed directly to PuyaPy, therefore this command supports all options supported by the PuyaPy compiler. + +Any errors detected by PuyaPy during the compilation process will be printed to the output. + +#### Prerequisites + +PuyaPy requires Python 3.12+, so please ensure your Python version satisfies this requirement. + +This command will attempt to resolve a matching installed PuyaPy compiler, either globally installed in the system or locally installed in your project (via [Poetry](https://python-poetry.org/)). If no appropriate match is found, the PuyaPy compiler will be dynamically run using [pipx](https://pipx.pypa.io/stable/). In this case pipx is also required. + +#### Examples + +To see a list of the supported PuyaPy options, run the following: + +```shell +algokit compile python -h +``` + +To determine the version of the PuyaPy compiler in use, execute the following command: + +```shell +algokit compile python --version +``` + +To compile a single Algorand Python smart contract and write the output to a specific location, run the following: + +```shell +algokit compile python hello_world/contract.py --out-dir hello_world/out +``` + +To compile multiple Algorand Python smart contracts and write the output to a specific location, run the following: + +```shell +algokit compile python hello_world/contract.py calculator/contract.py --out-dir my_contracts +``` + +To compile a directory of Algorand Python smart contracts and write the output to the default location, run the following: + +```shell +algokit compile python my_contracts +``` + +### Compile TypeScript + +The command `algokit compile typescript` or `algokit compile ts` will run the PuyaTs compiler against the supplied Algorand TypeScript smart contract. + +All arguments supplied to the command are passed directly to PuyaTs, therefore this command supports all options supported by the PuyaTs compiler. + +Any errors detected by PuyaTs during the compilation process will be printed to the output. + +#### Prerequisites + +PuyaTs requires Node 22+ and NPM 10+, so please ensure your versions satisfy this requirement. + +The command will attempt to find a correctly installed PuyaTs compiler in the following order: + +1. First, it checks if a matching version is installed at the project level (using `npm ls`). +2. Next, it checks if a matching version is installed globally (using `npm --global ls`). +3. If no appropriate match is found, it will run the compiler using npx with the `-y` flag. + +#### Examples + +To see a list of the supported PuyaTs options, run the following: + +```shell +algokit compile typescript -h +``` + +To determine the version of the PuyaTs compiler in use, execute the following command: + +```shell +algokit compile typescript --version +``` + +To compile a single Algorand TypeScript smart contract and write the output to a specific location, run the following: + +```shell +algokit compile typescript hello_world/contract.algo.ts --out-dir hello_world/out +``` + +To build multiple Algorand TypeScript smart contracts and write the output to a specific location, run the following: + +```shell +algokit compile typescript hello_world/contract.algo.ts calculator/contract.algo.ts --out-dir my_contracts +``` + +To compile a directory of Algorand TypeScript smart contracts and write the output to the default location, run the following: + +```shell +algokit compile typescript my_contracts +``` diff --git a/docs/features/completions.md b/docs/src/content/docs/features/completions.md similarity index 65% rename from docs/features/completions.md rename to docs/src/content/docs/features/completions.md index 79ef0c167..22d42e044 100644 --- a/docs/features/completions.md +++ b/docs/src/content/docs/features/completions.md @@ -1,18 +1,20 @@ -# AlgoKit Completions +--- +title: "AlgoKit Completions" +--- AlgoKit supports shell completions for zsh and bash shells, e.g. **bash** -``` -$ algokit +```bash +algokit bootstrap completions config doctor explore goal init sandbox ``` **zsh** -``` -$ ~ algokit +```bash +algokit bootstrap -- Bootstrap AlgoKit project dependencies. completions -- Install and Uninstall AlgoKit shell integration. config -- Configure AlgoKit options. @@ -30,10 +32,10 @@ To setup the completions, AlgoKit provides commands that will modify the current > **Note** > If you would prefer AlgoKit to not modify your interactive shell scripts you can install the completions yourself by following the instructions [here](https://click.palletsprojects.com/en/8.1.x/shell-completion/). -To [install](../cli/index.md#install) completions for the current shell execute `algokit completions install`. You should see output similar to below: +To [install](/algokit-cli/cli/#install) completions for the current shell execute `algokit completions install`. You should see output similar to below: -``` -$ ~ algokit completions install +```bash +algokit completions install AlgoKit completions installed for zsh 🎉 Restart shell or run `. ~/.zshrc` to enable completions ``` @@ -42,15 +44,15 @@ After installing the completions don't forget to restart the shell to begin usin ## Uninstalling -To [uninstall](../cli/index.md#uninstall) completions for the current shell run `algokit completions uninstall`: +To [uninstall](/algokit-cli/cli/#uninstall) completions for the current shell run `algokit completions uninstall`: -``` -$ ~ algokit completions uninstall +```bash +algokit completions uninstall AlgoKit completions uninstalled for zsh 🎉 ``` ## Shell Option -To install/uninstall the completions for a specific [shell](../cli/index.md#--shell-) the `--shell` option can be used e.g. `algokit completions install --shell bash`. +To install/uninstall the completions for a specific [shell](/algokit-cli/cli/#--shell-) the `--shell` option can be used e.g. `algokit completions install --shell bash`. -To learn more about the `algokit completions` command, please refer to [completions](../cli/index.md#completions) in the AlgoKit CLI reference documentation. +To learn more about the `algokit completions` command, please refer to [completions](/algokit-cli/cli/#completions) in the AlgoKit CLI reference documentation. diff --git a/docs/features/config.md b/docs/src/content/docs/features/config.md similarity index 80% rename from docs/features/config.md rename to docs/src/content/docs/features/config.md index b604a4d4f..2318597cc 100644 --- a/docs/features/config.md +++ b/docs/src/content/docs/features/config.md @@ -1,4 +1,6 @@ -# AlgoKit Config +--- +title: "AlgoKit Config" +--- The `algokit config` command allows you to manage various global settings used by AlgoKit CLI. This feature is essential for customizing your AlgoKit environment to suit your needs. @@ -14,8 +16,8 @@ Subcommands ### Version Prompt Configuration -```zsh -$ algokit config version-prompt [OPTIONS] +```bash +algokit config version-prompt [OPTIONS] ``` This command configures the version prompt settings for AlgoKit. @@ -25,8 +27,8 @@ This command configures the version prompt settings for AlgoKit. ### Container Engine Configuration -```zsh -$ algokit config container-engine [OPTIONS] [ENGINE] +```bash +algokit config container-engine [OPTIONS] [ENGINE] ``` This command configures the container engine settings for AlgoKit. @@ -36,8 +38,8 @@ This command configures the container engine settings for AlgoKit. ### JavaScript Package Manager Configuration -```zsh -$ algokit config js-package-manager [OPTIONS] [PACKAGE_MANAGER] +```bash +algokit config js-package-manager [OPTIONS] [PACKAGE_MANAGER] ``` This command configures the default JavaScript package manager used by AlgoKit's bootstrap command. @@ -48,8 +50,8 @@ If no package manager is specified, AlgoKit will prompt you to select one intera ### Python Package Manager Configuration -```zsh -$ algokit config py-package-manager [OPTIONS] [PACKAGE_MANAGER] +```bash +algokit config py-package-manager [OPTIONS] [PACKAGE_MANAGER] ``` This command configures the default Python package manager used by AlgoKit's bootstrap command. @@ -60,4 +62,4 @@ If no package manager is specified, AlgoKit will prompt you to select one intera ## Further Reading -For in-depth details, visit the [configuration section](../cli/index.md#config) in the AlgoKit CLI reference documentation. +For in-depth details, visit the [configuration section](/algokit-cli/cli/#config) in the AlgoKit CLI reference documentation. diff --git a/docs/features/dispenser.md b/docs/src/content/docs/features/dispenser.md similarity index 85% rename from docs/features/dispenser.md rename to docs/src/content/docs/features/dispenser.md index f2de4ea09..7da469a8e 100644 --- a/docs/features/dispenser.md +++ b/docs/src/content/docs/features/dispenser.md @@ -1,11 +1,13 @@ -# AlgoKit TestNet Dispenser +--- +title: "AlgoKit TestNet Dispenser" +--- The AlgoKit Dispenser feature allows you to interact with the AlgoKit TestNet Dispenser. This feature is essential for funding your wallet with TestNet ALGOs, refunding ALGOs back to the dispenser wallet, and getting information about current fund limits on your account. ## Usage -```zsh -$ algokit dispenser [OPTIONS] COMMAND [ARGS]... +```bash +algokit dispenser [OPTIONS] COMMAND [ARGS]... ``` This command provides a set of subcommands to interact with the AlgoKit TestNet Dispenser. @@ -27,8 +29,8 @@ All dispenser commands can work in CI mode by using a CI access token that can b ## Login -```zsh -$ algokit dispenser login [OPTIONS] +```bash +algokit dispenser login [OPTIONS] ``` This command logs you into your Dispenser API account if you are not already logged in. @@ -42,29 +44,29 @@ Options ## Logout -```zsh -$ algokit dispenser logout +```bash +algokit dispenser logout ``` This command logs you out of your Dispenser API account if you are logged in. ## Fund -```zsh -$ algokit dispenser fund [OPTIONS] +```bash +algokit dispenser fund [OPTIONS] ``` This command funds your wallet address with TestNet ALGOs. Options -- `--receiver`, -r: Receiver [alias](./tasks/wallet.md#add) or address to fund with TestNet ALGOs. This option is required. +- `--receiver`, -r: Receiver [alias](/algokit-cli/features/tasks/wallet/#add) or address to fund with TestNet ALGOs. This option is required. - `--amount`, -a: Amount to fund. Defaults to microAlgos. This option is required. - `--whole-units`: Use whole units (Algos) instead of smallest divisible units (microAlgos). Disabled by default. ## Refund -```zsh -$ algokit dispenser refund [OPTIONS] +```bash +algokit dispenser refund [OPTIONS] ``` This command refunds ALGOs back to the dispenser wallet address. @@ -76,8 +78,8 @@ Options ## Limit -```zsh -$ algokit dispenser limit [OPTIONS] +```bash +algokit dispenser limit [OPTIONS] ``` This command gets information about current fund limits on your account. The limits reset daily. @@ -87,4 +89,4 @@ Options ## Further Reading -For in-depth details, visit the [dispenser section](../cli/index.md#dispenser) in the AlgoKit CLI reference documentation. +For in-depth details, visit the [dispenser section](/algokit-cli/cli/#dispenser) in the AlgoKit CLI reference documentation. diff --git a/docs/src/content/docs/features/doctor.md b/docs/src/content/docs/features/doctor.md new file mode 100644 index 000000000..d2691f9b8 --- /dev/null +++ b/docs/src/content/docs/features/doctor.md @@ -0,0 +1,57 @@ +--- +title: "AlgoKit Doctor" +--- + +The AlgoKit Doctor feature allows you to check your AlgoKit installation along with its dependencies. This is useful for diagnosing potential issues with using AlgoKit. + +## Functionality + +The AlgoKit Doctor allows you to make sure that your system has the correct dependencies installed and that they satisfy the minimum required versions. All passed checks will appear in your command line natural color while warnings will be in yellow (warning) and errors or missing critical services will be in red (error). The critical services that AlgoKit will check for (since they are [directly used by certain commands](../../README.md#prerequisites)): Docker, docker compose and git. + +Please run this command to if you are facing an issue running AlgoKit. It is recommended to run it before [submitting an issue to AlgoKit](https://github.com/algorandfoundation/algokit-cli/issues/new). You can copy the contents of the Doctor command message (in Markdown format) to your clipboard by providing the `-c` flag to the command as follows `algokit doctor -c`. + +> NOTE: You can also use the `--verbose` or `-v` flag to show additional information including package dependencies of the AlgoKit CLI: `algokit -v doctor`. This only works when `algokit` is installed as a Python package (e.g., via `pipx install algokit`). + +# Examples + +For example, running `algokit doctor` with all prerequisites installed will result in output similar to the following: + +```bash +algokit doctor +timestamp: 2023-03-29T03:58:05+00:00 +AlgoKit: 0.6.0 +AlgoKit Python: 3.11.2 (main, Mar 24 2023, 00:16:47) [Clang 14.0.0 (clang-1400.0.29.202)] (location: /Users/algokit/.local/pipx/venvs/algokit) +OS: macOS-13.2.1-arm64-arm-64bit +docker: 20.10.22 +docker compose: 2.15.1 +git: 2.39.1 +python: 3.10.9 (location: /Users/algokit/.asdf/shims/python) +python3: 3.10.9 (location: /Users/algokit/.asdf/shims/python3) +pipx: 1.2.0 +poetry: 1.3.2 +node: 18.12.1 +npm: 8.19.2 +brew: 4.0.10-34-gb753315 + +If you are experiencing a problem with AlgoKit, feel free to submit an issue via: +https://github.com/algorandfoundation/algokit-cli/issues/new +Please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` +``` + +The doctor command will indicate if there is any issues to address, for example: + +If AlgoKit detects a newer version, this will be indicated next to the AlgoKit version + +```bash +AlgoKit: 1.2.3 (latest: 4.5.6) +``` + +If the detected version of docker compose is unsupported, this will be shown: + +```bash +docker compose: 2.1.3 + Docker Compose 2.5.0 required to run `algokit localnet command`; + install via https://docs.docker.com/compose/install/ +``` + +For more details about the `AlgoKit doctor` command, please refer to the [AlgoKit CLI reference documentation](/algokit-cli/cli/#doctor). diff --git a/docs/features/explore.md b/docs/src/content/docs/features/explore.md similarity index 56% rename from docs/features/explore.md rename to docs/src/content/docs/features/explore.md index 6eff46e4f..0550fb372 100644 --- a/docs/features/explore.md +++ b/docs/src/content/docs/features/explore.md @@ -1,10 +1,12 @@ -# AlgoKit explore +--- +title: "AlgoKit Explore" +--- -AlgoKit provides a quick shortcut to [explore](../cli/index.md#explore) various Algorand networks using [lora](https://lora.algokit.io/) including [AlgoKit LocalNet](./localnet.md)! +AlgoKit provides a quick shortcut to [explore](/algokit-cli/cli/#explore) various Algorand networks using [lora](https://lora.algokit.io/) including [AlgoKit LocalNet](/algokit-cli/features/localnet/)! ## LocalNet -The following three commands are all equivalent and will open lora pointing to the local [AlgoKit LocalNet](./localnet.md) instance: +The following three commands are all equivalent and will open lora pointing to the local [AlgoKit LocalNet](/algokit-cli/features/localnet/) instance: - `algokit explore` - `algokit explore localnet` @@ -18,4 +20,4 @@ The following three commands are all equivalent and will open lora pointing to t `algokit explore mainnet` will open lora pointing to MainNet via the [node](https://algonode.io/api/). -To learn more about the `algokit explore` command, please refer to [explore](../cli/index.md#explore) in the AlgoKit CLI reference documentation. +To learn more about the `algokit explore` command, please refer to [explore](/algokit-cli/cli/#explore) in the AlgoKit CLI reference documentation. diff --git a/docs/src/content/docs/features/generate.md b/docs/src/content/docs/features/generate.md new file mode 100644 index 000000000..b4d63e3d0 --- /dev/null +++ b/docs/src/content/docs/features/generate.md @@ -0,0 +1,181 @@ +--- +title: "AlgoKit Generate" +--- + +The `algokit generate` [command](/algokit-cli/cli/#generate) is used to generate components used in an AlgoKit project. It also allows for custom generate commands which are loaded from the .algokit.toml file in your project directory. + +## 1. Typed clients + +The `algokit generate client` [command](/algokit-cli/cli/#client) can be used to generate a typed client from an [ARC-0032](https://arc.algorand.foundation/ARCs/arc-0032) or [ARC-0056](https://github.com/algorandfoundation/ARCs/pull/258) application specification with both Python and TypeScript available as target languages. + +### Prerequisites + +To generate Python clients an installation of pip and pipx is required. +To generate TypeScript clients an installation of Node.js and npx is also required. + +Each generated client will also have a dependency on `algokit-utils` libraries for the target language. + +### Input file / directory + +You can either specify a path to an ARC-0032 JSON file, an ARC-0056 JSON file or to a directory that is recursively scanned for `application.json`, `*.arc32.json`, `*.arc56.json` file(s). + +### Output tokens + +The output path is interpreted as relative to the current working directory, however an absolute path may also be specified e.g. +`algokit generate client application.json --output /absolute/path/to/client.py` + +There are two tokens available for use with the `-o`, `--output` [option](/algokit-cli/cli/#-o---output-output_path_pattern): + +- `{contract_name}`: This will resolve to a name based on the ARC-0032/ARC-0056 contract name, formatted appropriately for the target language. +- `{app_spec_dir}`: This will resolve to the parent directory of the `application.json`, `*.arc32.json`, `*.arc56.json` file which can be useful to output a client relative to its source file. + +### Version Pinning + +If you want to ensure typed client output stability across different environments and additionally protect yourself from any potential breaking changes introduced in the client generator packages, you can specify a version you'd like to pin to. + +To make use of this feature, pass `-v`, `--version`, for example `algokit generate client --version 1.2.3 path/to/application.json`. + +Alternatively, you can achieve output stability by installing the underlying [Python](https://github.com/algorandfoundation/algokit-client-generator-py) or [TypeScript](https://github.com/algorandfoundation/algokit-client-generator-ts) client generator package either locally in your project (via `poetry` or `npm` respectively) or globally on your system (via `pipx` or `npm` respectively). AlgoKit will search for a matching installed version before dynamically resolving. + +### Usage + +Usage examples of using a generated client are below, typed clients allow your favourite IDE to provide better intellisense to provide better discoverability +of available operations and parameters. + +#### Python + +```python +# A similar working example can be seen in the algokit python template, when using Python deployment +from smart_contracts.artifacts.HelloWorldApp.client import ( + HelloWorldAppClient, +) + +app_client = HelloWorldAppClient( + algod_client, + creator=deployer, + indexer_client=indexer_client, +) +deploy_response = app_client.deploy( + on_schema_break=OnSchemaBreak.ReplaceApp, + on_update=OnUpdate.UpdateApp, + allow_delete=True, + allow_update=True, +) + +response = app_client.hello(name="World") +``` + +#### TypeScript + +```typescript +// A similar working example can be seen in the algokit python template with typescript deployer, when using TypeScript deployment +import { HelloWorldAppClient } from "./artifacts/HelloWorldApp/client"; + +const appClient = new HelloWorldAppClient( + { + resolveBy: "creatorAndName", + findExistingUsing: indexer, + sender: deployer, + creatorAddress: deployer.addr, + }, + algod +); +const app = await appClient.deploy({ + allowDelete: isLocal, + allowUpdate: isLocal, + onSchemaBreak: isLocal ? "replace" : "fail", + onUpdate: isLocal ? "update" : "fail", +}); +const response = await appClient.hello({ name: "world" }); +``` + +### Examples + +To output a single application.json to a python typed client: +`algokit generate client path/to/application.json --output client.py` + +To process multiple application.json in a directory structure and output to a typescript client for each in the current directory: +`algokit generate client smart_contracts/artifacts --output {contract_name}.ts` + +To process multiple application.json in a directory structure and output to a python client alongside each application.json: +`algokit generate client smart_contracts/artifacts --output {app_spec_path}/client.py` + +## 2. Using Custom Generate Commands + +Custom generate commands are defined in the `.algokit.toml` file within the project directory, typically supplied by community template builders or official AlgoKit templates. These commands are specified under the `generate` key and serve to execute a generator at a designated path with provided answer key/value pairs. + +### Understanding `Generators` + +A `generator` is essentially a compact, self-sufficient `copier` template. This template can optionally be defined within the primary `algokit templates` to offer supplementary functionality after a project is initialized from the template. For instance, the official [`algokit-python-template`](https://github.com/algorandfoundation/algokit-python-template/tree/main/template_content) provides a generator within the `.algokit/generators` directory. This generator can be employed for executing extra tasks on AlgoKit projects that have been initiated from this template, such as adding new smart contracts to an existing project. For a comprehensive explanation, please refer to the [`architecture decision record`](/algokit-cli/architecture-decisions/2023-07-19_advanced_generate_command/). + +### Requirements + +To utilize custom generate commands, you must have `copier` installed. This installation is included by default in the AlgoKit CLI. Therefore, no additional installation is necessary if you have already installed the `algokit cli`. + +### How to Use + +A custom command can be defined in the `.algokit.toml` as shown: + +```toml +[generate.my_generator] +path = "path/to/my_generator" +description = "A brief description of the function of my_generator" +``` + +Following this, you can execute the command as follows: + +`algokit generate my_generator --answer key value --path path/to/my_generator` + +If no `path` is given, the command will use the path specified in the `.algokit.toml`. If no `answer` is provided, the command will initiate an interactive `copier` prompt to request answers (similar to `algokit init`). + +The custom command employs the `copier` library to duplicate the files from the generator's path to the current working directory, substituting any values from the `answers` dictionary. + +### Examples + +As an example, let's use the `smart-contract` generator from the `algokit-python-template` to add new contract to an existing project based on that template. The `smart-contract` generator is defined as follows: + +```toml +[algokit] +min_version = "v1.3.1" + +... # other keys + +[generate.smart_contract] +description = "Adds a new smart contract to the existing project" +path = ".algokit/generators/create_contract" +``` + +To execute this generator, ensure that you are operating from the same directory as the `.algokit.toml` file, and then run: + +```bash +algokit generate + +# The output will be as follows: +# Note how algokit dynamically injects a new `smart-contract` command based +# on the `.algokit.toml` file + +Usage: algokit generate [OPTIONS] COMMAND [ARGS]... + + Generate code for an Algorand project. + +Options: + -h, --help Show this message and exit. + +Commands: + client Create a typed ApplicationClient from an ARC-32 application.json + smart-contract Adds a new smart contract to the existing project +``` + +To execute the `smart-contract` generator, run: + +```bash +algokit generate smart-contract + +# or + +algokit generate smart-contract -a contract_name "MyCoolContract" +``` + +#### Third Party Generators + +It is important to understand that by default, AlgoKit will always prompt you before executing a generator to ensure it's from a trusted source. If you are confident about the source of the generator, you can use the `--force` or `-f` option to execute the generator without this confirmation prompt. Be cautious while using this option and ensure the generator is from a trusted source. At the moment, a trusted source for a generator is defined as _a generator that is included in the official AlgoKit templates (e.g. `smart-contract` generator in `algokit-python-template`)_ diff --git a/docs/features/goal.md b/docs/src/content/docs/features/goal.md similarity index 94% rename from docs/features/goal.md rename to docs/src/content/docs/features/goal.md index 58f1c7c21..2139d4a9b 100644 --- a/docs/features/goal.md +++ b/docs/src/content/docs/features/goal.md @@ -1,11 +1,13 @@ -# AlgoKit goal +--- +title: "AlgoKit Goal" +--- -AlgoKit goal command provides the user with a mechanism to run [goal cli](https://dev.algorand.co/algokit/algokit-cli/goal/) commands against the current [AlgoKit LocalNet](./localnet.md). +AlgoKit goal command provides the user with a mechanism to run [goal cli](https://dev.algorand.co/algokit/algokit-cli/goal/) commands against the current [AlgoKit LocalNet](/algokit-cli/features/localnet/). You can explore all possible goal commands by running `algokit goal` e.g.: -``` -$ ~ algokit goal +```bash +algokit goal GOAL is the CLI for interacting Algorand software instance. The binary 'goal' is installed alongside the algod binary and is considered an integral part of the complete installation. The binaries should be used in tandem - you should not try to use a version of goal with a different version of algod. Usage: @@ -41,8 +43,8 @@ $ ~ algokit goal For instance, running `algokit goal report` would result in output like: -``` -$ ~ algokit goal report +```bash +algokit goal report 12885688322 3.12.2.dev [rel/stable] (commit #181490e3) go-algorand is licensed with AGPLv3.0 @@ -66,14 +68,14 @@ $ ~ algokit goal report If the AlgoKit Sandbox `algod` docker container is not present or not running, the command will fail with a clear error, e.g.: -``` -$ ~ algokit goal +```bash +algokit goal Error: No such container: algokit_algod Error: Error executing goal; ensure the Sandbox is started by executing `algokit sandbox status` ``` -``` -$ ~ algokit goal +```bash +algokit goal Error response from daemon: Container 5a73961536e2c98e371465739053d174066c40d00647c8742f2bb39eb793ed7e is not running Error: Error executing goal; ensure the Sandbox is started by executing `algokit sandbox status` ``` @@ -88,7 +90,7 @@ When you specify a file or directory path in your `goal` command, the system wil For instance, if you want to compile a `teal` file: -``` +```bash algokit goal clerk compile /Path/to/inputfile/approval.teal -o /Path/to/outputfile/approval.compiled ``` @@ -98,7 +100,7 @@ Here, `/Path/to/inputfile/approval.teal` and `/Path/to/outputfile/approval.compi In case you want to manually copy files into the container, you can do so using `docker cp`: -``` +```bash docker cp foo.txt algokit_algod:/root ``` @@ -111,7 +113,7 @@ Note: Manual copying is optional and generally only necessary if you have specif If you want to run multiple commands or interact with the filesystem you can execute `algokit goal --console`. This will open a [Bash](https://www.gnu.org/software/bash/) shell session on the `algod` Docker container and from there you can execute goal directly, e.g.: ```bash -$ algokit goal --console +algokit goal --console Opening Bash console on the algod node; execute `exit` to return to original console root@82d41336608a:~# goal account list [online] C62QEFC7MJBPHAUDMGVXGZ7WRWFAF3XYPBU3KZKOFHYVUYDGU5GNWS4NWU C62QEFC7MJBPHAUDMGVXGZ7WRWFAF3XYPBU3KZKOFHYVUYDGU5GNWS4NWU 4000000000000000 microAlgos @@ -124,7 +126,7 @@ root@82d41336608a:~# goal account list Some `goal` commands require interactive input from the user. By default, AlgoKit will attempt to run commands in non-interactive mode first, and automatically switch to interactive mode if needed. You can force a command to run in interactive mode by using the `--interactive` flag: ```bash -$ algokit goal --interactive wallet new algodev +algokit goal --interactive wallet new algodev Please choose a password for wallet 'algodev': Please confirm the password: Creating wallet... @@ -136,4 +138,4 @@ Would you like to see it now? (Y/n): n This is particularly useful when you know a command will require user input, such as creating new accounts, importing keys, or signing transactions. -For more details about the `AlgoKit goal` command, please refer to the [AlgoKit CLI reference documentation](../cli/index.md#goal). +For more details about the `AlgoKit goal` command, please refer to the [AlgoKit CLI reference documentation](/algokit-cli/cli/#goal). diff --git a/docs/features/init.md b/docs/src/content/docs/features/init.md similarity index 90% rename from docs/features/init.md rename to docs/src/content/docs/features/init.md index 5af907970..e71047550 100644 --- a/docs/features/init.md +++ b/docs/src/content/docs/features/init.md @@ -1,6 +1,8 @@ -# AlgoKit Init +--- +title: "AlgoKit Init" +--- -The `algokit init` [command](../cli/index.md#init) is used to quickly initialize new projects using official Algorand Templates or community provided templates. It supports a fully guided command line wizard experience, as well as fully scriptable / non-interactive functionality via command options. +The `algokit init` [command](/algokit-cli/cli/#init) is used to quickly initialize new projects using official Algorand Templates or community provided templates. It supports a fully guided command line wizard experience, as well as fully scriptable / non-interactive functionality via command options. ## Quick start @@ -14,8 +16,8 @@ Git is a prerequisite for the init command as it is used to clone templates and As outlined in [quick start](#quick-start), the simplest use of the command is to just run `algokit init` and you will then be guided through selecting a template and configuring options for that template. e.g. -``` -$ ~ algokit init +```bash +algokit init ? Which of these options best describes the project you want to start? `Smart Contract` | `Dapp Frontend` | `Smart Contract & Dapp Frontend` | `Custom` ? Name of project / directory to create the project in: my-cool-app ``` @@ -32,13 +34,13 @@ To initialize a project within a workspace, use the `--workspace` flag. If a wor To create a standalone project, use the `--no-workspace` flag during initialization. This instructs AlgoKit to bypass the workspace structure and set up the project as an isolated entity. -For more details on workspaces and standalone projects, refer to the [AlgoKit Project documentation](./project.md#workspaces-vs-standalone-projects). +For more details on workspaces and standalone projects, refer to the [AlgoKit Project documentation](/algokit-cli/features/project/#workspaces-vs-standalone-projects). ## Bootstrapping -You will also be prompted if you wish to run the [bootstrap](../cli/index.md#bootstrap) command, this is useful if you plan to immediately begin developing in the new project. If you passed in `--defaults` or `--bootstrap` then it will automatically run bootstrapping unless you passed in `--no-bootstrap`. +You will also be prompted if you wish to run the [bootstrap](/algokit-cli/cli/#bootstrap) command, this is useful if you plan to immediately begin developing in the new project. If you passed in `--defaults` or `--bootstrap` then it will automatically run bootstrapping unless you passed in `--no-bootstrap`. -``` +```bash ? Do you want to run `algokit bootstrap` to bootstrap dependencies for this new project so it can be run immediately? Yes Installing Python dependencies and setting up Python virtual environment via Poetry @@ -73,7 +75,7 @@ After bootstrapping you are also given the opportunity to initialize a git repo, ## Options -There are a number of options that can be used to provide answers to the template prompts. Some of the options requiring further explanation are detailed below, but consult the CLI reference for all available [options](../cli/index.md#init). +There are a number of options that can be used to provide answers to the template prompts. Some of the options requiring further explanation are detailed below, but consult the CLI reference for all available [options](/algokit-cli/cli/#init). ## Community Templates @@ -87,7 +89,7 @@ e.g. `algokit init --template-url https://github.com/algorandfoundation/algokit- If the URL is not an official template there is a potential security risk and so to continue you must either acknowledge this prompt, or if you are in a non-interactive environment you can pass the `--UNSAFE-SECURITY-accept-template-url` option (but we generally don't recommend this option so users can review the warning message first) e.g. -``` +```bash Community templates have not been reviewed, and can execute arbitrary code. Please inspect the template repository, and pay particular attention to the values of \_tasks, \_migrations and \_jinja_extensions in copier.yml @@ -107,9 +109,9 @@ To find out the key for a specific answer you can either look at `.algokit/.copi By combining a number of options, it is possible to initialize a new project without any interaction. For example, to create a project named `my-smart-contract` using the `python` template with no git, no bootstrapping, the author name of `Algorand Foundation`, and defaults for all other values, you could execute the following: -``` +```bash -$ ~ algokit init -n my-smart-contract -t python --no-git --no-bootstrap --answer author_name "Algorand Foundation" --defaults +algokit init -n my-smart-contract -t python --no-git --no-bootstrap --answer author_name "Algorand Foundation" --defaults 🙌 Project initialized at `my-smart-contract`! For template specific next steps, consult the documentation of your selected template 🧐 Your selected template comes from: ➡️ https://github.com/algorandfoundation/algokit-python-template @@ -157,4 +159,4 @@ To explore what examples are available before initializing, you can run the inte After initializing an example, AlgoKit automatically attempts to open the project in your default IDE to help you quickly start exploring and modifying the code. -For more details about the `AlgoKit init` command, please refer to the [AlgoKit CLI reference documentation](../cli/index.md#init). +For more details about the `AlgoKit init` command, please refer to the [AlgoKit CLI reference documentation](/algokit-cli/cli/#init). diff --git a/docs/features/localnet.md b/docs/src/content/docs/features/localnet.md similarity index 96% rename from docs/features/localnet.md rename to docs/src/content/docs/features/localnet.md index 9c4abd61f..cf7456f4f 100644 --- a/docs/features/localnet.md +++ b/docs/src/content/docs/features/localnet.md @@ -1,4 +1,6 @@ -# AlgoKit LocalNet +--- +title: "AlgoKit LocalNet" +--- The AlgoKit LocalNet feature allows you to manage (start, stop, reset, manage) a locally sandboxed private Algorand network. This allows you to interact and deploy changes against your own Algorand network without needing to worry about funding TestNet accounts, information you submit being publicly visible or being connected to an active Internet connection (once the network has been started). @@ -130,11 +132,11 @@ To reset the LocalNet you can execute `algokit localnet reset`, which will tear ### Viewing transactions in the LocalNet -You can see a web-based user interface of the current state of your LocalNet including all transactions by using the [AlgoKit Explore](./explore.md) feature, e.g. by executing `algokit localnet explore`. +You can see a web-based user interface of the current state of your LocalNet including all transactions by using the [AlgoKit Explore](/algokit-cli/features/explore/) feature, e.g. by executing `algokit localnet explore`. ### Executing goal commands against AlgoKit LocalNet -See the [AlgoKit Goal](./goal.md) feature. You can also execute `algokit localnet console` to open a [Bash shell which allows you to run the goal commandline](./goal.md#running-multiple-commands). +See the [AlgoKit Goal](/algokit-cli/features/goal/) feature. You can also execute `algokit localnet console` to open a [Bash shell which allows you to run the goal commandline](/algokit-cli/features/goal/#running-multiple-commands). Note: if you want to copy files into the container so you can access them via goal then you can use the following: @@ -164,7 +166,7 @@ AlgoKit Utils provides methods to help you do this: - TypeScript - [`ensureFunded`](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/docs/capabilities/transfer.md#ensurefunded) and [`getDispenserAccount`](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/docs/capabilities/transfer.md#dispenser) - Python - [`ensure_funded`](https://algorandfoundation.github.io/algokit-utils-py/html/apidocs/algokit_utils/algokit_utils.html#algokit_utils.ensure_funded) and [`get_dispenser_account`](https://algorandfoundation.github.io/algokit-utils-py/html/apidocs/algokit_utils/algokit_utils.html#algokit_utils.get_dispenser_account) -For more details about the `AlgoKit localnet` command, please refer to the [AlgoKit CLI reference documentation](../cli/index.md#localnet). +For more details about the `AlgoKit localnet` command, please refer to the [AlgoKit CLI reference documentation](/algokit-cli/cli/#localnet). ## GitHub Codespaces-based LocalNet @@ -186,6 +188,6 @@ Running an interactive session ensures that you have control over the lifecycle - `-r`, `--repo-url`: The URL of the repository to use. Defaults to the AlgoKit base template repository (`algorandfoundation/algokit-base-template`). The reason why algokit-base-template is used by default is due to [.devcontainer.json](https://github.com/algorandfoundation/algokit-base-template/blob/main/template_content/.devcontainer.json) which defines the scripts that take care of setting up AlgoKit CLI during container start. You can use any custom repo as a base, however it's important to ensure the reference [.devcontainer.json](https://github.com/algorandfoundation/algokit-base-template/blob/main/template_content/.devcontainer.json) file exists in your repository **otherwise there will be no ports to forward from the codespace**. - `--force`, `-f`: Force deletes stale codespaces and skips confirmation prompts. Defaults to explicitly prompting for confirmation. -For more details about managing LocalNet in GitHub Codespaces, please refer to the [AlgoKit CLI reference documentation](../cli/index.md#codespace). +For more details about managing LocalNet in GitHub Codespaces, please refer to the [AlgoKit CLI reference documentation](/algokit-cli/cli/#codespace). > Tip: By specifying alternative port values it is possible to have several LocalNet instances running where one is using default ports via `algokit localnet start` with Docker | Podman and the other relies on port forwarding via `algokit localnet codespace`. diff --git a/docs/algokit.md b/docs/src/content/docs/features/overview.md similarity index 71% rename from docs/algokit.md rename to docs/src/content/docs/features/overview.md index 036fa66c1..32a3b3670 100644 --- a/docs/algokit.md +++ b/docs/src/content/docs/features/overview.md @@ -1,4 +1,6 @@ -# AlgoKit +--- +title: "AlgoKit" +--- The Algorand AlgoKit CLI is the one-stop shop tool for developers building on the Algorand network. The goal of AlgoKit is to help developers build and launch secure, automated production-ready applications rapidly. @@ -6,19 +8,19 @@ The Algorand AlgoKit CLI is the one-stop shop tool for developers building on th For details on how to use individual features see the following -- [Bootstrap](./features/project/bootstrap.md) - Bootstrap AlgoKit project dependencies -- [Compile](./features/compile.md) - Compile Algorand Python code -- [Completions](./features/completions.md) - Install shell completions for AlgoKit -- [Deploy](./features/project/deploy.md) - Deploy your smart contracts effortlessly to various networks -- [Dispenser](./features/dispenser.md) - Fund your TestNet account with ALGOs from the AlgoKit TestNet Dispenser -- [Doctor](./features/doctor.md) - Check AlgoKit installation and dependencies -- [Explore](./features/explore.md) - Explore Algorand Blockchains using lora -- [Generate](./features/generate.md) - Generate code for an Algorand project -- [Goal](./features/goal.md) - Run the Algorand goal CLI against the AlgoKit Sandbox -- [Init](./features/init.md) - Quickly initialize new projects using official Algorand Templates or community provided templates -- [LocalNet](./features/localnet.md) - Manage a locally sandboxed private Algorand network -- [Project](./features/project.md) - Manage an AlgoKit project workspace on your file system -- [Tasks](./features/tasks.md) - Perform a variety of useful operations on the Algorand blockchain +- [Bootstrap](/algokit-cli/features/project/bootstrap/) - Bootstrap AlgoKit project dependencies +- [Compile](/algokit-cli/features/compile/) - Compile Algorand Python code +- [Completions](/algokit-cli/features/completions/) - Install shell completions for AlgoKit +- [Deploy](/algokit-cli/features/project/deploy/) - Deploy your smart contracts effortlessly to various networks +- [Dispenser](/algokit-cli/features/dispenser/) - Fund your TestNet account with ALGOs from the AlgoKit TestNet Dispenser +- [Doctor](/algokit-cli/features/doctor/) - Check AlgoKit installation and dependencies +- [Explore](/algokit-cli/features/explore/) - Explore Algorand Blockchains using lora +- [Generate](/algokit-cli/features/generate/) - Generate code for an Algorand project +- [Goal](/algokit-cli/features/goal/) - Run the Algorand goal CLI against the AlgoKit Sandbox +- [Init](/algokit-cli/features/init/) - Quickly initialize new projects using official Algorand Templates or community provided templates +- [LocalNet](/algokit-cli/features/localnet/) - Manage a locally sandboxed private Algorand network +- [Project](/algokit-cli/features/project/) - Manage an AlgoKit project workspace on your file system +- [Tasks](/algokit-cli/features/tasks/) - Perform a variety of useful operations on the Algorand blockchain ## Common AlgoKit CLI options @@ -27,9 +29,9 @@ AlgoKit has a number of global options that can impact all commands. Note: these - `-h, --help` The help option can be used on any command to get details on any command, its sub-commands and options. - `-v, --verbose` Enables DEBUG logging, useful when troubleshooting or if you want to peek under the covers and learn what AlgoKit CLI is doing. - `--color / --no-color` Enables or disables output of console styling, we also support the [NO_COLOR](https://no-color.org) environment variable. -- `--skip-version-check` Skips updated AlgoKit version checking and prompting for that execution, this can also be disabled [permanently on a given machine](./cli/index.md#version-prompt) with `algokit config version-prompt disable`. +- `--skip-version-check` Skips updated AlgoKit version checking and prompting for that execution, this can also be disabled [permanently on a given machine](/algokit-cli/cli/#version-prompt) with `algokit config version-prompt disable`. -See also the [AlgoKit CLI Reference](./cli/index.md), which details every command, sub-command and option. +See also the [AlgoKit CLI Reference](/algokit-cli/cli/), which details every command, sub-command and option. ## AlgoKit Tutorials diff --git a/docs/features/project.md b/docs/src/content/docs/features/project.md similarity index 88% rename from docs/features/project.md rename to docs/src/content/docs/features/project.md index 26256e2ec..d2a431d3f 100644 --- a/docs/features/project.md +++ b/docs/src/content/docs/features/project.md @@ -1,6 +1,8 @@ -# AlgoKit Project +--- +title: "AlgoKit Project" +--- -`algokit project` is a collection of commands and command groups useful for managing AlgoKit-compliant [project workspaces](./init.md#workspaces-vs-standalone-projects). +`algokit project` is a collection of commands and command groups useful for managing AlgoKit-compliant [project workspaces](/algokit-cli/features/init/#workspaces-vs-standalone-projects). ## Overview @@ -82,14 +84,14 @@ type = {'backend' | 'contract' | 'frontend'} # currently support 3 generic categ name = 'my-project' # unique name for the project inside workspace ``` -> We recommend using workspaces for most projects (hence enabled by default), as it provides a more organized and scalable approach to managing multiple sub-projects. However, standalone projects are a great choice for simple applications or when you are certain that you will not need to add more sub-projects in the future, for such cases simply append `--no-workspace` when using `algokit init` command. For more details on init command please refer to [init](./init.md) command docs. +> We recommend using workspaces for most projects (hence enabled by default), as it provides a more organized and scalable approach to managing multiple sub-projects. However, standalone projects are a great choice for simple applications or when you are certain that you will not need to add more sub-projects in the future, for such cases simply append `--no-workspace` when using `algokit init` command. For more details on init command please refer to [init](/algokit-cli/features/init/) command docs. ## Features Dive into the features of the `algokit project` command group: -- [bootstrap](./project/bootstrap.md) - Bootstrap your project with AlgoKit. -- [deploy](./project/deploy.md) - Deploy your smart contracts effortlessly to various networks. -- [link](./project/link.md) - Powerful feature designed to streamline the integration between `frontend` and `contract` projects -- [list](./project/list.md) - Enumerate all projects within an AlgoKit workspace. -- [run](./project/run.md) - Define custom commands and manage their execution via `algokit` cli. +- [bootstrap](/algokit-cli/features/project/bootstrap/) - Bootstrap your project with AlgoKit. +- [deploy](/algokit-cli/features/project/deploy/) - Deploy your smart contracts effortlessly to various networks. +- [link](/algokit-cli/features/project/link/) - Powerful feature designed to streamline the integration between `frontend` and `contract` projects +- [list](/algokit-cli/features/project/list/) - Enumerate all projects within an AlgoKit workspace. +- [run](/algokit-cli/features/project/run/) - Define custom commands and manage their execution via `algokit` cli. diff --git a/docs/features/project/bootstrap.md b/docs/src/content/docs/features/project/bootstrap.md similarity index 96% rename from docs/features/project/bootstrap.md rename to docs/src/content/docs/features/project/bootstrap.md index bd744bb74..0b08a8d63 100644 --- a/docs/features/project/bootstrap.md +++ b/docs/src/content/docs/features/project/bootstrap.md @@ -1,4 +1,6 @@ -# AlgoKit Project Bootstrap +--- +title: "AlgoKit Project Bootstrap" +--- The AlgoKit Project Bootstrap feature allows you to bootstrap different project dependencies by looking up specific files in your current directory and immediate sub directories by convention. @@ -17,7 +19,7 @@ You can configure which package managers are used by default via: - `algokit config py-package-manager` - Configure Python package manager (poetry or uv) - `algokit config js-package-manager` - Configure JavaScript package manager (npm or pnpm) -For more details, see the [configuration documentation](../config.md). +For more details, see the [configuration documentation](/algokit-cli/features/config/). ## Package Manager Override @@ -136,8 +138,8 @@ This approach ensures your project commands work correctly while being transpare Available commands and possible usage as follows: -``` -$ ~ algokit project bootstrap +```bash +algokit project bootstrap Usage: algokit project bootstrap [OPTIONS] COMMAND [ARGS]... Options: @@ -161,7 +163,7 @@ The command `algokit project bootstrap env` runs two main tasks in the current d For instance, a sample `.env.template` file as follows: -``` +```bash SERVER_URL=https://myserver.com # This is a mandatory field to run the server, please enter a value # For example: 5000 @@ -170,8 +172,8 @@ SERVER_PORT= Running the `algokit project bootstrap env` command while the above `.env.template` file in the current directory will result in the following: -``` -$ ~ algokit project bootstrap env +```bash +algokit project bootstrap env Copying /Users/me/my-project/.env.template to /Users/me/my-project/.env and prompting for empty values # This is a mandatory field to run the server, please enter a value value # For example: 5000 @@ -181,7 +183,7 @@ Copying /Users/me/my-project/.env.template to /Users/me/my-project/.env and prom And when the user enters a value for `SERVER_PORT`, a new `.env` file will be created as follows (e.g. if they entered `4000` as the value): -``` +```bash SERVER_URL=https://myserver.com # This is a mandatory field to run the server, please enter a value # For example: 5000 @@ -194,8 +196,8 @@ The command `algokit project bootstrap npm` installs Node.js project dependencie Here is an example outcome of running `algokit project bootstrap npm` command: -``` -$ ~ algokit project bootstrap npm +```bash +algokit project bootstrap npm Installing npm dependencies npm: npm: added 17 packages, and audited 18 packages in 3s @@ -215,8 +217,8 @@ The command `algokit project bootstrap poetry` does two main actions: Here is an example of running `algokit project bootstrap poetry` command: -``` -$ ~ algokit project bootstrap poetry +```bash +algokit project bootstrap poetry Installing Python dependencies and setting up Python virtual environment via Poetry poetry: poetry: Installing dependencies from lock file @@ -235,7 +237,7 @@ Execute `algokit project bootstrap all` to initiate `algokit project bootstrap e #### Filtering Options -The `algokit project bootstrap all` command includes flags for more granular control over the bootstrapping process within [AlgoKit workspaces](../init.md#workspaces): +The `algokit project bootstrap all` command includes flags for more granular control over the bootstrapping process within [AlgoKit workspaces](/algokit-cli/features/init/#workspaces): - `--project-name`: This flag allows you to specify one or more project names to bootstrap. Only projects matching the provided names will be bootstrapped. This is particularly useful in monorepos or when working with multiple projects in the same directory structure. @@ -245,4 +247,4 @@ These new flags enhance the flexibility and efficiency of the bootstrapping proc ## Further Reading -To learn more about the `algokit project bootstrap` command, please refer to [bootstrap](../../cli/index.md#bootstrap) in the AlgoKit CLI reference documentation. +To learn more about the `algokit project bootstrap` command, please refer to [bootstrap](/algokit-cli/cli/#bootstrap) in the AlgoKit CLI reference documentation. diff --git a/docs/features/project/deploy.md b/docs/src/content/docs/features/project/deploy.md similarity index 90% rename from docs/features/project/deploy.md rename to docs/src/content/docs/features/project/deploy.md index f78dffda1..0a1a2e72e 100644 --- a/docs/features/project/deploy.md +++ b/docs/src/content/docs/features/project/deploy.md @@ -1,4 +1,6 @@ -# AlgoKit Project Deploy +--- +title: "AlgoKit Project Deploy" +--- Deploy your smart contracts effortlessly to various networks with the algokit project deploy feature. This feature is essential for automation in CI/CD pipelines and for seamless deployment to various Algorand network environments. @@ -6,8 +8,8 @@ Deploy your smart contracts effortlessly to various networks with the algokit pr ## Usage -```sh -$ algokit project deploy [OPTIONS] [ENVIRONMENT_NAME] [EXTRA_ARGS] +```bash +algokit project deploy [OPTIONS] [ENVIRONMENT_NAME] [EXTRA_ARGS] ``` This command deploys smart contracts from an AlgoKit compliant repository to the specified network. @@ -113,8 +115,8 @@ The command requires a `ENVIRONMENT` argument, which specifies the network envir Example: -```sh -$ algokit project deploy testnet +```bash +algokit project deploy testnet ``` This command deploys the smart contracts to the testnet. @@ -145,7 +147,7 @@ command = "{custom_deploy_command}" ``` ```bash -$ algokit project deploy testnet --project-name myproject +algokit project deploy testnet --project-name myproject ``` This command deploys the smart contracts to TestNet from a sub project named 'myproject', which is available within the current workspace. All `.env` loading logic described in [Environment files](#environment-files) is applicable, execution from the workspace root orchestrates invoking the deploy command from the working directory of each applicable sub project. @@ -156,8 +158,8 @@ By default, the deploy command looks for the `.algokit.toml` file in the current Example: -```sh -$ algokit project deploy testnet --project-dir="path/to/project" +```bash +algokit project deploy testnet --project-dir="path/to/project" ``` ## Custom Deploy Command @@ -166,11 +168,11 @@ You can provide a custom deploy command using the `--custom-deploy-command` opti Example: -```sh -$ algokit project deploy testnet --custom-deploy-command="your-custom-command" +```bash +algokit project deploy testnet --custom-deploy-command="your-custom-command" ``` -> ⚠️ Please note, chaining multiple commands with `&&` is **not** currently supported. If you need to run multiple commands, you can defer to a custom script. Refer to [run](../project/run.md#custom-command-injection) for scenarios where multiple sub-command invocations are required. +>⚠️ Please note, chaining multiple commands with `&&` is **not** currently supported. If you need to run multiple commands, you can defer to a custom script. Refer to [run](/algokit-cli/features/project/run/#custom-command-injection) for scenarios where multiple sub-command invocations are required. ## CI Mode @@ -180,8 +182,8 @@ This is useful in CI/CD environments where user interaction is not possible. Whe Example: -```sh -$ algokit project deploy testnet --ci +```bash +algokit project deploy testnet --ci ``` ## Passing Extra Arguments @@ -192,20 +194,20 @@ To pass extra arguments, use `--` after the AlgoKit command and options to mark Example: -```sh -$ algokit project deploy testnet -- my_contract_name --some_contract_related_param +```bash +algokit project deploy testnet -- my_contract_name --some_contract_related_param ``` In this example, `my_contract_name` and `--some_contract_related_param` are extra arguments that can be utilized by the custom deploy command invocation, for instance, to filter the deployment to a specific contract or modify deployment behavior. ## Example of a Full Deployment -```sh -$ algokit project deploy testnet --custom-deploy-command="your-custom-command" +```bash +algokit project deploy testnet --custom-deploy-command="your-custom-command" ``` This example shows how to deploy smart contracts to the testnet using a custom deploy command. This also assumes that .algokit.toml file is present in the current working directory, and .env.testnet file is present in the current working directory and contains the required environment variables for deploying to TestNet environment. ## Further Reading -For in-depth details, visit the [deploy](../../cli/index.md#deploy) section in the AlgoKit CLI reference documentation. +For in-depth details, visit the [deploy](/algokit-cli/cli/#deploy) section in the AlgoKit CLI reference documentation. diff --git a/docs/features/project/link.md b/docs/src/content/docs/features/project/link.md similarity index 88% rename from docs/features/project/link.md rename to docs/src/content/docs/features/project/link.md index 08bf89097..8937979bf 100644 --- a/docs/features/project/link.md +++ b/docs/src/content/docs/features/project/link.md @@ -1,13 +1,15 @@ -# AlgoKit Project Link Command +--- +title: "AlgoKit Project Link Command" +--- -The `algokit project link` command is a powerful feature designed to streamline the integration between `frontend` and `contract` typed projects within the AlgoKit ecosystem. This command facilitates the automatic path resolution and invocation of [`algokit generate client`](../generate.md#1-typed-clients) on `contract` projects available in the workspace, making it easier to integrate smart contracts with frontend applications. +The `algokit project link` command is a powerful feature designed to streamline the integration between `frontend` and `contract` typed projects within the AlgoKit ecosystem. This command facilitates the automatic path resolution and invocation of [`algokit generate client`](/algokit-cli/features/generate/#1-typed-clients) on `contract` projects available in the workspace, making it easier to integrate smart contracts with frontend applications. ## Usage To use the `link` command, navigate to the root directory of your standalone frontend project and execute: -```sh -$ algokit project link [OPTIONS] +```bash +algokit project link [OPTIONS] ``` This command must be invoked from the root of a standalone 'frontend' typed project. @@ -56,12 +58,12 @@ graph LR Linking all contract projects with a frontend project and generating TypeScript clients: -```sh -$ algokit project link --all -l typescript +```bash +algokit project link --all -l typescript ``` This command will generate TypeScript clients for all contract projects and place them in the specified directory within the frontend project. ## Further Reading -To learn more about the `algokit project link` command, please refer to [link](../../cli/index.md#link) in the AlgoKit CLI reference documentation. +To learn more about the `algokit project link` command, please refer to [link](/algokit-cli/cli/#link) in the AlgoKit CLI reference documentation. diff --git a/docs/features/project/list.md b/docs/src/content/docs/features/project/list.md similarity index 90% rename from docs/features/project/list.md rename to docs/src/content/docs/features/project/list.md index 0f8275363..78940ea87 100644 --- a/docs/features/project/list.md +++ b/docs/src/content/docs/features/project/list.md @@ -1,4 +1,6 @@ -# AlgoKit Project List Command +--- +title: "AlgoKit Project List Command" +--- The `algokit project list` command is designed to enumerate all projects within an AlgoKit workspace. This command is particularly useful in workspace environments where multiple projects are managed under a single root directory. It provides a straightforward way to view all the projects that are part of the workspace. @@ -6,8 +8,8 @@ The `algokit project list` command is designed to enumerate all projects within To use the `list` command, execute the following **anywhere** within an AlgoKit workspace: -```sh -$ algokit project list [OPTIONS] [WORKSPACE_PATH] +```bash +algokit project list [OPTIONS] [WORKSPACE_PATH] ``` - `WORKSPACE_PATH` is an optional argument that specifies the path to the workspace. If not provided, the current directory (`.`) is used as the default workspace path. @@ -22,7 +24,7 @@ $ algokit project list [OPTIONS] [WORKSPACE_PATH] ## Example Output -```sh +```bash workspace: {path_to_workspace} 📁 - myapp ({path_to_myapp}) 📜 - myproject-app ({path_to_myproject_app}) 🖥️ @@ -32,7 +34,7 @@ workspace: {path_to_workspace} 📁 If the command is executed in a directory that is not recognized as an AlgoKit workspace, it will issue a warning: -```sh +```bash WARNING: No AlgoKit workspace found. Check [project.type] definition at .algokit.toml ``` @@ -40,4 +42,4 @@ This message indicates that either the current directory does not contain a `.al ## Further Reading -To learn more about the `algokit project list` command, please refer to [list](../../cli/index.md#list) in the AlgoKit CLI reference documentation. +To learn more about the `algokit project list` command, please refer to [list](/algokit-cli/cli/#list) in the AlgoKit CLI reference documentation. diff --git a/docs/features/project/run.md b/docs/src/content/docs/features/project/run.md similarity index 95% rename from docs/features/project/run.md rename to docs/src/content/docs/features/project/run.md index a6031e288..295ef510a 100644 --- a/docs/features/project/run.md +++ b/docs/src/content/docs/features/project/run.md @@ -1,11 +1,13 @@ -# AlgoKit Project Run +--- +title: "AlgoKit Project Run" +--- The `algokit project run` command allows defining custom commands to execute at standalone project level or being orchestrated from a workspace containing multiple standalone projects. ## Usage -```sh -$ algokit project run [OPTIONS] COMMAND [ARGS] +```bash +algokit project run [OPTIONS] COMMAND [ARGS] ``` This command executes a custom command defined in the `.algokit.toml` file of the current project or workspace. @@ -155,9 +157,9 @@ You can control whether commands are executed concurrently or sequentially: 1. Use command-line options: - ```sh - $ algokit project run hello -s # or --sequential - $ algokit project run hello -c # or --concurrent + ```bash + algokit project run hello -s # or --sequential + algokit project run hello -c # or --concurrent ``` 2. Behavior: @@ -173,12 +175,12 @@ You can pass additional arguments to the custom command. These extra arguments w Example: -```sh -$ algokit project run hello -- world +```bash +algokit project run hello -- world ``` In this example, if the `hello` command in `.algokit.toml` is defined as `echo "Hello"`, the actual command executed will be `echo "Hello" world`. ## Further Reading -To learn more about the `algokit project run` command, please refer to [run](../../cli/index.md#run) in the AlgoKit CLI reference documentation. +To learn more about the `algokit project run` command, please refer to [run](/algokit-cli/cli/#run) in the AlgoKit CLI reference documentation. diff --git a/docs/src/content/docs/features/tasks.md b/docs/src/content/docs/features/tasks.md new file mode 100644 index 000000000..d026689ce --- /dev/null +++ b/docs/src/content/docs/features/tasks.md @@ -0,0 +1,18 @@ +--- +title: "AlgoKit Tasks" +--- + +AlgoKit Tasks are a collection of handy tasks that can be used to perform various operations on Algorand blockchain. + +## Features + +- [Wallet Aliasing](/algokit-cli/features/tasks/wallet/) - Manage your Algorand addresses and accounts effortlessly with the AlgoKit Wallet feature. This feature allows you to create short aliases for your addresses and accounts on AlgoKit CLI. +- [Vanity Address Generation](/algokit-cli/features/tasks/vanity_address/) - Generate vanity addresses for your Algorand accounts with the AlgoKit Vanity feature. This feature allows you to generate Algorand addresses which contains a specific keyword of your choice. +- [Transfer Assets or Algos](/algokit-cli/features/tasks/transfer/) - Transfer Algos or Assets from one account to another with the AlgoKit Transfer feature. This feature allows you to transfer Algos or Assets from one account to another on Algorand blockchain. +- [Opt-(in|out) Assets](/algokit-cli/features/tasks/opt/) - Opt-in or opt-out of Algorand Asset(s). Supports single or multiple assets. +- [Signing transactions](/algokit-cli/features/tasks/sign/) - Sign goal clerk compatible Algorand transactions. +- [Sending transactions](/algokit-cli/features/tasks/send/) - Send signed goal clerk compatible Algorand transactions. +- [NFD lookups](/algokit-cli/features/tasks/nfd/) - Perform a lookup via NFD domain or address, returning the associated address or domain respectively using the AlgoKit CLI. +- [IPFS uploads](/algokit-cli/features/tasks/ipfs/) - Upload files to IPFS. +- [Asset minting](/algokit-cli/features/tasks/mint/) - Mint new fungible or non-fungible assets on Algorand. +- [Analyze TEAL code](/algokit-cli/features/tasks/analyze/) - Analyze TEAL code using [`tealer`](https://github.com/crytic/tealer) integration for common vulnerabilities. diff --git a/docs/features/tasks/analyze.md b/docs/src/content/docs/features/tasks/analyze.md similarity index 97% rename from docs/features/tasks/analyze.md rename to docs/src/content/docs/features/tasks/analyze.md index 47da76002..c2b90568a 100644 --- a/docs/features/tasks/analyze.md +++ b/docs/src/content/docs/features/tasks/analyze.md @@ -1,4 +1,6 @@ -# AlgoKit Task Analyze +--- +title: "AlgoKit Task Analyze" +--- The `analyze` task is a command-line utility that analyzes TEAL programs for common vulnerabilities using [Tealer](https://github.com/crytic/tealer) integration. It allows you to detect a range of common vulnerabilities in code written in TEAL. For full list of vulnerability detectors refer to [Tealer documentation](https://github.com/crytic/tealer?tab=readme-ov-file#detectors). diff --git a/docs/features/tasks/ipfs.md b/docs/src/content/docs/features/tasks/ipfs.md similarity index 87% rename from docs/features/tasks/ipfs.md rename to docs/src/content/docs/features/tasks/ipfs.md index 638038be3..2a522d05a 100644 --- a/docs/features/tasks/ipfs.md +++ b/docs/src/content/docs/features/tasks/ipfs.md @@ -1,4 +1,6 @@ -# AlgoKit Task IPFS +--- +title: "AlgoKit Task IPFS" +--- The AlgoKit IPFS feature allows you to interact with the IPFS [InterPlanetary File System](https://ipfs.tech/) using the [Piñata provider](https://www.pinata.cloud/). This feature supports logging in and out of the Piñata provider, and uploading files to IPFS. @@ -7,7 +9,7 @@ The AlgoKit IPFS feature allows you to interact with the IPFS [InterPlanetary Fi Available commands and possible usage as follows: ```bash -$ ~ algokit task ipfs +algokit task ipfs Usage: algokit task ipfs [OPTIONS] Upload files to IPFS using Pinata provider. @@ -32,7 +34,7 @@ Before you can use this feature, you need to ensure that you have signed up for Please note, you need to login to the Piñata provider before you can upload files. You can do this using the `login` command: ```bash -$ algokit task ipfs login +algokit task ipfs login ``` This will prompt you to enter your Piñata JWT. Once you are logged in, you can upload files to IPFS. @@ -42,7 +44,7 @@ This will prompt you to enter your Piñata JWT. Once you are logged in, you can To upload a file to IPFS, you can use the `ipfs` command as follows: ```bash -$ algokit task ipfs --file {PATH_TO_YOUR_FILE} +algokit task ipfs --file {PATH_TO_YOUR_FILE} ``` This will upload the file to IPFS using the Piñata provider and return the CID (Content Identifier) of the uploaded file. @@ -52,7 +54,7 @@ This will upload the file to IPFS using the Piñata provider and return the CID If you want to logout from the Piñata provider, you can use the `logout` command: ```bash -$ algokit task ipfs logout +algokit task ipfs logout ``` This will remove your Piñata JWT from the keyring. @@ -63,4 +65,4 @@ Please note, the maximum file size that can be uploaded is 100MB. If you try to ## Further Reading -For in-depth details, visit the [ipfs section](../../cli/index.md#ipfs) in the AlgoKit CLI reference documentation. +For in-depth details, visit the [ipfs section](/algokit-cli/cli/#ipfs) in the AlgoKit CLI reference documentation. diff --git a/docs/features/tasks/mint.md b/docs/src/content/docs/features/tasks/mint.md similarity index 95% rename from docs/features/tasks/mint.md rename to docs/src/content/docs/features/tasks/mint.md index 5fabda32b..58ee1e75d 100644 --- a/docs/features/tasks/mint.md +++ b/docs/src/content/docs/features/tasks/mint.md @@ -1,4 +1,6 @@ -# AlgoKit Task Mint +--- +title: "AlgoKit Task Mint" +--- The AlgoKit Mint feature allows you to mint new fungible or non-fungible assets on the Algorand blockchain. This feature supports the creation of assets, validation of asset parameters, and uploading of asset metadata and image to IPFS using the Piñata provider. Immutable assets are compliant with [ARC3](https://arc.algorand.foundation/ARCs/arc-0003), while mutable are based using [ARC19](https://arc.algorand.foundation/ARCs/arc-0019) standard. @@ -48,7 +50,7 @@ Options: To mint a new asset in interactive mode, you can use the mint command as follows: ```bash -$ algokit task mint +algokit task mint ``` This will interactively prompt you for the required information, upload the asset image and metadata to IPFS using the Piñata provider and mint a new asset on the Algorand blockchain. The [asset's metadata](https://arc.algorand.foundation/ARCs/arc-0003#json-metadata-file-schema) will be generated automatically based on the provided asset name, decimals, and image. @@ -56,7 +58,7 @@ This will interactively prompt you for the required information, upload the asse If you want to provide a custom metadata file, you can use the --metadata flag: ```bash -$ algokit task mint --metadata {PATH_TO_METADATA} +algokit task mint --metadata {PATH_TO_METADATA} ``` If the minting process is successful, the asset ID and transaction ID will be output to the console. @@ -67,4 +69,4 @@ For non interactive mode, refer to usage section above for available options. ## Further Reading -For in-depth details, visit the [mint section](../../cli/index.md#mint) in the AlgoKit CLI reference documentation. +For in-depth details, visit the [mint section](/algokit-cli/cli/#mint) in the AlgoKit CLI reference documentation. diff --git a/docs/features/tasks/nfd.md b/docs/src/content/docs/features/tasks/nfd.md similarity index 83% rename from docs/features/tasks/nfd.md rename to docs/src/content/docs/features/tasks/nfd.md index 813146151..5e21b8aae 100644 --- a/docs/features/tasks/nfd.md +++ b/docs/src/content/docs/features/tasks/nfd.md @@ -1,4 +1,6 @@ -# AlgoKit Task NFD Lookup +--- +title: "AlgoKit Task NFD Lookup" +--- The AlgoKit NFD Lookup feature allows you to perform a lookup via NFD domain or address, returning the associated address or domain respectively using the AlgoKit CLI. The feature is powered by [NFDomains MainNet API](https://api-docs.nf.domains/). @@ -7,7 +9,7 @@ The AlgoKit NFD Lookup feature allows you to perform a lookup via NFD domain or Available commands and possible usage as follows: ```bash -$ ~ algokit task nfd-lookup +algokit task nfd-lookup Usage: algokit task nfd-lookup [OPTIONS] VALUE Perform a lookup via NFD domain or address, returning the associated address or domain respectively. @@ -29,17 +31,17 @@ Options: To perform a lookup, you can use the nfd-lookup command as follows: ```bash -$ algokit task nfd-lookup {NFD_DOMAIN_OR_ALGORAND_ADDRESS} +algokit task nfd-lookup {NFD_DOMAIN_OR_ALGORAND_ADDRESS} ``` This will perform a lookup and return the associated address or domain. If you want to specify the output format, you can use the --output flag: ```bash -$ algokit task nfd-lookup {NFD_DOMAIN_OR_ALGORAND_ADDRESS} --output full +algokit task nfd-lookup {NFD_DOMAIN_OR_ALGORAND_ADDRESS} --output full ``` If the lookup is successful, the result will be output to the console in a JSON format. ## Further Reading -For in-depth details, visit the [nfd-lookup section](../../cli/index.md#nfd-lookup) in the AlgoKit CLI reference documentation. +For in-depth details, visit the [nfd-lookup section](/algokit-cli/cli/#nfd-lookup) in the AlgoKit CLI reference documentation. diff --git a/docs/features/tasks/opt.md b/docs/src/content/docs/features/tasks/opt.md similarity index 82% rename from docs/features/tasks/opt.md rename to docs/src/content/docs/features/tasks/opt.md index afc5785fb..af66e2fae 100644 --- a/docs/features/tasks/opt.md +++ b/docs/src/content/docs/features/tasks/opt.md @@ -1,4 +1,6 @@ -# AlgoKit Task Asset opt-(in|out) +--- +title: "AlgoKit Task Asset opt-(in|out)" +--- AlgoKit Task Asset opt-(in|out) allows you to opt-in or opt-out of Algorand Asset(s). This task supports single or multiple assets. @@ -49,23 +51,23 @@ Example To opt-in to an asset(s), you can use the opt-in command as follows: ```bash -$ algokit task opt-in --account {YOUR_ACCOUNT} {ASSET_ID_1} {ASSET_ID_2} {ASSET_ID_3} ... +algokit task opt-in --account {YOUR_ACCOUNT} {ASSET_ID_1} {ASSET_ID_2} {ASSET_ID_3} ... ``` To opt-out of an asset(s), you can use the opt-out command as follows: ```bash -$ algokit task opt-out --account {YOUR_ACCOUNT} {ASSET_ID_1} {ASSET_ID_2} ... +algokit task opt-out --account {YOUR_ACCOUNT} {ASSET_ID_1} {ASSET_ID_2} ... ``` To opt-out of all assets with zero balance, you can use the opt-out command with the `--all` flag: ```bash -$ algokit task opt-out --account {YOUR_ACCOUNT} --all +algokit task opt-out --account {YOUR_ACCOUNT} --all ``` > Please note, the account must have sufficient balance to cover the transaction fees. ## Further Reading -For in-depth details, visit the [opt-in](../../cli/index.md#opt-in) and [opt-out](../../cli/index#opt-out) sections in the AlgoKit CLI reference documentation. +For in-depth details, visit the [opt-in](/algokit-cli/cli/#opt-in) and [opt-out](../../cli/index#opt-out) sections in the AlgoKit CLI reference documentation. diff --git a/docs/features/tasks/send.md b/docs/src/content/docs/features/tasks/send.md similarity index 82% rename from docs/features/tasks/send.md rename to docs/src/content/docs/features/tasks/send.md index c9c5bf34b..9a91a8461 100644 --- a/docs/features/tasks/send.md +++ b/docs/src/content/docs/features/tasks/send.md @@ -1,4 +1,6 @@ -# AlgoKit Task Send +--- +title: "AlgoKit Task Send" +--- The AlgoKit Send feature allows you to send signed Algorand transaction(s) to a specified network using the AlgoKit CLI. This feature supports sending single or multiple transactions, either provided directly as a base64 encoded string or from a binary file. @@ -7,7 +9,7 @@ The AlgoKit Send feature allows you to send signed Algorand transaction(s) to a Available commands and possible usage as follows: ```bash -$ ~ algokit task send +algokit task send Usage: algokit task send [OPTIONS] Send a signed transaction to the given network. @@ -34,19 +36,19 @@ Options: To send a transaction, you can use the `send` command as follows: ```bash -$ algokit task send --file {PATH_TO_BINARY_FILE_CONTAINING_SIGNED_TRANSACTIONS} +algokit task send --file {PATH_TO_BINARY_FILE_CONTAINING_SIGNED_TRANSACTIONS} ``` This will send the transactions to the default `localnet` network. If you want to send the transactions to a different network, you can use the `--network` flag: ```bash -$ algokit task send --transaction {YOUR_BASE64_ENCODED_SIGNED_TRANSACTION} --network testnet +algokit task send --transaction {YOUR_BASE64_ENCODED_SIGNED_TRANSACTION} --network testnet ``` You can also pipe in the `stdout` of `algokit sign` command: ```bash -$ algokit task sign --account {YOUR_ACCOUNT_ALIAS OR YOUR_ADDRESS} --file {PATH_TO_BINARY_FILE_CONTAINING_TRANSACTIONS} --force | algokit task send --network {network_name} +algokit task sign --account {YOUR_ACCOUNT_ALIAS OR YOUR_ADDRESS} --file {PATH_TO_BINARY_FILE_CONTAINING_TRANSACTIONS} --force | algokit task send --network {network_name} ``` If the transaction is successfully sent, the transaction ID (txid) will be output to the console. You can check the transaction status at the provided transaction explorer URL. @@ -57,4 +59,4 @@ Please note, at the moment this feature only supports [`goal clerk`](https://dev ## Further Reading -For in-depth details, visit the [send section](../../cli/index.md#send) in the AlgoKit CLI reference documentation. +For in-depth details, visit the [send section](/algokit-cli/cli/#send) in the AlgoKit CLI reference documentation. diff --git a/docs/features/tasks/sign.md b/docs/src/content/docs/features/tasks/sign.md similarity index 86% rename from docs/features/tasks/sign.md rename to docs/src/content/docs/features/tasks/sign.md index 6480dc3b3..a334e6173 100644 --- a/docs/features/tasks/sign.md +++ b/docs/src/content/docs/features/tasks/sign.md @@ -1,4 +1,6 @@ -# AlgoKit Task Sign +--- +title: "AlgoKit Task Sign" +--- The AlgoKit Sign feature allows you to sign Algorand transaction(s) using the AlgoKit CLI. This feature supports signing single or multiple transactions, either provided directly as a base64 encoded string or from a binary file. @@ -7,7 +9,7 @@ The AlgoKit Sign feature allows you to sign Algorand transaction(s) using the Al Available commands and possible usage as follows: ```bash -$ ~ algokit task sign +algokit task sign Usage: algokit task sign [OPTIONS] Sign goal clerk compatible Algorand transaction(s). @@ -36,19 +38,19 @@ Options: To sign a transaction, you can use the `sign` command as follows: ```bash -$ algokit task sign --account {YOUR_ACCOUNT_ALIAS OR YOUR_ADDRESS} --file {PATH_TO_BINARY_FILE_CONTAINING_TRANSACTIONS} +algokit task sign --account {YOUR_ACCOUNT_ALIAS OR YOUR_ADDRESS} --file {PATH_TO_BINARY_FILE_CONTAINING_TRANSACTIONS} ``` This will prompt you to confirm the transaction details before signing. If you want to bypass the confirmation, you can use the `--force` flag: ```bash -$ algokit task sign --account {YOUR_ACCOUNT_ALIAS OR YOUR_ADDRESS} --transaction {YOUR_BASE64_ENCODED_TRANSACTION} --force +algokit task sign --account {YOUR_ACCOUNT_ALIAS OR YOUR_ADDRESS} --transaction {YOUR_BASE64_ENCODED_TRANSACTION} --force ``` If the transaction is successfully signed, the signed transaction will be output to the console in a JSON format. If you want to write the signed transaction to a file, you can use the `--output` option: ```bash -$ algokit task sign --account {YOUR_ACCOUNT_ALIAS OR YOUR_ADDRESS} --transaction {YOUR_BASE64_ENCODED_TRANSACTION} --output /path/to/output/file +algokit task sign --account {YOUR_ACCOUNT_ALIAS OR YOUR_ADDRESS} --transaction {YOUR_BASE64_ENCODED_TRANSACTION} --output /path/to/output/file ``` This will write the signed transaction to the specified file. @@ -85,10 +87,10 @@ Encoding simple txn object in javascript: ```ts Buffer.from(algosdk.encodeObj({ txn: txn.get_obj_for_encoding() })).toString( - "base64" + "base64", ); // Resulting string can be passed directly to algokit task sign with --transaction flag ``` ## Further Reading -For in-depth details, visit the [sign section](../../cli/index.md#sign) in the AlgoKit CLI reference documentation. +For in-depth details, visit the [sign section](/algokit-cli/cli/#sign) in the AlgoKit CLI reference documentation. diff --git a/docs/features/tasks/transfer.md b/docs/src/content/docs/features/tasks/transfer.md similarity index 66% rename from docs/features/tasks/transfer.md rename to docs/src/content/docs/features/tasks/transfer.md index 4e5034d43..06e153809 100644 --- a/docs/features/tasks/transfer.md +++ b/docs/src/content/docs/features/tasks/transfer.md @@ -1,4 +1,6 @@ -# AlgoKit Task Transfer +--- +title: "AlgoKit Task Transfer" +--- The AlgoKit Transfer feature allows you to transfer algos and assets between two accounts. @@ -7,7 +9,7 @@ The AlgoKit Transfer feature allows you to transfer algos and assets between two Available commands and possible usage as follows: ```bash -$ ~ algokit task transfer +algokit task transfer Usage: algokit task transfer [OPTIONS] Transfer algos or assets from one account to another. @@ -24,14 +26,14 @@ Options: -h, --help Show this message and exit. ``` -> Note: If you use a wallet address for the `sender` argument, you'll be asked for the mnemonic phrase. To use a wallet alias instead, see the [wallet aliasing](wallet.md) task. For wallet aliases, the sender must have a stored `private key`, but the receiver doesn't need one. This is because the sender signs and sends the transfer transaction, while the receiver reference only needs a valid Algorand address. +> Note: If you use a wallet address for the `sender` argument, you'll be asked for the mnemonic phrase. To use a wallet alias instead, see the [wallet aliasing](/algokit-cli/features/tasks/wallet/) task. For wallet aliases, the sender must have a stored `private key`, but the receiver doesn't need one. This is because the sender signs and sends the transfer transaction, while the receiver reference only needs a valid Algorand address. ## Examples ### Transfer algo between accounts on LocalNet ```bash -$ ~ algokit task transfer -s {SENDER_ALIAS OR SENDER_ADDRESS} -r {RECEIVER_ALIAS OR RECEIVER_ADDRESS} -a {AMOUNT} +algokit task transfer -s {SENDER_ALIAS OR SENDER_ADDRESS} -r {RECEIVER_ALIAS OR RECEIVER_ADDRESS} -a {AMOUNT} ``` By default: @@ -42,7 +44,7 @@ By default: ### Transfer asset between accounts on TestNet ```bash -$ ~ algokit task transfer -s {SENDER_ALIAS OR SENDER_ADDRESS} -r {RECEIVER_ALIAS OR RECEIVER_ADDRESS} -a {AMOUNT} --id {ASSET_ID} --network testnet +algokit task transfer -s {SENDER_ALIAS OR SENDER_ADDRESS} -r {RECEIVER_ALIAS OR RECEIVER_ADDRESS} -a {AMOUNT} --id {ASSET_ID} --network testnet ``` By default: @@ -51,4 +53,4 @@ By default: ## Further Reading -For in-depth details, visit the [transfer section](../../cli/index.md#transfer) in the AlgoKit CLI reference documentation. +For in-depth details, visit the [transfer section](/algokit-cli/cli/#transfer) in the AlgoKit CLI reference documentation. diff --git a/docs/features/tasks/vanity_address.md b/docs/src/content/docs/features/tasks/vanity_address.md similarity index 77% rename from docs/features/tasks/vanity_address.md rename to docs/src/content/docs/features/tasks/vanity_address.md index d8d9c3609..2a8ecf128 100644 --- a/docs/features/tasks/vanity_address.md +++ b/docs/src/content/docs/features/tasks/vanity_address.md @@ -1,4 +1,6 @@ -# AlgoKit Task Vanity Address +--- +title: "AlgoKit Task Vanity Address" +--- The AlgoKit Vanity Address feature allows you to generate a vanity Algorand address. A vanity address is an address that contains a specific keyword in it. The keyword can only include uppercase letters A-Z and numbers 2-7. The longer the keyword, the longer it may take to generate a matching address. @@ -7,7 +9,7 @@ The AlgoKit Vanity Address feature allows you to generate a vanity Algorand addr Available commands and possible usage as follows: ```bash -$ ~ algokit task vanity-address +algokit task vanity-address Usage: algokit task vanity-address [OPTIONS] KEYWORD Generate a vanity Algorand address. Your KEYWORD can only include letters A - Z and numbers 2 - 7. Keeping your @@ -30,27 +32,27 @@ Options: Generate a vanity address with the keyword "ALGO" at the start of the address with default output to `stdout`: ```bash -$ ~ algokit task vanity-address ALGO +algokit task vanity-address ALGO ``` Generate a vanity address with the keyword "ALGO" at the start of the address with output to a file: ```bash -$ ~ algokit task vanity-address ALGO -o file -f vanity-address.txt +algokit task vanity-address ALGO -o file -f vanity-address.txt ``` Generate a vanity address with the keyword "ALGO" anywhere in the address with output to a file: ```bash -$ ~ algokit task vanity-address ALGO -m anywhere -o file -f vanity-address.txt +algokit task vanity-address ALGO -m anywhere -o file -f vanity-address.txt ``` -Generate a vanity address with the keyword "ALGO" at the start of the address and store into a [wallet alias](wallet.md): +Generate a vanity address with the keyword "ALGO" at the start of the address and store into a [wallet alias](/algokit-cli/features/tasks/wallet/): ```bash -$ ~ algokit task vanity-address ALGO -o alias -a my-vanity-address +algokit task vanity-address ALGO -o alias -a my-vanity-address ``` ## Further Reading -For in-depth details, visit the [vanity-address section](../../cli/index.md#vanity-address) in the AlgoKit CLI reference documentation. +For in-depth details, visit the [vanity-address section](/algokit-cli/cli/#vanity-address) in the AlgoKit CLI reference documentation. diff --git a/docs/features/tasks/wallet.md b/docs/src/content/docs/features/tasks/wallet.md similarity index 95% rename from docs/features/tasks/wallet.md rename to docs/src/content/docs/features/tasks/wallet.md index e77fa8c05..85c2475aa 100644 --- a/docs/features/tasks/wallet.md +++ b/docs/src/content/docs/features/tasks/wallet.md @@ -1,4 +1,6 @@ -# AlgoKit Task Wallet +--- +title: "AlgoKit Task Wallet" +--- Manage your Algorand addresses and accounts effortlessly with the AlgoKit Wallet feature. This feature allows you to create short aliases for your addresses and accounts on AlgoKit CLI. @@ -7,7 +9,7 @@ Manage your Algorand addresses and accounts effortlessly with the AlgoKit Wallet Available commands and possible usage as follows: ```bash -$ ~ algokit task wallet +algokit task wallet Usage: algokit task wallet [OPTIONS] COMMAND [ARGS]... Create short aliases for your addresses and accounts on AlgoKit CLI. @@ -94,4 +96,4 @@ WSL2 environments don't have a keyring backend installed by default. If you want ## Further Reading -For in-depth details, visit the [wallet section](../../cli/index.md#wallet) in the AlgoKit CLI reference documentation. +For in-depth details, visit the [wallet section](/algokit-cli/cli/#wallet) in the AlgoKit CLI reference documentation. diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx new file mode 100644 index 000000000..85203e54c --- /dev/null +++ b/docs/src/content/docs/index.mdx @@ -0,0 +1,76 @@ +--- +title: AlgoKit CLI +description: The one-stop shop tool for developers building on the Algorand network +template: splash +hero: + title: AlgoKit CLI + tagline: The one-stop shop tool for developers building on the Algorand network + actions: + - text: Get Started + link: /algokit-cli/tutorials/intro/ + icon: right-arrow + - text: CLI Reference + link: /algokit-cli/cli/ + variant: minimal +--- + +import { Card, CardGrid, Tabs, TabItem } from '@astrojs/starlight/components'; + +## Installation + + + + ```bash + brew install algorandfoundation/tap/algokit + ``` + + + ```bash + winget install AlgoKit + ``` + + + ```bash + pipx install algokit + ``` + + + +## Quick Start + +```bash +# Verify installation +algokit --version + +# Create a new project from a template +algokit init + +# Start a local Algorand network +algokit localnet start + +# Explore the network with lora +algokit explore +``` + +## Features + + + + Quickly scaffold new Algorand projects from official templates or community templates. + + + Spin up a local isolated Algorand network for development and testing. + + + Compile Algorand Python and other smart contract languages to AVM bytecode. + + + Deploy smart contracts to LocalNet, TestNet or MainNet with a single command. + + + Perform blockchain operations: send, sign, mint, transfer assets and more. + + + Generate typed clients and other code artifacts for your Algorand project. + + \ No newline at end of file diff --git a/docs/tutorials/algokit-template.md b/docs/src/content/docs/tutorials/algokit-template.md similarity index 98% rename from docs/tutorials/algokit-template.md rename to docs/src/content/docs/tutorials/algokit-template.md index ed86d7762..268742f42 100644 --- a/docs/tutorials/algokit-template.md +++ b/docs/src/content/docs/tutorials/algokit-template.md @@ -1,4 +1,6 @@ -# Creating AlgoKit Templates +--- +title: "Creating AlgoKit Templates" +--- This README serves as a guide on how to create custom templates for AlgoKit, a tool for initializing Algorand smart contract projects. Creating templates in AlgoKit involves the use of various configuration files and a templating engine to generate project structures that are tailored to your needs. @@ -172,7 +174,7 @@ python_path: After mastering the use of `copier` and building your templates based on the official AlgoKit template repositories, you can enhance your proficiency by learning to define `custom generators`. Essentially, generators are smaller-scope `copier` templates designed to provide additional functionality after a project has been initialized from the template. -For example, the official [`algokit-python-template`](https://github.com/algorandfoundation/algokit-python-template/tree/main/template_content) incorporates a generator in the `.algokit/generators` directory. This generator can be utilized to execute auxiliary tasks on AlgoKit projects that are initiated from this template, like adding new smart contracts to an existing project. For a comprehensive understanding, please consult the [`architecture decision record`](../architecture-decisions/2023-07-19_advanced_generate_command.md) and [`algokit generate documentation`](../features/generate.md). +For example, the official [`algokit-python-template`](https://github.com/algorandfoundation/algokit-python-template/tree/main/template_content) incorporates a generator in the `.algokit/generators` directory. This generator can be utilized to execute auxiliary tasks on AlgoKit projects that are initiated from this template, like adding new smart contracts to an existing project. For a comprehensive understanding, please consult the [`architecture decision record`](/algokit-cli/architecture-decisions/2023-07-19_advanced_generate_command/) and [`algokit generate documentation`](/algokit-cli/features/generate/). #### How to Create a Generator diff --git a/docs/src/content/docs/tutorials/intro.md b/docs/src/content/docs/tutorials/intro.md new file mode 100644 index 000000000..4dcfe3900 --- /dev/null +++ b/docs/src/content/docs/tutorials/intro.md @@ -0,0 +1,173 @@ +--- +title: "AlgoKit Quick Start Tutorial" +--- + +AlgoKit is the primary tool used by the Algorand community to develop smart contracts on the Algorand blockchain. It provides the capabilities to develop, test and deploy Algorand smart contracts within minutes! This guide is intended to help you setup AlgoKit and to start developing your application. + +## Quick start videos + +If you prefer videos, take a look at this 10 minute guide to getting started. + +[![Learn How to Build on Algorand in 10 Minutes](/algokit-cli/images/algokit-intro-video-thumbnail.jpg)](https://www.youtube.com/embed/dow6U8DxOGc) + +Detailed video guides for both [Windows](https://www.youtube.com/embed/22RvINnZsRo) and [Mac](https://www.youtube.com/embed/zsurtpCGmgE) are also available. + +> Please note, the videos above are to be refreshed to cover v2.0 features. For now, its best to follow the instructions below to get started. + +## Prequisites + +This guide presents installing AlgoKit using an OS agnostic procedure. For OS specific instructions take a look that the [AlgoKit install](https://github.com/algorandfoundation/algokit-cli/blob/main/README.md#install) guide. + +Before proceeding, ensure you have the following components installed: + +- [Python 3.10](https://www.python.org/downloads/) or higher +- [pipx](https://pypa.github.io/pipx/#on-linux-install-via-pip-requires-pip-190-or-later) +- [git](https://github.com/git-guides/install-git#install-git) +- [Docker](https://docs.docker.com/desktop/install/mac-install/) (or [Podman](https://podman.io/getting-started/installation/), see [details](/algokit-cli/features/localnet/#podman-support)) +- [VSCode](https://code.visualstudio.com/download) + +## Install AlgoKit + +To install AlgoKit, run the following command from a terminal. + +```shell +pipx install algokit +``` + +After the installation completes, **restart the terminal**. + +For more detailed installation documentation, see the [official installation guide](https://github.com/algorandfoundation/algokit-cli#install). + +> Please note, `pipx` is only one of the supported installation methods. You can also install AlgoKit via `brew` and _soon_ `winget` and `snap` as pre-build binaries. Refer to the official installation guide. + +## Verify the Installation + +To verify AlgoKit Installed correctly run the following. + +```shell +algokit --version +``` + +Output similar to the following should be displayed: + +```shell +algokit, version 2.0.3 # or higher +``` + +## Start a LocalNet + +AlgoKit supports using a [local version of the Algorand blockchain](/algokit-cli/features/localnet/). To start an instance of this LocalNet run the following command from the terminal: + +```shell +algokit localnet start +``` + +This should start an instance of the LocalNet within docker. If you open the Docker Desktop application you should see something similar to the following: + +![Docker Desktop LocalNet Instance](/algokit-cli/images/localnet.png) + +## Create an AlgoKit project + +Now that AlgoKit is installed, you can rapidly create a new project to get started quickly. This can be done by running: + +```shell +algokit init +``` + +This will launch a guided menu system to create a specific project tailored to your needs. The templates are basic starter applications for various Algorand development scenarios. To read more about templates checkout AlgoKit detailed documentation. + +For now we'll use the `python` template, which is a lightweight starting point for learning Algorand smart contract development using Algorand Python. You can initialize a project using this template by running: + +```shell +algokit init -t python -a preset_name "starter" +``` + +Next, you will be prompted for the name of your project. Finally, select the default value for the rest of the prompts (enter). + +Once finished, (if you have it installed) VS Code should automatically be opened with the initialised project and you will be prompted to install appropriate VS Code extensions. This starter app will contain one smart contract (built using the [Algorand Python](https://algorandfoundation.github.io/puya/) language) named `contract.py`, in the `smart_contracts/hello_world` folder, with one method (`hello`) that takes a `String` and returns a `String`. Notice that within the contract folder, there is a `deploy_config.py` which defines the parameters for deployment of your smart contract to the target chain (Algorand TestNet, Algorand MainNet, Algorand LocalNet or else). + +![AlgoKit Playground Contract](/algokit-cli/images/algokitplayground.png) + +## AlgoKit Project structure + +The structure of your fresh algokit project instance will look similar to below: + +```bash +. +├── .algokit.toml # Configuration for AlgoKit projects in the workspace. +├── README.md # Quick start guide for the AlgoKit Workspace. +├── {your_workspace|project_name}.code-workspace +└── projects + └── {your_project_name} # Root directory for the smart contract project. To add more projects into your algokit workspace run 'algokit init' from the root of your workspace repository. + ├── README.md # Quick start on Algorand Python smart contract template based project. + ├── .algokit # Hidden folder for AlgoKit AVM debugger and custom generators. + ├── .algokit.toml # Project-specific commands and custom generator references. + ├── poetry.lock + ├── poetry.toml # Dependency definitions for {your_project_name}. + ├── pyproject.toml # Project definitions for {your_project_name}. + └── smart_contracts + ├── README.md # Guide for adding new smart contracts. + ├── ... + ├── hello_world # Contract logic for 'hello_world'. + │ ├── contract.py # Contract logic. + │ └── deploy_config.py # Deployment logic for 'hello_world'. + └── helpers # Helper functions for contract build and deployment. +``` + +Additionally, each official smart contract template includes an interactive codespace walkthrough powered by [CodeTour](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour). + +To start the interactive walkthrough, install the extension and click on the green play button in the left bottom corner of the `Explorer` pane as demonstrated on the screenshot below (See `Getting Started with Your AlgoKit Project`). + +![CodeTour Play Button](/algokit-cli/images/algokitcodetour.png) + +Upon execution, the walkthrough will guide you through the key components of your fresh AlgoKit project, which is an important prerequisite to learn before running and deploying your first smart contract. Certainly, not because its hard to learn, but because it will save you a lot of time and effort having the correct foundations. + +## Run the Demo Application + +Once the `Algorand Python` based project is created, you can get started by building and deploying your first smart contract. There are a few possible ways to do so as demonstrated on the following video. + +[![Watch the video](https://ipfs.algonode.xyz/ipfs/Qmc9mRaPoDyhUFmek4ETxVfKUKzUg9pf3Tss5xwkBGdQis)](https://ipfs.algonode.xyz/ipfs/Qma6gNqxsSFc9Jbh8kBTZyVLv5gqFj1xnrsjoeT6MAAwCw/) + +The App ID of the deployed contract and its Algorand address is displayed, followed by the message returned from the smart contract call (`Hello, Python`). + +1. Start LocalNet +2. Build the smart contract. Notice how a folder named `artifacts` is created with the [AVM (Algorand Virtual Machine)](https://dev.algorand.co/concepts/smart-contracts/avm/) related artifacts for deploying your smart contract. +3. Deploy and call the `HelloWorld` smart contract (from `contract.py` file). + +After execution, the `App ID` of the deployed contract and its Algorand address are displayed, followed by the message returned from the smart contract call (`Hello, world`). + +At this point you have deployed a simple contract to a LocalNet Algorand network (running in your Docker environment) and called it successfully! + +Additionally, you can find the native AVM related artifacts and the appropriate smart contract manifest JSON files have been output to the `artifacts` folder. Note that in this example, AVM bytecode is compiled using the `PuyaPy` compiler, which is what `Algorand Python` relies on to compile your Python smart contract code to TEAL ([Transaction Execution Approval Language](https://dev.algorand.co/concepts/smart-contracts/languages/teal)). + +### Using AlgoKit CLI to build and deploy contracts + +When using official AlgoKit templates via `algokit init`, you can manage your projects using the AlgoKit CLI at the convenience of your terminal. + +For example, to achieve the same results as in the demo earlier, build and deploy the `HelloWorld` contract from the `contract.py` file by running the following command from the terminal: + +```shell +algokit project run build +``` + +This command will recompile your python contracts from `contract.py` and produce the necessary artefacts for deploying your contract. + +```shell +algokit project deploy localnet +``` + +This will then deploy to your LocalNet instance and display the same output as in the earlier demo. + +> Please note, as highlighted in the [structure](#algokit-project-structure) section above, the `project run ...` commands are defined in the respective `.algokit.toml` file under `[project]` sections. + +## Next steps + +We have only covered a tiny fraction of the capabilities of the AlgoKit CLI and its related ecosystem of templates and utilities for an efficient developer experience. + +- To get the most out of `AlgoKit`, we recommend to get started with learning more about AlgoKit and what you can do with it by checking out our extensive [AlgoKit CLI documentation](/algokit-cli/features/overview/). +- Explore the `README.md` files at the root of any project created via `algokit init`. All official AlgoKit templates include detailed quick started guides, an interactive code tour and various presets which can be customized to your needs. +- To learn more about `Algorand Python`, take a look at the [documentation](https://algorandfoundation.github.io/puya/). +- To learn more about the commands demonstrated in this tutorial, refer to [`init`](/algokit-cli/features/init/) and [`project`](/algokit-cli/features/project/) to get a comprehensive understanding of their further capabilities. +- If you'd like to learn more on structuring your `AlgoKit Project` as a monorepo, refer to `workspace` mode as described in [`init`](/algokit-cli/features/init/#workspaces-vs-standalone-projects). You can also pass the `--no-workspace` flag to setup a standalone algokit project, if preferred. +- If you'd like to **create your own** `AlgoKit` template, refer to the [template tutorial](/algokit-cli/tutorials/algokit-template/). +- More information on Algorand smart contracts is also available in the [smart contract documentation](https://dev.algorand.co/concepts/smart-contracts/overview). diff --git a/docs/tutorials/smart-contracts.md b/docs/src/content/docs/tutorials/smart-contracts.md similarity index 80% rename from docs/tutorials/smart-contracts.md rename to docs/src/content/docs/tutorials/smart-contracts.md index 786587a39..6db209e4d 100644 --- a/docs/tutorials/smart-contracts.md +++ b/docs/src/content/docs/tutorials/smart-contracts.md @@ -1,4 +1,6 @@ -# Smart Contract Tutorial +--- +title: "Smart Contract Tutorial" +--- _TODO_ diff --git a/docs/src/styles/cli-reference.css b/docs/src/styles/cli-reference.css new file mode 100644 index 000000000..73b9d7022 --- /dev/null +++ b/docs/src/styles/cli-reference.css @@ -0,0 +1,27 @@ +/* + * CLI Reference styling for auto-generated sphinx-click docs. + * + * Styles the generated CLI reference page with monospace headings + * and clear visual hierarchy for commands, subcommands, and options. + */ + +/* ── Command headings (H3) — monospace, reduced size ── */ +.cli-ref h3 { + font-family: var(--sl-font-mono, ui-monospace, monospace); + font-size: var(--sl-text-base, 1rem); + font-weight: 400; + margin-top: 2rem; + padding: 0.25rem 0; + border-bottom: 1px solid var(--sl-color-gray-6, #343841); +} + +/* ── Subcommand / option headings (H4) — compact ── */ +.cli-ref h4 { + font-family: var(--sl-font-mono, ui-monospace, monospace); + font-size: var(--sl-text-sm, 0.875rem); + font-weight: 600; + margin-top: 1.25rem; + margin-bottom: 0.25rem; + padding: 0.25rem 0; + border-bottom: 1px solid var(--sl-color-gray-6, #343841); +} \ No newline at end of file diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 000000000..8bf91d3bb --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] +} diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 000000000..fe1ddb43d --- /dev/null +++ b/poetry.lock @@ -0,0 +1,3389 @@ +# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. + +[[package]] +name = "alabaster" +version = "0.7.16" +description = "A light, configurable Sphinx theme" +optional = false +python-versions = ">=3.9" +groups = ["docs"] +files = [ + {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, + {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, +] + +[[package]] +name = "algokit-utils" +version = "5.0.0a7" +description = "Utilities for Algorand development for use by AlgoKit" +optional = false +python-versions = "<4,>=3.10" +groups = ["main"] +files = [ + {file = "algokit_utils-5.0.0a7-py3-none-any.whl", hash = "sha256:e409dd838e6d29aca978fe91ced43e7f94d2120ab7025eb7ccf548d2849589e1"}, + {file = "algokit_utils-5.0.0a7.tar.gz", hash = "sha256:97212bfdf2854de7e41f8e9ec2da7194a352c90c527e1ca4a11493721b60d8aa"}, +] + +[package.dependencies] +httpx = ">=0.23.1,<=0.28.1" +msgpack = ">=1.0.0,<2" +msgpack-types = ">=0.2.0,<=0.5.0" +pycryptodomex = ">=3.19,<4" +pynacl = ">=1.4.0,<2" +typing-extensions = ">=4.6.0" + +[[package]] +name = "allpairspy" +version = "2.5.1" +description = "Pairwise test combinations generator" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "allpairspy-2.5.1-py3-none-any.whl", hash = "sha256:3f97cbac2bbee86f4bfceffd0fd91dca740a120c78e9368af2bad81a2b3426e2"}, + {file = "allpairspy-2.5.1.tar.gz", hash = "sha256:f69d31a3b56eee119d1ec6063e9c732dd44fbba352ef738cb22d9699fc4009fe"}, +] + +[package.extras] +test = ["pytest (>=6.0.1)", "pytest-md-report (>=0.3)"] + +[[package]] +name = "altgraph" +version = "0.17.4" +description = "Python graph (network) package" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff"}, + {file = "altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406"}, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[[package]] +name = "anyio" +version = "4.9.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.9" +groups = ["main", "dev"] +files = [ + {file = "anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"}, + {file = "anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" +typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} + +[package.extras] +doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] +test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] +trio = ["trio (>=0.26.1)"] + +[[package]] +name = "approval-utilities" +version = "7.4.0" +description = "Utilities for your production code that work well with approvaltests" +optional = false +python-versions = ">=3.6.1" +groups = ["dev"] +files = [ + {file = "approval_utilities-7.4.0-py3-none-any.whl", hash = "sha256:d11f545ad318f3520e997657aaeb6511521a4d0b647a0868037ca817af7c73b3"}, + {file = "approval_utilities-7.4.0.tar.gz", hash = "sha256:8e0b146716db2f7d95d01726947438904760a6cb005aa391cee6f7a623d627ee"}, +] + +[[package]] +name = "approvaltests" +version = "7.4.0" +description = "Assertion/verification library to aid testing" +optional = false +python-versions = ">=3.6.1" +groups = ["dev"] +files = [ + {file = "approvaltests-7.4.0-py3-none-any.whl", hash = "sha256:64e8798f843f44ffd047935f18e8ec850caf9d4f924b9b24456008102cbb6aca"}, + {file = "approvaltests-7.4.0.tar.gz", hash = "sha256:e09b2f2af6cd049d71a3dcdc7b3bb4c2cd887cc5eb4b1294b557675360c5f90d"}, +] + +[package.dependencies] +allpairspy = ">=2.1.0" +approval-utilities = "7.4.0" +beautifulsoup4 = ">=4.4.0" +empty-files = ">=0.0.3" +mrjob = ">=0.7.4" +pyperclip = ">=1.5.29" +pytest = ">=4.0.0" +typing-extensions = ">=3.6.2" + +[[package]] +name = "babel" +version = "2.17.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.8" +groups = ["docs"] +files = [ + {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"}, + {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, +] + +[package.extras] +dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] + +[[package]] +name = "backports-tarfile" +version = "1.2.0" +description = "Backport of CPython tarfile module" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version < \"3.12\"" +files = [ + {file = "backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34"}, + {file = "backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["jaraco.test", "pytest (!=8.0.*)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)"] + +[[package]] +name = "bases" +version = "0.3.0" +description = "Python library for general Base-N encodings." +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "bases-0.3.0-py3-none-any.whl", hash = "sha256:a2fef3366f3e522ff473d2e95c21523fe8e44251038d5c6150c01481585ebf5b"}, + {file = "bases-0.3.0.tar.gz", hash = "sha256:70f04a4a45d63245787f9e89095ca11042685b6b64b542ad916575ba3ccd1570"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0" +typing-validation = ">=1.1.0" + +[package.extras] +dev = ["base58", "mypy", "pylint", "pytest", "pytest-cov"] + +[[package]] +name = "beautifulsoup4" +version = "4.13.4" +description = "Screen-scraping library" +optional = false +python-versions = ">=3.7.0" +groups = ["dev"] +files = [ + {file = "beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b"}, + {file = "beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195"}, +] + +[package.dependencies] +soupsieve = ">1.2" +typing-extensions = ">=4.0.0" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "boolean-py" +version = "5.0" +description = "Define boolean algebras, create and parse boolean expressions and create custom boolean DSL." +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "boolean_py-5.0-py3-none-any.whl", hash = "sha256:ef28a70bd43115208441b53a045d1549e2f0ec6e3d08a9d142cbc41c1938e8d9"}, + {file = "boolean_py-5.0.tar.gz", hash = "sha256:60cbc4bad079753721d32649545505362c754e121570ada4658b852a3a318d95"}, +] + +[package.extras] +dev = ["build", "twine"] +docs = ["Sphinx (>=3.3.1)", "doc8 (>=0.8.1)", "sphinx-rtd-theme (>=0.5.0)", "sphinxcontrib-apidoc (>=0.3.0)"] +linting = ["black", "isort", "pycodestyle"] +testing = ["pytest (>=6,!=7.0.0)", "pytest-xdist (>=2)"] + +[[package]] +name = "cachecontrol" +version = "0.14.3" +description = "httplib2 caching for requests" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "cachecontrol-0.14.3-py3-none-any.whl", hash = "sha256:b35e44a3113f17d2a31c1e6b27b9de6d4405f84ae51baa8c1d3cc5b633010cae"}, + {file = "cachecontrol-0.14.3.tar.gz", hash = "sha256:73e7efec4b06b20d9267b441c1f733664f989fb8688391b670ca812d70795d11"}, +] + +[package.dependencies] +filelock = {version = ">=3.8.0", optional = true, markers = "extra == \"filecache\""} +msgpack = ">=0.5.2,<2.0.0" +requests = ">=2.16.0" + +[package.extras] +dev = ["CacheControl[filecache,redis]", "build", "cherrypy", "codespell[tomli]", "furo", "mypy", "pytest", "pytest-cov", "ruff", "sphinx", "sphinx-copybutton", "tox", "types-redis", "types-requests"] +filecache = ["filelock (>=3.8.0)"] +redis = ["redis (>=2.10.5)"] + +[[package]] +name = "certifi" +version = "2025.4.26" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +groups = ["main", "dev", "docs"] +files = [ + {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"}, + {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"}, +] + +[[package]] +name = "cffi" +version = "1.17.1" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, +] +markers = {dev = "platform_python_implementation != \"PyPy\""} + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7" +groups = ["main", "dev", "docs"] +files = [ + {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-win32.whl", hash = "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"}, + {file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"}, + {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"}, +] + +[[package]] +name = "click" +version = "8.1.8" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +groups = ["main", "dev", "docs"] +files = [ + {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, + {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "click-log" +version = "0.4.0" +description = "Logging integration for Click" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "click-log-0.4.0.tar.gz", hash = "sha256:3970f8570ac54491237bcdb3d8ab5e3eef6c057df29f8c3d1151a51a9c23b975"}, + {file = "click_log-0.4.0-py2.py3-none-any.whl", hash = "sha256:a43e394b528d52112af599f2fc9e4b7cf3c15f94e53581f74fa6867e68c91756"}, +] + +[package.dependencies] +click = "*" + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "dev", "docs"] +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] +markers = {docs = "platform_system == \"Windows\" or sys_platform == \"win32\""} + +[[package]] +name = "copier" +version = "9.10.1" +description = "A library for rendering project templates." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "copier-9.10.1-py3-none-any.whl", hash = "sha256:8b1b406367c67e5ee389778246cea18cddd55e71bfc6503d5fa13fe73304407a"}, + {file = "copier-9.10.1.tar.gz", hash = "sha256:ba2d729465508da04a62bc9b76eed13d952aa7634a74a69519252fcf8a54d94e"}, +] + +[package.dependencies] +colorama = ">=0.4.6" +dunamai = ">=1.7.0" +funcy = ">=1.17" +jinja2 = ">=3.1.5" +jinja2-ansible-filters = ">=1.3.1" +packaging = ">=23.0" +pathspec = ">=0.9.0" +platformdirs = ">=4.3.6" +plumbum = ">=1.6.9" +prompt-toolkit = "<3.0.52" +pydantic = ">=2.4.2" +pygments = ">=2.7.1" +pyyaml = ">=5.3.1" +questionary = ">=1.8.1" +typing-extensions = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} + +[[package]] +name = "coverage" +version = "7.8.0" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "coverage-7.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2931f66991175369859b5fd58529cd4b73582461877ecfd859b6549869287ffe"}, + {file = "coverage-7.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52a523153c568d2c0ef8826f6cc23031dc86cffb8c6aeab92c4ff776e7951b28"}, + {file = "coverage-7.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c8a5c139aae4c35cbd7cadca1df02ea8cf28a911534fc1b0456acb0b14234f3"}, + {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a26c0c795c3e0b63ec7da6efded5f0bc856d7c0b24b2ac84b4d1d7bc578d676"}, + {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821f7bcbaa84318287115d54becb1915eece6918136c6f91045bb84e2f88739d"}, + {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a321c61477ff8ee705b8a5fed370b5710c56b3a52d17b983d9215861e37b642a"}, + {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ed2144b8a78f9d94d9515963ed273d620e07846acd5d4b0a642d4849e8d91a0c"}, + {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:042e7841a26498fff7a37d6fda770d17519982f5b7d8bf5278d140b67b61095f"}, + {file = "coverage-7.8.0-cp310-cp310-win32.whl", hash = "sha256:f9983d01d7705b2d1f7a95e10bbe4091fabc03a46881a256c2787637b087003f"}, + {file = "coverage-7.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a570cd9bd20b85d1a0d7b009aaf6c110b52b5755c17be6962f8ccd65d1dbd23"}, + {file = "coverage-7.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7ac22a0bb2c7c49f441f7a6d46c9c80d96e56f5a8bc6972529ed43c8b694e27"}, + {file = "coverage-7.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf13d564d310c156d1c8e53877baf2993fb3073b2fc9f69790ca6a732eb4bfea"}, + {file = "coverage-7.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5761c70c017c1b0d21b0815a920ffb94a670c8d5d409d9b38857874c21f70d7"}, + {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ff52d790c7e1628241ffbcaeb33e07d14b007b6eb00a19320c7b8a7024c040"}, + {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d39fc4817fd67b3915256af5dda75fd4ee10621a3d484524487e33416c6f3543"}, + {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b44674870709017e4b4036e3d0d6c17f06a0e6d4436422e0ad29b882c40697d2"}, + {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f99eb72bf27cbb167b636eb1726f590c00e1ad375002230607a844d9e9a2318"}, + {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b571bf5341ba8c6bc02e0baeaf3b061ab993bf372d982ae509807e7f112554e9"}, + {file = "coverage-7.8.0-cp311-cp311-win32.whl", hash = "sha256:e75a2ad7b647fd8046d58c3132d7eaf31b12d8a53c0e4b21fa9c4d23d6ee6d3c"}, + {file = "coverage-7.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3043ba1c88b2139126fc72cb48574b90e2e0546d4c78b5299317f61b7f718b78"}, + {file = "coverage-7.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbb5cc845a0292e0c520656d19d7ce40e18d0e19b22cb3e0409135a575bf79fc"}, + {file = "coverage-7.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4dfd9a93db9e78666d178d4f08a5408aa3f2474ad4d0e0378ed5f2ef71640cb6"}, + {file = "coverage-7.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f017a61399f13aa6d1039f75cd467be388d157cd81f1a119b9d9a68ba6f2830d"}, + {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0915742f4c82208ebf47a2b154a5334155ed9ef9fe6190674b8a46c2fb89cb05"}, + {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a40fcf208e021eb14b0fac6bdb045c0e0cab53105f93ba0d03fd934c956143a"}, + {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a1f406a8e0995d654b2ad87c62caf6befa767885301f3b8f6f73e6f3c31ec3a6"}, + {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77af0f6447a582fdc7de5e06fa3757a3ef87769fbb0fdbdeba78c23049140a47"}, + {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f2d32f95922927186c6dbc8bc60df0d186b6edb828d299ab10898ef3f40052fe"}, + {file = "coverage-7.8.0-cp312-cp312-win32.whl", hash = "sha256:769773614e676f9d8e8a0980dd7740f09a6ea386d0f383db6821df07d0f08545"}, + {file = "coverage-7.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5d2b9be5b0693cf21eb4ce0ec8d211efb43966f6657807f6859aab3814f946b"}, + {file = "coverage-7.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ac46d0c2dd5820ce93943a501ac5f6548ea81594777ca585bf002aa8854cacd"}, + {file = "coverage-7.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:771eb7587a0563ca5bb6f622b9ed7f9d07bd08900f7589b4febff05f469bea00"}, + {file = "coverage-7.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42421e04069fb2cbcbca5a696c4050b84a43b05392679d4068acbe65449b5c64"}, + {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554fec1199d93ab30adaa751db68acec2b41c5602ac944bb19187cb9a41a8067"}, + {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aaeb00761f985007b38cf463b1d160a14a22c34eb3f6a39d9ad6fc27cb73008"}, + {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:581a40c7b94921fffd6457ffe532259813fc68eb2bdda60fa8cc343414ce3733"}, + {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f319bae0321bc838e205bf9e5bc28f0a3165f30c203b610f17ab5552cff90323"}, + {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04bfec25a8ef1c5f41f5e7e5c842f6b615599ca8ba8391ec33a9290d9d2db3a3"}, + {file = "coverage-7.8.0-cp313-cp313-win32.whl", hash = "sha256:dd19608788b50eed889e13a5d71d832edc34fc9dfce606f66e8f9f917eef910d"}, + {file = "coverage-7.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:a9abbccd778d98e9c7e85038e35e91e67f5b520776781d9a1e2ee9d400869487"}, + {file = "coverage-7.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:18c5ae6d061ad5b3e7eef4363fb27a0576012a7447af48be6c75b88494c6cf25"}, + {file = "coverage-7.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:95aa6ae391a22bbbce1b77ddac846c98c5473de0372ba5c463480043a07bff42"}, + {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e013b07ba1c748dacc2a80e69a46286ff145935f260eb8c72df7185bf048f502"}, + {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d766a4f0e5aa1ba056ec3496243150698dc0481902e2b8559314368717be82b1"}, + {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad80e6b4a0c3cb6f10f29ae4c60e991f424e6b14219d46f1e7d442b938ee68a4"}, + {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b87eb6fc9e1bb8f98892a2458781348fa37e6925f35bb6ceb9d4afd54ba36c73"}, + {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d1ba00ae33be84066cfbe7361d4e04dec78445b2b88bdb734d0d1cbab916025a"}, + {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f3c38e4e5ccbdc9198aecc766cedbb134b2d89bf64533973678dfcf07effd883"}, + {file = "coverage-7.8.0-cp313-cp313t-win32.whl", hash = "sha256:379fe315e206b14e21db5240f89dc0774bdd3e25c3c58c2c733c99eca96f1ada"}, + {file = "coverage-7.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e4b6b87bb0c846a9315e3ab4be2d52fac905100565f4b92f02c445c8799e257"}, + {file = "coverage-7.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa260de59dfb143af06dcf30c2be0b200bed2a73737a8a59248fcb9fa601ef0f"}, + {file = "coverage-7.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:96121edfa4c2dfdda409877ea8608dd01de816a4dc4a0523356067b305e4e17a"}, + {file = "coverage-7.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8af63b9afa1031c0ef05b217faa598f3069148eeee6bb24b79da9012423b82"}, + {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89b1f4af0d4afe495cd4787a68e00f30f1d15939f550e869de90a86efa7e0814"}, + {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ec0be97723ae72d63d3aa41961a0b9a6f5a53ff599813c324548d18e3b9e8c"}, + {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a1d96e780bdb2d0cbb297325711701f7c0b6f89199a57f2049e90064c29f6bd"}, + {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f1d8a2a57b47142b10374902777e798784abf400a004b14f1b0b9eaf1e528ba4"}, + {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cf60dd2696b457b710dd40bf17ad269d5f5457b96442f7f85722bdb16fa6c899"}, + {file = "coverage-7.8.0-cp39-cp39-win32.whl", hash = "sha256:be945402e03de47ba1872cd5236395e0f4ad635526185a930735f66710e1bd3f"}, + {file = "coverage-7.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:90e7fbc6216ecaffa5a880cdc9c77b7418c1dcb166166b78dbc630d07f278cc3"}, + {file = "coverage-7.8.0-pp39.pp310.pp311-none-any.whl", hash = "sha256:b8194fb8e50d556d5849753de991d390c5a1edeeba50f68e3a9253fbd8bf8ccd"}, + {file = "coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7"}, + {file = "coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] + +[[package]] +name = "cryptography" +version = "44.0.3" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +optional = false +python-versions = "!=3.9.0,!=3.9.1,>=3.7" +groups = ["main", "dev"] +files = [ + {file = "cryptography-44.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:962bc30480a08d133e631e8dfd4783ab71cc9e33d5d7c1e192f0b7c06397bb88"}, + {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffc61e8f3bf5b60346d89cd3d37231019c17a081208dfbbd6e1605ba03fa137"}, + {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58968d331425a6f9eedcee087f77fd3c927c88f55368f43ff7e0a19891f2642c"}, + {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e28d62e59a4dbd1d22e747f57d4f00c459af22181f0b2f787ea83f5a876d7c76"}, + {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af653022a0c25ef2e3ffb2c673a50e5a0d02fecc41608f4954176f1933b12359"}, + {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:157f1f3b8d941c2bd8f3ffee0af9b049c9665c39d3da9db2dc338feca5e98a43"}, + {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:c6cd67722619e4d55fdb42ead64ed8843d64638e9c07f4011163e46bc512cf01"}, + {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b424563394c369a804ecbee9b06dfb34997f19d00b3518e39f83a5642618397d"}, + {file = "cryptography-44.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c91fc8e8fd78af553f98bc7f2a1d8db977334e4eea302a4bfd75b9461c2d8904"}, + {file = "cryptography-44.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:25cd194c39fa5a0aa4169125ee27d1172097857b27109a45fadc59653ec06f44"}, + {file = "cryptography-44.0.3-cp37-abi3-win32.whl", hash = "sha256:3be3f649d91cb182c3a6bd336de8b61a0a71965bd13d1a04a0e15b39c3d5809d"}, + {file = "cryptography-44.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:3883076d5c4cc56dbef0b898a74eb6992fdac29a7b9013870b34efe4ddb39a0d"}, + {file = "cryptography-44.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:5639c2b16764c6f76eedf722dbad9a0914960d3489c0cc38694ddf9464f1bb2f"}, + {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ffef566ac88f75967d7abd852ed5f182da252d23fac11b4766da3957766759"}, + {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:192ed30fac1728f7587c6f4613c29c584abdc565d7417c13904708db10206645"}, + {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7d5fe7195c27c32a64955740b949070f21cba664604291c298518d2e255931d2"}, + {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3f07943aa4d7dad689e3bb1638ddc4944cc5e0921e3c227486daae0e31a05e54"}, + {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cb90f60e03d563ca2445099edf605c16ed1d5b15182d21831f58460c48bffb93"}, + {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ab0b005721cc0039e885ac3503825661bd9810b15d4f374e473f8c89b7d5460c"}, + {file = "cryptography-44.0.3-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:3bb0847e6363c037df8f6ede57d88eaf3410ca2267fb12275370a76f85786a6f"}, + {file = "cryptography-44.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b0cc66c74c797e1db750aaa842ad5b8b78e14805a9b5d1348dc603612d3e3ff5"}, + {file = "cryptography-44.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6866df152b581f9429020320e5eb9794c8780e90f7ccb021940d7f50ee00ae0b"}, + {file = "cryptography-44.0.3-cp39-abi3-win32.whl", hash = "sha256:c138abae3a12a94c75c10499f1cbae81294a6f983b3af066390adee73f433028"}, + {file = "cryptography-44.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:5d186f32e52e66994dce4f766884bcb9c68b8da62d61d9d215bfe5fb56d21334"}, + {file = "cryptography-44.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:cad399780053fb383dc067475135e41c9fe7d901a97dd5d9c5dfb5611afc0d7d"}, + {file = "cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:21a83f6f35b9cc656d71b5de8d519f566df01e660ac2578805ab245ffd8523f8"}, + {file = "cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fc3c9babc1e1faefd62704bb46a69f359a9819eb0292e40df3fb6e3574715cd4"}, + {file = "cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:e909df4053064a97f1e6565153ff8bb389af12c5c8d29c343308760890560aff"}, + {file = "cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:dad80b45c22e05b259e33ddd458e9e2ba099c86ccf4e88db7bbab4b747b18d06"}, + {file = "cryptography-44.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:479d92908277bed6e1a1c69b277734a7771c2b78633c224445b5c60a9f4bc1d9"}, + {file = "cryptography-44.0.3-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:896530bc9107b226f265effa7ef3f21270f18a2026bc09fed1ebd7b66ddf6375"}, + {file = "cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9b4d4a5dbee05a2c390bf212e78b99434efec37b17a4bff42f50285c5c8c9647"}, + {file = "cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02f55fb4f8b79c1221b0961488eaae21015b69b210e18c386b69de182ebb1259"}, + {file = "cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:dd3db61b8fe5be220eee484a17233287d0be6932d056cf5738225b9c05ef4fff"}, + {file = "cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:978631ec51a6bbc0b7e58f23b68a8ce9e5f09721940933e9c217068388789fe5"}, + {file = "cryptography-44.0.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:5d20cc348cca3a8aa7312f42ab953a56e15323800ca3ab0706b8cd452a3a056c"}, + {file = "cryptography-44.0.3.tar.gz", hash = "sha256:fe19d8bc5536a91a24a8133328880a41831b6c5df54599a8417b62fe015d3053"}, +] + +[package.dependencies] +cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""] +docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""] +pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +sdist = ["build (>=1.0.0)"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["certifi (>=2024)", "cryptography-vectors (==44.0.3)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] +test-randomorder = ["pytest-randomly"] + +[[package]] +name = "cyclonedx-python-lib" +version = "9.1.0" +description = "Python library for CycloneDX" +optional = false +python-versions = "<4.0,>=3.8" +groups = ["dev"] +files = [ + {file = "cyclonedx_python_lib-9.1.0-py3-none-any.whl", hash = "sha256:55693fca8edaecc3363b24af14e82cc6e659eb1e8353e58b587c42652ce0fb52"}, + {file = "cyclonedx_python_lib-9.1.0.tar.gz", hash = "sha256:86935f2c88a7b47a529b93c724dbd3e903bc573f6f8bd977628a7ca1b5dadea1"}, +] + +[package.dependencies] +license-expression = ">=30,<31" +packageurl-python = ">=0.11,<2" +py-serializable = ">=2.0.0,<3.0.0" +sortedcontainers = ">=2.4.0,<3.0.0" + +[package.extras] +json-validation = ["jsonschema[format] (>=4.18,<5.0)"] +validation = ["jsonschema[format] (>=4.18,<5.0)", "lxml (>=4,<6)"] +xml-validation = ["lxml (>=4,<6)"] + +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["dev"] +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + +[[package]] +name = "distlib" +version = "0.3.9" +description = "Distribution utilities" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, + {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, +] + +[[package]] +name = "docutils" +version = "0.19" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.7" +groups = ["dev", "docs"] +files = [ + {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"}, + {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, +] + +[[package]] +name = "dotty-dict" +version = "1.3.1" +description = "Dictionary wrapper for quick access to deeply nested keys." +optional = false +python-versions = ">=3.5,<4.0" +groups = ["dev"] +files = [ + {file = "dotty_dict-1.3.1-py3-none-any.whl", hash = "sha256:5022d234d9922f13aa711b4950372a06a6d64cb6d6db9ba43d0ba133ebfce31f"}, + {file = "dotty_dict-1.3.1.tar.gz", hash = "sha256:4b016e03b8ae265539757a53eba24b9bfda506fb94fbce0bee843c6f05541a15"}, +] + +[[package]] +name = "dunamai" +version = "1.24.1" +description = "Dynamic version generation" +optional = false +python-versions = ">=3.5" +groups = ["main"] +files = [ + {file = "dunamai-1.24.1-py3-none-any.whl", hash = "sha256:4370e406d8ce195fc4b066b5c326bfa9adb269c4b8719b4e4fd90b63a2144bf7"}, + {file = "dunamai-1.24.1.tar.gz", hash = "sha256:3aa3348f77242da8628b23f11e89569343440f0f912bcef32a1fa891cf8e7215"}, +] + +[package.dependencies] +packaging = ">=20.9" + +[[package]] +name = "empty-files" +version = "0.0.9" +description = "Serves empty files of many types" +optional = false +python-versions = ">=3.7.1" +groups = ["dev"] +files = [ + {file = "empty-files-0.0.9.tar.gz", hash = "sha256:22e74de327271ef9592a661aaa53bb1d5fa6cfd539dac7315625c8b30b7292ae"}, + {file = "empty_files-0.0.9-py3-none-any.whl", hash = "sha256:9af04feacd5858d1255a00e76926a2d760f6d05c3c5a8df58abd6be21da742c2"}, +] + +[package.dependencies] +requests = "*" + +[[package]] +name = "exceptiongroup" +version = "1.2.2" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "python_version == \"3.10\"" +files = [ + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "execnet" +version = "2.1.1" +description = "execnet: rapid multi-Python deployment" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, + {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, +] + +[package.extras] +testing = ["hatch", "pre-commit", "pytest", "tox"] + +[[package]] +name = "filelock" +version = "3.18.0" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de"}, + {file = "filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] +typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] + +[[package]] +name = "funcy" +version = "2.0" +description = "A fancy and practical functional tools" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "funcy-2.0-py2.py3-none-any.whl", hash = "sha256:53df23c8bb1651b12f095df764bfb057935d49537a56de211b098f4c79614bb0"}, + {file = "funcy-2.0.tar.gz", hash = "sha256:3963315d59d41c6f30c04bc910e10ab50a3ac4a225868bfa96feed133df075cb"}, +] + +[[package]] +name = "gitdb" +version = "4.0.12" +description = "Git Object Database" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, + {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, +] + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.44" +description = "GitPython is a Python library used to interact with Git repositories" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, + {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, +] + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[package.extras] +doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] +test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] + +[[package]] +name = "h11" +version = "0.16.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, +] + +[[package]] +name = "html2text" +version = "2025.4.15" +description = "Turn HTML into equivalent Markdown-structured text." +optional = false +python-versions = ">=3.9" +groups = ["docs"] +files = [ + {file = "html2text-2025.4.15-py3-none-any.whl", hash = "sha256:00569167ffdab3d7767a4cdf589b7f57e777a5ed28d12907d8c58769ec734acc"}, + {file = "html2text-2025.4.15.tar.gz", hash = "sha256:948a645f8f0bc3abe7fd587019a2197a12436cd73d0d4908af95bfc8da337588"}, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, + {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.16" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<1.0)"] + +[[package]] +name = "httpx" +version = "0.28.1" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" + +[package.extras] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "identify" +version = "2.6.10" +description = "File identification library for Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "identify-2.6.10-py2.py3-none-any.whl", hash = "sha256:5f34248f54136beed1a7ba6a6b5c4b6cf21ff495aac7c359e1ef831ae3b8ab25"}, + {file = "identify-2.6.10.tar.gz", hash = "sha256:45e92fd704f3da71cc3880036633f48b4b7265fd4de2b57627cb157216eb7eb8"}, +] + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "idna" +version = "3.10" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.6" +groups = ["main", "dev", "docs"] +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] + +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["docs"] +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + +[[package]] +name = "importlib-metadata" +version = "8.7.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.9" +groups = ["main", "dev"] +files = [ + {file = "importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd"}, + {file = "importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000"}, +] +markers = {main = "python_version < \"3.12\""} + +[package.dependencies] +zipp = ">=3.20" + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +perf = ["ipython"] +test = ["flufl.flake8", "importlib_resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +type = ["pytest-mypy"] + +[[package]] +name = "iniconfig" +version = "2.1.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, +] + +[[package]] +name = "invoke" +version = "2.2.0" +description = "Pythonic task execution" +optional = false +python-versions = ">=3.6" +groups = ["dev"] +files = [ + {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"}, + {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, +] + +[[package]] +name = "jaraco-classes" +version = "3.4.0" +description = "Utility functions for Python class constructs" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790"}, + {file = "jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd"}, +] + +[package.dependencies] +more-itertools = "*" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)"] + +[[package]] +name = "jaraco-context" +version = "6.0.1" +description = "Useful decorators and context managers" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "jaraco.context-6.0.1-py3-none-any.whl", hash = "sha256:f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4"}, + {file = "jaraco_context-6.0.1.tar.gz", hash = "sha256:9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3"}, +] + +[package.dependencies] +"backports.tarfile" = {version = "*", markers = "python_version < \"3.12\""} + +[package.extras] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["portend", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] + +[[package]] +name = "jaraco-functools" +version = "4.1.0" +description = "Functools like those found in stdlib" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "jaraco.functools-4.1.0-py3-none-any.whl", hash = "sha256:ad159f13428bc4acbf5541ad6dec511f91573b90fba04df61dafa2a1231cf649"}, + {file = "jaraco_functools-4.1.0.tar.gz", hash = "sha256:70f7e0e2ae076498e212562325e805204fc092d7b4c17e0e86c959e249701a9d"}, +] + +[package.dependencies] +more-itertools = "*" + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["jaraco.classes", "pytest (>=6,!=8.1.*)"] +type = ["pytest-mypy"] + +[[package]] +name = "jeepney" +version = "0.9.0" +description = "Low-level, pure Python DBus protocol wrapper." +optional = false +python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "sys_platform == \"linux\"" +files = [ + {file = "jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683"}, + {file = "jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732"}, +] + +[package.extras] +test = ["async-timeout ; python_version < \"3.11\"", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"] +trio = ["trio"] + +[[package]] +name = "jinja2" +version = "3.1.6" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +groups = ["main", "docs"] +files = [ + {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, + {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jinja2-ansible-filters" +version = "1.3.2" +description = "A port of Ansible's jinja2 filters without requiring ansible core." +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "jinja2-ansible-filters-1.3.2.tar.gz", hash = "sha256:07c10cf44d7073f4f01102ca12d9a2dc31b41d47e4c61ed92ef6a6d2669b356b"}, + {file = "jinja2_ansible_filters-1.3.2-py3-none-any.whl", hash = "sha256:e1082f5564917649c76fed239117820610516ec10f87735d0338688800a55b34"}, +] + +[package.dependencies] +Jinja2 = "*" +PyYAML = "*" + +[package.extras] +test = ["pytest", "pytest-cov"] + +[[package]] +name = "jsondiff" +version = "2.2.1" +description = "Diff JSON and JSON-like structures in Python" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "jsondiff-2.2.1-py3-none-any.whl", hash = "sha256:b1f0f7e2421881848b1d556d541ac01a91680cfcc14f51a9b62cdf4da0e56722"}, + {file = "jsondiff-2.2.1.tar.gz", hash = "sha256:658d162c8a86ba86de26303cd86a7b37e1b2c1ec98b569a60e2ca6180545f7fe"}, +] + +[package.dependencies] +pyyaml = "*" + +[package.extras] +dev = ["build", "hypothesis", "pytest", "setuptools-scm"] + +[[package]] +name = "keyring" +version = "25.6.0" +description = "Store and access your passwords safely." +optional = false +python-versions = ">=3.9" +groups = ["main", "dev"] +files = [ + {file = "keyring-25.6.0-py3-none-any.whl", hash = "sha256:552a3f7af126ece7ed5c89753650eec89c7eaae8617d0aa4d9ad2b75111266bd"}, + {file = "keyring-25.6.0.tar.gz", hash = "sha256:0b39998aa941431eb3d9b0d4b2460bc773b9df6fed7621c2dfb291a7e0187a66"}, +] + +[package.dependencies] +importlib_metadata = {version = ">=4.11.4", markers = "python_version < \"3.12\""} +"jaraco.classes" = "*" +"jaraco.context" = "*" +"jaraco.functools" = "*" +jeepney = {version = ">=0.4.2", markers = "sys_platform == \"linux\""} +pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""} +SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] +completion = ["shtab (>=1.1.0)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["pyfakefs", "pytest (>=6,!=8.1.*)"] +type = ["pygobject-stubs", "pytest-mypy", "shtab", "types-pywin32"] + +[[package]] +name = "license-expression" +version = "30.4.1" +description = "license-expression is a comprehensive utility library to parse, compare, simplify and normalize license expressions (such as SPDX license expressions) using boolean logic." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "license_expression-30.4.1-py3-none-any.whl", hash = "sha256:679646bc3261a17690494a3e1cada446e5ee342dbd87dcfa4a0c24cc5dce13ee"}, + {file = "license_expression-30.4.1.tar.gz", hash = "sha256:9f02105f9e0fcecba6a85dfbbed7d94ea1c3a70cf23ddbfb5adf3438a6f6fce0"}, +] + +[package.dependencies] +"boolean.py" = ">=4.0" + +[package.extras] +docs = ["Sphinx (>=5.0.2)", "doc8 (>=0.11.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-reredirects (>=0.1.2)", "sphinx-rtd-dark-mode (>=1.3.0)", "sphinx-rtd-theme (>=1.0.0)", "sphinxcontrib-apidoc (>=0.4.0)"] +testing = ["black", "isort", "pytest (>=6,!=7.0.0)", "pytest-xdist (>=2)", "twine"] + +[[package]] +name = "linkify-it-py" +version = "2.0.3" +description = "Links recognition library with FULL unicode support." +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "linkify-it-py-2.0.3.tar.gz", hash = "sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048"}, + {file = "linkify_it_py-2.0.3-py3-none-any.whl", hash = "sha256:6bcbc417b0ac14323382aef5c5192c0075bf8a9d6b41820a2b66371eac6b6d79"}, +] + +[package.dependencies] +uc-micro-py = "*" + +[package.extras] +benchmark = ["pytest", "pytest-benchmark"] +dev = ["black", "flake8", "isort", "pre-commit", "pyproject-flake8"] +doc = ["myst-parser", "sphinx", "sphinx-book-theme"] +test = ["coverage", "pytest", "pytest-cov"] + +[[package]] +name = "macholib" +version = "1.16.3" +description = "Mach-O header analysis and editing" +optional = false +python-versions = "*" +groups = ["dev"] +markers = "sys_platform == \"darwin\"" +files = [ + {file = "macholib-1.16.3-py2.py3-none-any.whl", hash = "sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c"}, + {file = "macholib-1.16.3.tar.gz", hash = "sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30"}, +] + +[package.dependencies] +altgraph = ">=0.17" + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +linkify-it-py = {version = ">=1,<3", optional = true, markers = "extra == \"linkify\""} +mdit-py-plugins = {version = "*", optional = true, markers = "extra == \"plugins\""} +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "markupsafe" +version = "3.0.2" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.9" +groups = ["main", "docs"] +files = [ + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, + {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, +] + +[[package]] +name = "mdit-py-plugins" +version = "0.4.2" +description = "Collection of plugins for markdown-it-py" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636"}, + {file = "mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"}, +] + +[package.dependencies] +markdown-it-py = ">=1.0.0,<4.0.0" + +[package.extras] +code-style = ["pre-commit"] +rtd = ["myst-parser", "sphinx-book-theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +groups = ["main", "dev"] +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + +[[package]] +name = "more-itertools" +version = "10.7.0" +description = "More routines for operating on iterables, beyond itertools" +optional = false +python-versions = ">=3.9" +groups = ["main", "dev"] +files = [ + {file = "more_itertools-10.7.0-py3-none-any.whl", hash = "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e"}, + {file = "more_itertools-10.7.0.tar.gz", hash = "sha256:9fddd5403be01a94b204faadcff459ec3568cf110265d3c54323e1e866ad29d3"}, +] + +[[package]] +name = "mrjob" +version = "0.7.4" +description = "Python MapReduce framework" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "mrjob-0.7.4-py2.py3-none-any.whl", hash = "sha256:d8fa1bafcada0ffe3e7166896a27e996815e2cb835088aec025e3dd12c7146ce"}, + {file = "mrjob-0.7.4.tar.gz", hash = "sha256:2c8d8dc8aa4b354a97de18d0260f551f018693af74af104b3d41daf165eebdd4"}, +] + +[package.dependencies] +PyYAML = ">=3.10" + +[package.extras] +aws = ["boto3 (>=1.10.0)", "botocore (>=1.13.26)"] +google = ["google-cloud-dataproc (>=0.3.0,<=1.1.0)", "google-cloud-logging (>=1.9.0)", "google-cloud-storage (>=1.13.1)"] +rapidjson = ["python-rapidjson"] +simplejson = ["simplejson"] +ujson = ["ujson"] + +[[package]] +name = "msgpack" +version = "1.1.0" +description = "MessagePack serializer" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "msgpack-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd"}, + {file = "msgpack-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d"}, + {file = "msgpack-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5"}, + {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5"}, + {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e"}, + {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b"}, + {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f"}, + {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68"}, + {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b"}, + {file = "msgpack-1.1.0-cp310-cp310-win32.whl", hash = "sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044"}, + {file = "msgpack-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f"}, + {file = "msgpack-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7"}, + {file = "msgpack-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa"}, + {file = "msgpack-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701"}, + {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6"}, + {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59"}, + {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0"}, + {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e"}, + {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6"}, + {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5"}, + {file = "msgpack-1.1.0-cp311-cp311-win32.whl", hash = "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88"}, + {file = "msgpack-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788"}, + {file = "msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d"}, + {file = "msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2"}, + {file = "msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420"}, + {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2"}, + {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39"}, + {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f"}, + {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247"}, + {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c"}, + {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b"}, + {file = "msgpack-1.1.0-cp312-cp312-win32.whl", hash = "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b"}, + {file = "msgpack-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f"}, + {file = "msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf"}, + {file = "msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330"}, + {file = "msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734"}, + {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e"}, + {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca"}, + {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915"}, + {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d"}, + {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434"}, + {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c"}, + {file = "msgpack-1.1.0-cp313-cp313-win32.whl", hash = "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc"}, + {file = "msgpack-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f"}, + {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c40ffa9a15d74e05ba1fe2681ea33b9caffd886675412612d93ab17b58ea2fec"}, + {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1ba6136e650898082d9d5a5217d5906d1e138024f836ff48691784bbe1adf96"}, + {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0856a2b7e8dcb874be44fea031d22e5b3a19121be92a1e098f46068a11b0870"}, + {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:471e27a5787a2e3f974ba023f9e265a8c7cfd373632247deb225617e3100a3c7"}, + {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:646afc8102935a388ffc3914b336d22d1c2d6209c773f3eb5dd4d6d3b6f8c1cb"}, + {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:13599f8829cfbe0158f6456374e9eea9f44eee08076291771d8ae93eda56607f"}, + {file = "msgpack-1.1.0-cp38-cp38-win32.whl", hash = "sha256:8a84efb768fb968381e525eeeb3d92857e4985aacc39f3c47ffd00eb4509315b"}, + {file = "msgpack-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:879a7b7b0ad82481c52d3c7eb99bf6f0645dbdec5134a4bddbd16f3506947feb"}, + {file = "msgpack-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:53258eeb7a80fc46f62fd59c876957a2d0e15e6449a9e71842b6d24419d88ca1"}, + {file = "msgpack-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7e7b853bbc44fb03fbdba34feb4bd414322180135e2cb5164f20ce1c9795ee48"}, + {file = "msgpack-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3e9b4936df53b970513eac1758f3882c88658a220b58dcc1e39606dccaaf01c"}, + {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46c34e99110762a76e3911fc923222472c9d681f1094096ac4102c18319e6468"}, + {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a706d1e74dd3dea05cb54580d9bd8b2880e9264856ce5068027eed09680aa74"}, + {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:534480ee5690ab3cbed89d4c8971a5c631b69a8c0883ecfea96c19118510c846"}, + {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8cf9e8c3a2153934a23ac160cc4cba0ec035f6867c8013cc6077a79823370346"}, + {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3180065ec2abbe13a4ad37688b61b99d7f9e012a535b930e0e683ad6bc30155b"}, + {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5a91481a3cc573ac8c0d9aace09345d989dc4a0202b7fcb312c88c26d4e71a8"}, + {file = "msgpack-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f80bc7d47f76089633763f952e67f8214cb7b3ee6bfa489b3cb6a84cfac114cd"}, + {file = "msgpack-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:4d1b7ff2d6146e16e8bd665ac726a89c74163ef8cd39fa8c1087d4e52d3a2325"}, + {file = "msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e"}, +] + +[[package]] +name = "msgpack-types" +version = "0.5.0" +description = "Type stubs for msgpack" +optional = false +python-versions = "<4.0,>=3.8" +groups = ["main"] +files = [ + {file = "msgpack_types-0.5.0-py3-none-any.whl", hash = "sha256:8b633ed75e495a555fa0615843de559a74b1d176828d59bb393d266e51f6bda7"}, + {file = "msgpack_types-0.5.0.tar.gz", hash = "sha256:aebd1b8da23f8f9966d66ebb1a43bd261b95751c6a267bd21a124d2ccac84201"}, +] + +[package.dependencies] +msgpack = ">=1.1.0,<1.2.0" +typing-extensions = ">=4.6.0" + +[[package]] +name = "mslex" +version = "1.3.0" +description = "shlex for windows" +optional = false +python-versions = ">=3.5" +groups = ["main"] +files = [ + {file = "mslex-1.3.0-py3-none-any.whl", hash = "sha256:c7074b347201b3466fc077c5692fbce9b5f62a63a51f537a53fbbd02eff2eea4"}, + {file = "mslex-1.3.0.tar.gz", hash = "sha256:641c887d1d3db610eee2af37a8e5abda3f70b3006cdfd2d0d29dc0d1ae28a85d"}, +] + +[[package]] +name = "multiformats" +version = "0.3.1" +description = "Python implementation of multiformats protocols." +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "multiformats-0.3.1-py3-none-any.whl", hash = "sha256:e194bae88004cb41ca8df83cd330d97e0a566c46db99e915831761cbf0a319a4"}, + {file = "multiformats-0.3.1.tar.gz", hash = "sha256:6b011e780d8283395c3062e16def6a61636ee265a3a8c94cc83d7a80293e70e5"}, +] + +[package.dependencies] +bases = ">=0.3.0" +multiformats-config = ">=0.3.0" +typing-extensions = ">=4.6.0" +typing-validation = ">=1.1.0" + +[package.extras] +dev = ["blake3", "mmh3", "mypy", "pycryptodomex", "pylint", "pyskein", "pytest", "pytest-cov", "rich"] +full = ["blake3", "mmh3", "pycryptodomex", "pyskein", "rich"] + +[[package]] +name = "multiformats-config" +version = "0.3.1" +description = "Pre-loading configuration module for the 'multiformats' package." +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "multiformats-config-0.3.1.tar.gz", hash = "sha256:7eaa80ef5d9c5ee9b86612d21f93a087c4a655cbcb68960457e61adbc62b47a7"}, + {file = "multiformats_config-0.3.1-py3-none-any.whl", hash = "sha256:dec4c9d42ed0d9305889b67440f72e8e8d74b82b80abd7219667764b5b0a8e1d"}, +] + +[package.dependencies] +multiformats = "*" + +[package.extras] +dev = ["mypy", "pylint", "pytest", "pytest-cov"] + +[[package]] +name = "mypy" +version = "1.16.1" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a"}, + {file = "mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72"}, + {file = "mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea"}, + {file = "mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574"}, + {file = "mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d"}, + {file = "mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6"}, + {file = "mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc"}, + {file = "mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782"}, + {file = "mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507"}, + {file = "mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca"}, + {file = "mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4"}, + {file = "mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6"}, + {file = "mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d"}, + {file = "mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9"}, + {file = "mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79"}, + {file = "mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15"}, + {file = "mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd"}, + {file = "mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b"}, + {file = "mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438"}, + {file = "mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536"}, + {file = "mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f"}, + {file = "mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359"}, + {file = "mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be"}, + {file = "mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee"}, + {file = "mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069"}, + {file = "mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da"}, + {file = "mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c"}, + {file = "mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383"}, + {file = "mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40"}, + {file = "mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b"}, + {file = "mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37"}, + {file = "mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab"}, +] + +[package.dependencies] +mypy_extensions = ">=1.0.0" +pathspec = ">=0.9.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing_extensions = ">=4.6.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +faster-cache = ["orjson"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, + {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, +] + +[[package]] +name = "nh3" +version = "0.2.21" +description = "Python binding to Ammonia HTML sanitizer Rust crate" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "nh3-0.2.21-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:fcff321bd60c6c5c9cb4ddf2554e22772bb41ebd93ad88171bbbb6f271255286"}, + {file = "nh3-0.2.21-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31eedcd7d08b0eae28ba47f43fd33a653b4cdb271d64f1aeda47001618348fde"}, + {file = "nh3-0.2.21-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d426d7be1a2f3d896950fe263332ed1662f6c78525b4520c8e9861f8d7f0d243"}, + {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9d67709bc0d7d1f5797b21db26e7a8b3d15d21c9c5f58ccfe48b5328483b685b"}, + {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:55823c5ea1f6b267a4fad5de39bc0524d49a47783e1fe094bcf9c537a37df251"}, + {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:818f2b6df3763e058efa9e69677b5a92f9bc0acff3295af5ed013da544250d5b"}, + {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b3b5c58161e08549904ac4abd450dacd94ff648916f7c376ae4b2c0652b98ff9"}, + {file = "nh3-0.2.21-cp313-cp313t-win32.whl", hash = "sha256:637d4a10c834e1b7d9548592c7aad760611415fcd5bd346f77fd8a064309ae6d"}, + {file = "nh3-0.2.21-cp313-cp313t-win_amd64.whl", hash = "sha256:713d16686596e556b65e7f8c58328c2df63f1a7abe1277d87625dcbbc012ef82"}, + {file = "nh3-0.2.21-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a772dec5b7b7325780922dd904709f0f5f3a79fbf756de5291c01370f6df0967"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d002b648592bf3033adfd875a48f09b8ecc000abd7f6a8769ed86b6ccc70c759"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2a5174551f95f2836f2ad6a8074560f261cf9740a48437d6151fd2d4d7d617ab"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b8d55ea1fc7ae3633d758a92aafa3505cd3cc5a6e40470c9164d54dff6f96d42"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ae319f17cd8960d0612f0f0ddff5a90700fa71926ca800e9028e7851ce44a6f"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:63ca02ac6f27fc80f9894409eb61de2cb20ef0a23740c7e29f9ec827139fa578"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5f77e62aed5c4acad635239ac1290404c7e940c81abe561fd2af011ff59f585"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:087ffadfdcd497658c3adc797258ce0f06be8a537786a7217649fc1c0c60c293"}, + {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ac7006c3abd097790e611fe4646ecb19a8d7f2184b882f6093293b8d9b887431"}, + {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:6141caabe00bbddc869665b35fc56a478eb774a8c1dfd6fba9fe1dfdf29e6efa"}, + {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:20979783526641c81d2f5bfa6ca5ccca3d1e4472474b162c6256745fbfe31cd1"}, + {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a7ea28cd49293749d67e4fcf326c554c83ec912cd09cd94aa7ec3ab1921c8283"}, + {file = "nh3-0.2.21-cp38-abi3-win32.whl", hash = "sha256:6c9c30b8b0d291a7c5ab0967ab200598ba33208f754f2f4920e9343bdd88f79a"}, + {file = "nh3-0.2.21-cp38-abi3-win_amd64.whl", hash = "sha256:bb0014948f04d7976aabae43fcd4cb7f551f9f8ce785a4c9ef66e6c2590f8629"}, + {file = "nh3-0.2.21.tar.gz", hash = "sha256:4990e7ee6a55490dbf00d61a6f476c9a3258e31e711e13713b2ea7d6616f670e"}, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +description = "Node.js virtual environment builder" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] +files = [ + {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, + {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, +] + +[[package]] +name = "packageurl-python" +version = "0.16.0" +description = "A purl aka. Package URL parser and builder" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "packageurl_python-0.16.0-py3-none-any.whl", hash = "sha256:5c3872638b177b0f1cf01c3673017b7b27ebee485693ae12a8bed70fa7fa7c35"}, + {file = "packageurl_python-0.16.0.tar.gz", hash = "sha256:69e3bf8a3932fe9c2400f56aaeb9f86911ecee2f9398dbe1b58ec34340be365d"}, +] + +[package.extras] +build = ["setuptools", "wheel"] +lint = ["black", "isort", "mypy"] +sqlalchemy = ["sqlalchemy (>=2.0.0)"] +test = ["pytest"] + +[[package]] +name = "packaging" +version = "25.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev", "docs"] +files = [ + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, +] + +[[package]] +name = "pasteboard" +version = "0.3.3" +description = "Pasteboard - Python interface for reading from NSPasteboard (macOS clipboard)" +optional = false +python-versions = ">=3.6,<4.0" +groups = ["main"] +markers = "platform_system == \"Darwin\"" +files = [ + {file = "pasteboard-0.3.3-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:afd171e200316f6b3d3da381476921ca57cb8f26d2fa418f779454913918dbb9"}, + {file = "pasteboard-0.3.3-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:f99dd6c7039b755756b2068942c4c2487d6366e5a56eafd6db0ae7aa2a371a0e"}, + {file = "pasteboard-0.3.3-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:19229dfa28f41afb5e731ac81e52bbc4212f67d678c082d3e3621cec0628a773"}, + {file = "pasteboard-0.3.3-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:20a5c53bae8ac8186ecdd621020fb1b072d45a35f9f11a8e4cd5e82d76b485d0"}, + {file = "pasteboard-0.3.3.tar.gz", hash = "sha256:d80275e76ff1eaaa5ca3d0e0fd8aecd5ea1298523dfd51f3774b5aaebdde02cf"}, +] + +[[package]] +name = "pastel" +version = "0.2.1" +description = "Bring colors to your terminal." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] +files = [ + {file = "pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364"}, + {file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"}, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + +[[package]] +name = "pefile" +version = "2023.2.7" +description = "Python PE parsing module" +optional = false +python-versions = ">=3.6.0" +groups = ["dev"] +markers = "sys_platform == \"win32\"" +files = [ + {file = "pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"}, + {file = "pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc"}, +] + +[[package]] +name = "pip" +version = "25.1.1" +description = "The PyPA recommended tool for installing Python packages." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pip-25.1.1-py3-none-any.whl", hash = "sha256:2913a38a2abf4ea6b64ab507bd9e967f3b53dc1ede74b01b0931e1ce548751af"}, + {file = "pip-25.1.1.tar.gz", hash = "sha256:3de45d411d308d5054c2168185d8da7f9a2cd753dbac8acbfa88a8909ecd9077"}, +] + +[[package]] +name = "pip-api" +version = "0.0.34" +description = "An unofficial, importable pip API" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pip_api-0.0.34-py3-none-any.whl", hash = "sha256:8b2d7d7c37f2447373aa2cf8b1f60a2f2b27a84e1e9e0294a3f6ef10eb3ba6bb"}, + {file = "pip_api-0.0.34.tar.gz", hash = "sha256:9b75e958f14c5a2614bae415f2adf7eeb54d50a2cfbe7e24fd4826471bac3625"}, +] + +[package.dependencies] +pip = "*" + +[[package]] +name = "pip-audit" +version = "2.9.0" +description = "A tool for scanning Python environments for known vulnerabilities" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pip_audit-2.9.0-py3-none-any.whl", hash = "sha256:348b16e60895749a0839875d7cc27ebd692e1584ebe5d5cb145941c8e25a80bd"}, + {file = "pip_audit-2.9.0.tar.gz", hash = "sha256:0b998410b58339d7a231e5aa004326a294e4c7c6295289cdc9d5e1ef07b1f44d"}, +] + +[package.dependencies] +CacheControl = {version = ">=0.13.0", extras = ["filecache"]} +cyclonedx-python-lib = ">=5,<10" +packaging = ">=23.0.0" +pip-api = ">=0.0.28" +pip-requirements-parser = ">=32.0.0" +platformdirs = ">=4.2.0" +requests = ">=2.31.0" +rich = ">=12.4" +toml = ">=0.10" + +[package.extras] +dev = ["build", "pip-audit[doc,lint,test]"] +doc = ["pdoc"] +lint = ["interrogate (>=1.6,<2.0)", "mypy", "ruff (>=0.9,<1.0)", "types-requests", "types-toml"] +test = ["coverage[toml] (>=7.0,!=7.3.3,<8.0)", "pretend", "pytest", "pytest-cov"] + +[[package]] +name = "pip-requirements-parser" +version = "32.0.1" +description = "pip requirements parser - a mostly correct pip requirements parsing library because it uses pip's own code." +optional = false +python-versions = ">=3.6.0" +groups = ["dev"] +files = [ + {file = "pip-requirements-parser-32.0.1.tar.gz", hash = "sha256:b4fa3a7a0be38243123cf9d1f3518da10c51bdb165a2b2985566247f9155a7d3"}, + {file = "pip_requirements_parser-32.0.1-py3-none-any.whl", hash = "sha256:4659bc2a667783e7a15d190f6fccf8b2486685b6dba4c19c3876314769c57526"}, +] + +[package.dependencies] +packaging = "*" +pyparsing = "*" + +[package.extras] +docs = ["Sphinx (>=3.3.1)", "doc8 (>=0.8.1)", "sphinx-rtd-theme (>=0.5.0)"] +testing = ["aboutcode-toolkit (>=6.0.0)", "black", "pytest (>=6,!=7.0.0)", "pytest-xdist (>=2)"] + +[[package]] +name = "pkginfo" +version = "1.12.1.2" +description = "Query metadata from sdists / bdists / installed packages." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pkginfo-1.12.1.2-py3-none-any.whl", hash = "sha256:c783ac885519cab2c34927ccfa6bf64b5a704d7c69afaea583dd9b7afe969343"}, + {file = "pkginfo-1.12.1.2.tar.gz", hash = "sha256:5cd957824ac36f140260964eba3c6be6442a8359b8c48f4adf90210f33a04b7b"}, +] + +[package.extras] +testing = ["pytest", "pytest-cov", "wheel"] + +[[package]] +name = "platformdirs" +version = "4.3.8" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.9" +groups = ["main", "dev", "docs"] +files = [ + {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, + {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "plumbum" +version = "1.9.0" +description = "Plumbum: shell combinators library" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "plumbum-1.9.0-py3-none-any.whl", hash = "sha256:9fd0d3b0e8d86e4b581af36edf3f3bbe9d1ae15b45b8caab28de1bcb27aaa7f5"}, + {file = "plumbum-1.9.0.tar.gz", hash = "sha256:e640062b72642c3873bd5bdc3effed75ba4d3c70ef6b6a7b907357a84d909219"}, +] + +[package.dependencies] +pywin32 = {version = "*", markers = "platform_system == \"Windows\" and platform_python_implementation != \"PyPy\""} + +[package.extras] +dev = ["coverage[toml]", "paramiko", "psutil", "pytest (>=6.0)", "pytest-cov", "pytest-mock", "pytest-timeout"] +docs = ["sphinx (>=4.0.0)", "sphinx-rtd-theme (>=1.0.0)"] +ssh = ["paramiko"] +test = ["coverage[toml]", "paramiko", "psutil", "pytest (>=6.0)", "pytest-cov", "pytest-mock", "pytest-timeout"] + +[[package]] +name = "poethepoet" +version = "0.36.0" +description = "A task runner that works well with poetry and uv." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "poethepoet-0.36.0-py3-none-any.whl", hash = "sha256:693e3c1eae9f6731d3613c3c0c40f747d3c5c68a375beda42e590a63c5623308"}, + {file = "poethepoet-0.36.0.tar.gz", hash = "sha256:2217b49cb4e4c64af0b42ff8c4814b17f02e107d38bc461542517348ede25663"}, +] + +[package.dependencies] +pastel = ">=0.2.1,<0.3.0" +pyyaml = ">=6.0.2,<7.0" +tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} + +[package.extras] +poetry-plugin = ["poetry (>=1.2.0,<3.0.0) ; python_version < \"4.0\""] + +[[package]] +name = "pre-commit" +version = "3.8.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"}, + {file = "pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + +[[package]] +name = "prompt-toolkit" +version = "3.0.51" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07"}, + {file = "prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed"}, +] + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "py-serializable" +version = "2.0.0" +description = "Library for serializing and deserializing Python Objects to and from JSON and XML." +optional = false +python-versions = "<4.0,>=3.8" +groups = ["dev"] +files = [ + {file = "py_serializable-2.0.0-py3-none-any.whl", hash = "sha256:1721e4c0368adeec965c183168da4b912024702f19e15e13f8577098b9a4f8fe"}, + {file = "py_serializable-2.0.0.tar.gz", hash = "sha256:e9e6491dd7d29c31daf1050232b57f9657f9e8a43b867cca1ff204752cf420a5"}, +] + +[package.dependencies] +defusedxml = ">=0.7.1,<0.8.0" + +[[package]] +name = "pyclip" +version = "0.7.0" +description = "Cross-platform clipboard utilities supporting both binary and text data." +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "pyclip-0.7.0-py3-none-any.whl", hash = "sha256:a7b7ea2cfad2dd61e86a529af588d006070d3eb0bd32981afaee5215f4604fec"}, + {file = "pyclip-0.7.0.tar.gz", hash = "sha256:57602047a4ceab709bdcd42f3dde6449a3349b95c16154cfdce27376a2072491"}, +] + +[package.dependencies] +pasteboard = {version = "0.3.3", markers = "platform_system == \"Darwin\""} +pywin32 = {version = ">=1.0", markers = "platform_system == \"Windows\""} + +[package.extras] +test = ["pytest"] + +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] +markers = {dev = "platform_python_implementation != \"PyPy\""} + +[[package]] +name = "pycryptodomex" +version = "3.22.0" +description = "Cryptographic library for Python" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main"] +files = [ + {file = "pycryptodomex-3.22.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:41673e5cc39a8524557a0472077635d981172182c9fe39ce0b5f5c19381ffaff"}, + {file = "pycryptodomex-3.22.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:276be1ed006e8fd01bba00d9bd9b60a0151e478033e86ea1cb37447bbc057edc"}, + {file = "pycryptodomex-3.22.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:813e57da5ceb4b549bab96fa548781d9a63f49f1d68fdb148eeac846238056b7"}, + {file = "pycryptodomex-3.22.0-cp27-cp27m-win32.whl", hash = "sha256:d7beeacb5394765aa8dabed135389a11ee322d3ee16160d178adc7f8ee3e1f65"}, + {file = "pycryptodomex-3.22.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:b3746dedf74787da43e4a2f85bd78f5ec14d2469eb299ddce22518b3891f16ea"}, + {file = "pycryptodomex-3.22.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5ebc09b7d8964654aaf8a4f5ac325f2b0cc038af9bea12efff0cd4a5bb19aa42"}, + {file = "pycryptodomex-3.22.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:aef4590263b9f2f6283469e998574d0bd45c14fb262241c27055b82727426157"}, + {file = "pycryptodomex-3.22.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:5ac608a6dce9418d4f300fab7ba2f7d499a96b462f2b9b5c90d8d994cd36dcad"}, + {file = "pycryptodomex-3.22.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a24f681365ec9757ccd69b85868bbd7216ba451d0f86f6ea0eed75eeb6975db"}, + {file = "pycryptodomex-3.22.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:259664c4803a1fa260d5afb322972813c5fe30ea8b43e54b03b7e3a27b30856b"}, + {file = "pycryptodomex-3.22.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7127d9de3c7ce20339e06bcd4f16f1a1a77f1471bcf04e3b704306dde101b719"}, + {file = "pycryptodomex-3.22.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ee75067b35c93cc18b38af47b7c0664998d8815174cfc66dd00ea1e244eb27e6"}, + {file = "pycryptodomex-3.22.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:1a8b0c5ba061ace4bcd03496d42702c3927003db805b8ec619ea6506080b381d"}, + {file = "pycryptodomex-3.22.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:bfe4fe3233ef3e58028a3ad8f28473653b78c6d56e088ea04fe7550c63d4d16b"}, + {file = "pycryptodomex-3.22.0-cp37-abi3-win32.whl", hash = "sha256:2cac9ed5c343bb3d0075db6e797e6112514764d08d667c74cb89b931aac9dddd"}, + {file = "pycryptodomex-3.22.0-cp37-abi3-win_amd64.whl", hash = "sha256:ff46212fda7ee86ec2f4a64016c994e8ad80f11ef748131753adb67e9b722ebd"}, + {file = "pycryptodomex-3.22.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:5bf3ce9211d2a9877b00b8e524593e2209e370a287b3d5e61a8c45f5198487e2"}, + {file = "pycryptodomex-3.22.0-pp27-pypy_73-win32.whl", hash = "sha256:684cb57812cd243217c3d1e01a720c5844b30f0b7b64bb1a49679f7e1e8a54ac"}, + {file = "pycryptodomex-3.22.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c8cffb03f5dee1026e3f892f7cffd79926a538c67c34f8b07c90c0bd5c834e27"}, + {file = "pycryptodomex-3.22.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:140b27caa68a36d0501b05eb247bd33afa5f854c1ee04140e38af63c750d4e39"}, + {file = "pycryptodomex-3.22.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:644834b1836bb8e1d304afaf794d5ae98a1d637bd6e140c9be7dd192b5374811"}, + {file = "pycryptodomex-3.22.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72c506aba3318505dbeecf821ed7b9a9f86f422ed085e2d79c4fba0ae669920a"}, + {file = "pycryptodomex-3.22.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7cd39f7a110c1ab97ce9ee3459b8bc615920344dc00e56d1b709628965fba3f2"}, + {file = "pycryptodomex-3.22.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e4eaaf6163ff13788c1f8f615ad60cdc69efac6d3bf7b310b21e8cfe5f46c801"}, + {file = "pycryptodomex-3.22.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eac39e237d65981554c2d4c6668192dc7051ad61ab5fc383ed0ba049e4007ca2"}, + {file = "pycryptodomex-3.22.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ab0d89d1761959b608952c7b347b0e76a32d1a5bb278afbaa10a7f3eaef9a0a"}, + {file = "pycryptodomex-3.22.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e64164f816f5e43fd69f8ed98eb28f98157faf68208cd19c44ed9d8e72d33e8"}, + {file = "pycryptodomex-3.22.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f005de31efad6f9acefc417296c641f13b720be7dbfec90edeaca601c0fab048"}, + {file = "pycryptodomex-3.22.0.tar.gz", hash = "sha256:a1da61bacc22f93a91cbe690e3eb2022a03ab4123690ab16c46abb693a9df63d"}, +] + +[[package]] +name = "pydantic" +version = "2.11.4" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb"}, + {file = "pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d"}, +] + +[package.dependencies] +annotated-types = ">=0.6.0" +pydantic-core = "2.33.2" +typing-extensions = ">=4.12.2" +typing-inspection = ">=0.4.0" + +[package.extras] +email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] + +[[package]] +name = "pydantic-core" +version = "2.33.2" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, + {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, + {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, + {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, + {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, + {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, + {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, + {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, + {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, + {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, + {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, + {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, + {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pydash" +version = "8.0.5" +description = "The kitchen sink of Python utility libraries for doing \"stuff\" in a functional way. Based on the Lo-Dash Javascript library." +optional = false +python-versions = ">=3.8" +groups = ["docs"] +files = [ + {file = "pydash-8.0.5-py3-none-any.whl", hash = "sha256:b2625f8981862e19911daa07f80ed47b315ce20d9b5eb57aaf97aaf570c3892f"}, + {file = "pydash-8.0.5.tar.gz", hash = "sha256:7cc44ebfe5d362f4f5f06c74c8684143c5ac481376b059ff02570705523f9e2e"}, +] + +[package.dependencies] +typing-extensions = ">3.10,<4.6.0 || >4.6.0" + +[package.extras] +dev = ["build", "coverage", "furo", "invoke", "mypy", "pytest", "pytest-cov", "pytest-mypy-testing", "ruff", "sphinx", "sphinx-autodoc-typehints", "tox", "twine", "wheel"] + +[[package]] +name = "pygments" +version = "2.19.1" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +groups = ["main", "dev", "docs"] +files = [ + {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, + {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pyinstaller" +version = "6.14.2" +description = "PyInstaller bundles a Python application and all its dependencies into a single package." +optional = false +python-versions = "<3.14,>=3.8" +groups = ["dev"] +files = [ + {file = "pyinstaller-6.14.2-py3-none-macosx_10_13_universal2.whl", hash = "sha256:d77d18bf5343a1afef2772393d7a489d4ec2282dee5bca549803fc0d74b78330"}, + {file = "pyinstaller-6.14.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:3fa0c391e1300a9fd7752eb1ffe2950112b88fba9d2743eee2ef218a15f4705f"}, + {file = "pyinstaller-6.14.2-py3-none-manylinux2014_i686.whl", hash = "sha256:077efb2d01d16d9c8fdda3ad52788f0fead2791c5cec9ed6ce058af7e26eb74b"}, + {file = "pyinstaller-6.14.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:fdd2bd020a18736806a6bd5d3c4352f1209b427a96ad6c459d88aec1d90c4f21"}, + {file = "pyinstaller-6.14.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:03862c6b3cf7b16843d24b529f89cd4077cbe467883cd54ce7a81940d6da09d3"}, + {file = "pyinstaller-6.14.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:78827a21ada2a848e98671852d20d74b2955b6e2aaf2359ed13a462e1a603d84"}, + {file = "pyinstaller-6.14.2-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:185710ab1503dfdfa14c43237d394d96ac183422d588294be42531480dfa6c38"}, + {file = "pyinstaller-6.14.2-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:6c673a7e761bd4a2560cfd5dbe1ccdcfe2dff304b774e6e5242fc5afed953661"}, + {file = "pyinstaller-6.14.2-py3-none-win32.whl", hash = "sha256:1697601aa788e3a52f0b5e620b4741a34b82e6f222ec6e1318b3a1349f566bb2"}, + {file = "pyinstaller-6.14.2-py3-none-win_amd64.whl", hash = "sha256:e10e0e67288d6dcb5898a917dd1d4272aa0ff33f197ad49a0e39618009d63ed9"}, + {file = "pyinstaller-6.14.2-py3-none-win_arm64.whl", hash = "sha256:69fd11ca57e572387826afaa4a1b3d4cb74927d76f231f0308c0bd7872ca5ac1"}, + {file = "pyinstaller-6.14.2.tar.gz", hash = "sha256:142cce0719e79315f0cc26400c2e5c45d9b6b17e7e0491fee444a9f8f16f4917"}, +] + +[package.dependencies] +altgraph = "*" +macholib = {version = ">=1.8", markers = "sys_platform == \"darwin\""} +packaging = ">=22.0" +pefile = {version = ">=2022.5.30,<2024.8.26 || >2024.8.26", markers = "sys_platform == \"win32\""} +pyinstaller-hooks-contrib = ">=2025.5" +pywin32-ctypes = {version = ">=0.2.1", markers = "sys_platform == \"win32\""} +setuptools = ">=42.0.0" + +[package.extras] +completion = ["argcomplete"] +hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] + +[[package]] +name = "pyinstaller-hooks-contrib" +version = "2025.5" +description = "Community maintained hooks for PyInstaller" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pyinstaller_hooks_contrib-2025.5-py3-none-any.whl", hash = "sha256:ebfae1ba341cb0002fb2770fad0edf2b3e913c2728d92df7ad562260988ca373"}, + {file = "pyinstaller_hooks_contrib-2025.5.tar.gz", hash = "sha256:707386770b8fe066c04aad18a71bc483c7b25e18b4750a756999f7da2ab31982"}, +] + +[package.dependencies] +packaging = ">=22.0" +setuptools = ">=42.0.0" + +[[package]] +name = "pyjwt" +version = "2.10.1" +description = "JSON Web Token implementation in Python" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, + {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, +] + +[package.extras] +crypto = ["cryptography (>=3.4.0)"] +dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] +docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] + +[[package]] +name = "pynacl" +version = "1.5.0" +description = "Python binding to the Networking and Cryptography (NaCl) library" +optional = false +python-versions = ">=3.6" +groups = ["main"] +files = [ + {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, + {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, +] + +[package.dependencies] +cffi = ">=1.4.1" + +[package.extras] +docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] +tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] + +[[package]] +name = "pyparsing" +version = "3.2.3" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf"}, + {file = "pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "pyperclip" +version = "1.9.0" +description = "A cross-platform clipboard module for Python. (Only handles plain text for now.)" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "pyperclip-1.9.0.tar.gz", hash = "sha256:b7de0142ddc81bfc5c7507eea19da920b92252b548b96186caf94a5e2527d310"}, +] + +[[package]] +name = "pytest" +version = "8.4.1" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, + {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, +] + +[package.dependencies] +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} +iniconfig = ">=1" +packaging = ">=20" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + +[[package]] +name = "pytest-httpx" +version = "0.35.0" +description = "Send responses to httpx." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest_httpx-0.35.0-py3-none-any.whl", hash = "sha256:ee11a00ffcea94a5cbff47af2114d34c5b231c326902458deed73f9c459fd744"}, + {file = "pytest_httpx-0.35.0.tar.gz", hash = "sha256:d619ad5d2e67734abfbb224c3d9025d64795d4b8711116b1a13f72a251ae511f"}, +] + +[package.dependencies] +httpx = "==0.28.*" +pytest = "==8.*" + +[package.extras] +testing = ["pytest-asyncio (==0.24.*)", "pytest-cov (==6.*)"] + +[[package]] +name = "pytest-mock" +version = "3.14.1" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0"}, + {file = "pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e"}, +] + +[package.dependencies] +pytest = ">=6.2.5" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + +[[package]] +name = "pytest-sugar" +version = "1.0.0" +description = "pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly)." +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "pytest-sugar-1.0.0.tar.gz", hash = "sha256:6422e83258f5b0c04ce7c632176c7732cab5fdb909cb39cca5c9139f81276c0a"}, + {file = "pytest_sugar-1.0.0-py3-none-any.whl", hash = "sha256:70ebcd8fc5795dc457ff8b69d266a4e2e8a74ae0c3edc749381c64b5246c8dfd"}, +] + +[package.dependencies] +packaging = ">=21.3" +pytest = ">=6.2.0" +termcolor = ">=2.1.0" + +[package.extras] +dev = ["black", "flake8", "pre-commit"] + +[[package]] +name = "pytest-xdist" +version = "3.8.0" +description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88"}, + {file = "pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1"}, +] + +[package.dependencies] +execnet = ">=2.1" +pytest = ">=7.0.0" + +[package.extras] +psutil = ["psutil (>=3.0)"] +setproctitle = ["setproctitle"] +testing = ["filelock"] + +[[package]] +name = "python-dotenv" +version = "1.1.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc"}, + {file = "python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "python-gitlab" +version = "3.15.0" +description = "Interact with GitLab API" +optional = false +python-versions = ">=3.7.0" +groups = ["dev"] +files = [ + {file = "python-gitlab-3.15.0.tar.gz", hash = "sha256:c9e65eb7612a9fbb8abf0339972eca7fd7a73d4da66c9b446ffe528930aff534"}, + {file = "python_gitlab-3.15.0-py3-none-any.whl", hash = "sha256:8f8d1c0d387f642eb1ac7bf5e8e0cd8b3dd49c6f34170cee3c7deb7d384611f3"}, +] + +[package.dependencies] +requests = ">=2.25.0" +requests-toolbelt = ">=0.10.1" + +[package.extras] +autocompletion = ["argcomplete (>=1.10.0,<3)"] +yaml = ["PyYaml (>=5.2)"] + +[[package]] +name = "python-semantic-release" +version = "7.34.6" +description = "Automatic Semantic Versioning for Python projects" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "python-semantic-release-7.34.6.tar.gz", hash = "sha256:e9b8fb788024ae9510a924136d573588415a16eeca31cc5240f2754a80a2e831"}, + {file = "python_semantic_release-7.34.6-py3-none-any.whl", hash = "sha256:7e3969ba4663d9b2087b02bf3ac140e202551377bf045c34e09bfe19753e19ab"}, +] + +[package.dependencies] +click = ">=7,<9" +click-log = ">=0.3,<1" +dotty-dict = ">=1.3.0,<2" +gitpython = ">=3.0.8,<4" +invoke = ">=1.4.1,<3" +packaging = "*" +python-gitlab = ">=2,<4" +requests = ">=2.25,<3" +semver = ">=2.10,<3" +tomlkit = ">=0.10,<1.0" +twine = ">=3,<4" +wheel = "*" + +[package.extras] +dev = ["black", "isort", "tox"] +docs = ["Jinja2 (==3.0.3)", "Sphinx (==1.8.6)"] +mypy = ["mypy", "types-requests"] +test = ["coverage (>=5,<6)", "mock (==1.3.0)", "pytest (>=7,<8)", "pytest-mock (>=2,<3)", "pytest-xdist (>=1,<2)", "responses (==0.13.3)"] + +[[package]] +name = "pywin32" +version = "310" +description = "Python for Window Extensions" +optional = false +python-versions = "*" +groups = ["main"] +markers = "platform_system == \"Windows\"" +files = [ + {file = "pywin32-310-cp310-cp310-win32.whl", hash = "sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1"}, + {file = "pywin32-310-cp310-cp310-win_amd64.whl", hash = "sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d"}, + {file = "pywin32-310-cp310-cp310-win_arm64.whl", hash = "sha256:33babed0cf0c92a6f94cc6cc13546ab24ee13e3e800e61ed87609ab91e4c8213"}, + {file = "pywin32-310-cp311-cp311-win32.whl", hash = "sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd"}, + {file = "pywin32-310-cp311-cp311-win_amd64.whl", hash = "sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c"}, + {file = "pywin32-310-cp311-cp311-win_arm64.whl", hash = "sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582"}, + {file = "pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d"}, + {file = "pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060"}, + {file = "pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966"}, + {file = "pywin32-310-cp313-cp313-win32.whl", hash = "sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab"}, + {file = "pywin32-310-cp313-cp313-win_amd64.whl", hash = "sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e"}, + {file = "pywin32-310-cp313-cp313-win_arm64.whl", hash = "sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33"}, + {file = "pywin32-310-cp38-cp38-win32.whl", hash = "sha256:0867beb8addefa2e3979d4084352e4ac6e991ca45373390775f7084cc0209b9c"}, + {file = "pywin32-310-cp38-cp38-win_amd64.whl", hash = "sha256:30f0a9b3138fb5e07eb4973b7077e1883f558e40c578c6925acc7a94c34eaa36"}, + {file = "pywin32-310-cp39-cp39-win32.whl", hash = "sha256:851c8d927af0d879221e616ae1f66145253537bbdd321a77e8ef701b443a9a1a"}, + {file = "pywin32-310-cp39-cp39-win_amd64.whl", hash = "sha256:96867217335559ac619f00ad70e513c0fcf84b8a3af9fc2bba3b59b97da70475"}, +] + +[[package]] +name = "pywin32-ctypes" +version = "0.2.3" +description = "A (partial) reimplementation of pywin32 using ctypes/cffi" +optional = false +python-versions = ">=3.6" +groups = ["main", "dev"] +markers = "sys_platform == \"win32\"" +files = [ + {file = "pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755"}, + {file = "pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, +] + +[[package]] +name = "questionary" +version = "1.10.0" +description = "Python library to build pretty command line user prompts ⭐️" +optional = false +python-versions = ">=3.6,<4.0" +groups = ["main"] +files = [ + {file = "questionary-1.10.0-py3-none-any.whl", hash = "sha256:fecfcc8cca110fda9d561cb83f1e97ecbb93c613ff857f655818839dac74ce90"}, + {file = "questionary-1.10.0.tar.gz", hash = "sha256:600d3aefecce26d48d97eee936fdb66e4bc27f934c3ab6dd1e292c4f43946d90"}, +] + +[package.dependencies] +prompt_toolkit = ">=2.0,<4.0" + +[package.extras] +docs = ["Sphinx (>=3.3,<4.0)", "sphinx-autobuild (>=2020.9.1,<2021.0.0)", "sphinx-autodoc-typehints (>=1.11.1,<2.0.0)", "sphinx-copybutton (>=0.3.1,<0.4.0)", "sphinx-rtd-theme (>=0.5.0,<0.6.0)"] + +[[package]] +name = "readme-renderer" +version = "43.0" +description = "readme_renderer is a library for rendering readme descriptions for Warehouse" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "readme_renderer-43.0-py3-none-any.whl", hash = "sha256:19db308d86ecd60e5affa3b2a98f017af384678c63c88e5d4556a380e674f3f9"}, + {file = "readme_renderer-43.0.tar.gz", hash = "sha256:1818dd28140813509eeed8d62687f7cd4f7bad90d4db586001c5dc09d4fde311"}, +] + +[package.dependencies] +docutils = ">=0.13.1" +nh3 = ">=0.2.14" +Pygments = ">=2.5.1" + +[package.extras] +md = ["cmarkgfm (>=0.8.0)"] + +[[package]] +name = "requests" +version = "2.32.4" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +groups = ["main", "dev", "docs"] +files = [ + {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, + {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset_normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-toolbelt" +version = "1.0.0" +description = "A utility belt for advanced users of python-requests" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] +files = [ + {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, + {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, +] + +[package.dependencies] +requests = ">=2.0.1,<3.0.0" + +[[package]] +name = "rfc3986" +version = "2.0.0" +description = "Validating URI References per RFC 3986" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd"}, + {file = "rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c"}, +] + +[package.extras] +idna2008 = ["idna"] + +[[package]] +name = "rich" +version = "14.0.0" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.8.0" +groups = ["main", "dev"] +files = [ + {file = "rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0"}, + {file = "rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" +typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "ruff" +version = "0.12.2" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be"}, + {file = "ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e"}, + {file = "ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc"}, + {file = "ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922"}, + {file = "ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b"}, + {file = "ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d"}, + {file = "ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1"}, + {file = "ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4"}, + {file = "ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9"}, + {file = "ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da"}, + {file = "ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce"}, + {file = "ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d"}, + {file = "ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04"}, + {file = "ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342"}, + {file = "ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a"}, + {file = "ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639"}, + {file = "ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12"}, + {file = "ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e"}, +] + +[[package]] +name = "secretstorage" +version = "3.3.3" +description = "Python bindings to FreeDesktop.org Secret Service API" +optional = false +python-versions = ">=3.6" +groups = ["main", "dev"] +markers = "sys_platform == \"linux\"" +files = [ + {file = "SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99"}, + {file = "SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77"}, +] + +[package.dependencies] +cryptography = ">=2.0" +jeepney = ">=0.6" + +[[package]] +name = "semver" +version = "2.13.0" +description = "Python helper for Semantic Versioning (http://semver.org/)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] +files = [ + {file = "semver-2.13.0-py2.py3-none-any.whl", hash = "sha256:ced8b23dceb22134307c1b8abfa523da14198793d9787ac838e70e29e77458d4"}, + {file = "semver-2.13.0.tar.gz", hash = "sha256:fa0fe2722ee1c3f57eac478820c3a5ae2f624af8264cbdf9000c980ff7f75e3f"}, +] + +[[package]] +name = "setuptools" +version = "80.4.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "setuptools-80.4.0-py3-none-any.whl", hash = "sha256:6cdc8cb9a7d590b237dbe4493614a9b75d0559b888047c1f67d49ba50fc3edb2"}, + {file = "setuptools-80.4.0.tar.gz", hash = "sha256:5a78f61820bc088c8e4add52932ae6b8cf423da2aff268c23f813cfbb13b4006"}, +] + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] + +[[package]] +name = "shellingham" +version = "1.5.4" +description = "Tool to Detect Surrounding Shell" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, + {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, +] + +[[package]] +name = "smmap" +version = "5.0.2" +description = "A pure Python implementation of a sliding window memory map manager" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, + {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +groups = ["main", "dev"] +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + +[[package]] +name = "snowballstemmer" +version = "3.0.1" +description = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*" +groups = ["docs"] +files = [ + {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}, + {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + +[[package]] +name = "soupsieve" +version = "2.7" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4"}, + {file = "soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a"}, +] + +[[package]] +name = "sphinx" +version = "6.2.1" +description = "Python documentation generator" +optional = false +python-versions = ">=3.8" +groups = ["docs"] +files = [ + {file = "Sphinx-6.2.1.tar.gz", hash = "sha256:6d56a34697bb749ffa0152feafc4b19836c755d90a7c59b72bc7dfd371b9cc6b"}, + {file = "sphinx-6.2.1-py3-none-any.whl", hash = "sha256:97787ff1fa3256a3eef9eda523a63dbf299f7b47e053cfcf684a1c2a8380c912"}, +] + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=2.9" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.18.1,<0.20" +imagesize = ">=1.3" +Jinja2 = ">=3.0" +packaging = ">=21.0" +Pygments = ">=2.13" +requests = ">=2.25.0" +snowballstemmer = ">=2.0" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.5" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] +test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] + +[[package]] +name = "sphinx-click" +version = "4.4.0" +description = "Sphinx extension that automatically documents click applications" +optional = false +python-versions = ">=3.7" +groups = ["docs"] +files = [ + {file = "sphinx-click-4.4.0.tar.gz", hash = "sha256:cc67692bd28f482c7f01531c61b64e9d2f069bfcf3d24cbbb51d4a84a749fa48"}, + {file = "sphinx_click-4.4.0-py3-none-any.whl", hash = "sha256:2821c10a68fc9ee6ce7c92fad26540d8d8c8f45e6d7258f0e4fb7529ae8fab49"}, +] + +[package.dependencies] +click = ">=7.0" +docutils = "*" +sphinx = ">=2.0" + +[[package]] +name = "sphinxcontrib-applehelp" +version = "2.0.0" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.9" +groups = ["docs"] +files = [ + {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, + {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "2.0.0" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" +optional = false +python-versions = ">=3.9" +groups = ["docs"] +files = [ + {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, + {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.1.0" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.9" +groups = ["docs"] +files = [ + {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, + {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +optional = false +python-versions = ">=3.5" +groups = ["docs"] +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "2.0.0" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" +optional = false +python-versions = ">=3.9" +groups = ["docs"] +files = [ + {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, + {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["defusedxml (>=0.7.1)", "pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "2.0.0" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" +optional = false +python-versions = ">=3.9" +groups = ["docs"] +files = [ + {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, + {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxnotes-markdown-builder" +version = "0.5.7" +description = "sphinx builder that outputs markdown files, an active fork of clayrisser/sphinx-markdown-builder" +optional = false +python-versions = "*" +groups = ["docs"] +files = [ + {file = "sphinxnotes-markdown-builder-0.5.7.tar.gz", hash = "sha256:ad3e88fa1052d1a9bc4b75d7ae389ce51ffa896963bb19643e01b9120ca17ee9"}, + {file = "sphinxnotes_markdown_builder-0.5.7-py2.py3-none-any.whl", hash = "sha256:e1c49c31f72c36b29defc69fb05b7087b736355474b8806c814306ad3b42e2b8"}, +] + +[package.dependencies] +html2text = "*" +pydash = "*" +sphinx = "*" +unify = "*" +yapf = "*" + +[[package]] +name = "termcolor" +version = "3.1.0" +description = "ANSI color formatting for output in terminal" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "termcolor-3.1.0-py3-none-any.whl", hash = "sha256:591dd26b5c2ce03b9e43f391264626557873ce1d379019786f99b0c2bee140aa"}, + {file = "termcolor-3.1.0.tar.gz", hash = "sha256:6a6dd7fbee581909eeec6a756cff1d7f7c376063b14e4a298dc4980309e55970"}, +] + +[package.extras] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "textual" +version = "3.6.0" +description = "Modern Text User Interface framework" +optional = false +python-versions = "<4.0.0,>=3.8.1" +groups = ["main"] +files = [ + {file = "textual-3.6.0-py3-none-any.whl", hash = "sha256:8b2fafe17b1805fd608092ab2f99b6ddeaff1809f1d5de6820bf5db5b6c51c28"}, + {file = "textual-3.6.0.tar.gz", hash = "sha256:d86b666e34758392a4a1aefc4b781b17d0d001419d24e4d47c277f36c20b1222"}, +] + +[package.dependencies] +markdown-it-py = {version = ">=2.1.0", extras = ["linkify", "plugins"]} +platformdirs = ">=3.6.0,<5" +rich = ">=13.3.3" +typing-extensions = ">=4.4.0,<5.0.0" + +[package.extras] +syntax = ["tree-sitter (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-bash (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-css (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-go (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-html (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-java (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-javascript (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-json (>=0.24.0) ; python_version >= \"3.9\"", "tree-sitter-markdown (>=0.3.0) ; python_version >= \"3.9\"", "tree-sitter-python (>=0.23.0) ; python_version >= \"3.9\"", "tree-sitter-regex (>=0.24.0) ; python_version >= \"3.9\"", "tree-sitter-rust (>=0.23.0,<=0.23.2) ; python_version >= \"3.9\"", "tree-sitter-sql (>=0.3.0,<0.3.8) ; python_version >= \"3.9\"", "tree-sitter-toml (>=0.6.0) ; python_version >= \"3.9\"", "tree-sitter-xml (>=0.7.0) ; python_version >= \"3.9\"", "tree-sitter-yaml (>=0.6.0) ; python_version >= \"3.9\""] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +groups = ["dev"] +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + +[[package]] +name = "tomli" +version = "2.2.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev", "docs"] +files = [ + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, +] +markers = {main = "python_version == \"3.10\"", dev = "python_full_version <= \"3.11.0a6\"", docs = "python_version == \"3.10\""} + +[[package]] +name = "tomlkit" +version = "0.13.2" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, + {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, +] + +[[package]] +name = "tqdm" +version = "4.67.1" +description = "Fast, Extensible Progress Meter" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, + {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +dev = ["nbval", "pytest (>=6)", "pytest-asyncio (>=0.24)", "pytest-cov", "pytest-timeout"] +discord = ["requests"] +notebook = ["ipywidgets (>=6)"] +slack = ["slack-sdk"] +telegram = ["requests"] + +[[package]] +name = "twine" +version = "3.8.0" +description = "Collection of utilities for publishing packages on PyPI" +optional = false +python-versions = ">=3.6" +groups = ["dev"] +files = [ + {file = "twine-3.8.0-py3-none-any.whl", hash = "sha256:d0550fca9dc19f3d5e8eadfce0c227294df0a2a951251a4385797c8a6198b7c8"}, + {file = "twine-3.8.0.tar.gz", hash = "sha256:8efa52658e0ae770686a13b675569328f1fba9837e5de1867bfe5f46a9aefe19"}, +] + +[package.dependencies] +colorama = ">=0.4.3" +importlib-metadata = ">=3.6" +keyring = ">=15.1" +pkginfo = ">=1.8.1" +readme-renderer = ">=21.0" +requests = ">=2.20" +requests-toolbelt = ">=0.8.0,<0.9.0 || >0.9.0" +rfc3986 = ">=1.4.0" +tqdm = ">=4.14" +urllib3 = ">=1.26.0" + +[[package]] +name = "types-pyyaml" +version = "6.0.12.20250402" +description = "Typing stubs for PyYAML" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "types_pyyaml-6.0.12.20250402-py3-none-any.whl", hash = "sha256:652348fa9e7a203d4b0d21066dfb00760d3cbd5a15ebb7cf8d33c88a49546681"}, + {file = "types_pyyaml-6.0.12.20250402.tar.gz", hash = "sha256:d7c13c3e6d335b6af4b0122a01ff1d270aba84ab96d1a1a1063ecba3e13ec075"}, +] + +[[package]] +name = "typing-extensions" +version = "4.13.2" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev", "docs"] +files = [ + {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, + {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, +] + +[[package]] +name = "typing-inspection" +version = "0.4.0" +description = "Runtime typing introspection tools" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f"}, + {file = "typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122"}, +] + +[package.dependencies] +typing-extensions = ">=4.12.0" + +[[package]] +name = "typing-validation" +version = "1.2.12" +description = "A simple library for runtime type-checking." +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "typing_validation-1.2.12-py3-none-any.whl", hash = "sha256:d68e22a41bf2b98ae91e5d6407db56e9ef83e9e5600164a7aff64aaa082fc232"}, + {file = "typing_validation-1.2.12.tar.gz", hash = "sha256:7ea9463a18bd04922e799cac1954f687e68e9564773f81db491536852ffe1d54"}, +] + +[package.dependencies] +typing_extensions = {version = ">=4.6.0", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["mypy", "pylint", "pytest", "pytest-cov", "rich"] + +[[package]] +name = "uc-micro-py" +version = "1.0.3" +description = "Micro subset of unicode data files for linkify-it-py projects." +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "uc-micro-py-1.0.3.tar.gz", hash = "sha256:d321b92cff673ec58027c04015fcaa8bb1e005478643ff4a500882eaab88c48a"}, + {file = "uc_micro_py-1.0.3-py3-none-any.whl", hash = "sha256:db1dffff340817673d7b466ec86114a9dc0e9d4d9b5ba229d9d60e5c12600cd5"}, +] + +[package.extras] +test = ["coverage", "pytest", "pytest-cov"] + +[[package]] +name = "unify" +version = "0.5" +description = "Modifies strings to all use the same (single/double) quote where possible." +optional = false +python-versions = "*" +groups = ["docs"] +files = [ + {file = "unify-0.5.tar.gz", hash = "sha256:8ddce812b2457212b7598fe574c9e6eb3ad69710f445391338270c7f8a71723c"}, +] + +[package.dependencies] +untokenize = "*" + +[[package]] +name = "untokenize" +version = "0.1.1" +description = "Transforms tokens into original source code (while preserving whitespace)." +optional = false +python-versions = "*" +groups = ["docs"] +files = [ + {file = "untokenize-0.1.1.tar.gz", hash = "sha256:3865dbbbb8efb4bb5eaa72f1be7f3e0be00ea8b7f125c69cbd1f5fda926f37a2"}, +] + +[[package]] +name = "urllib3" +version = "2.6.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.9" +groups = ["main", "dev", "docs"] +files = [ + {file = "urllib3-2.6.0-py3-none-any.whl", hash = "sha256:c90f7a39f716c572c4e3e58509581ebd83f9b59cced005b7db7ad2d22b0db99f"}, + {file = "urllib3-2.6.0.tar.gz", hash = "sha256:cb9bcef5a4b345d5da5d145dc3e30834f58e8018828cbc724d30b4cb7d4d49f1"}, +] + +[package.extras] +brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] + +[[package]] +name = "virtualenv" +version = "20.31.2" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11"}, + {file = "virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] + +[[package]] +name = "wcwidth" +version = "0.2.13" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, +] + +[[package]] +name = "wheel" +version = "0.45.1" +description = "A built-package format for Python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248"}, + {file = "wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729"}, +] + +[package.extras] +test = ["pytest (>=6.0.0)", "setuptools (>=65)"] + +[[package]] +name = "yapf" +version = "0.43.0" +description = "A formatter for Python code" +optional = false +python-versions = ">=3.7" +groups = ["docs"] +files = [ + {file = "yapf-0.43.0-py3-none-any.whl", hash = "sha256:224faffbc39c428cb095818cf6ef5511fdab6f7430a10783fdfb292ccf2852ca"}, + {file = "yapf-0.43.0.tar.gz", hash = "sha256:00d3aa24bfedff9420b2e0d5d9f5ab6d9d4268e72afbf59bb3fa542781d5218e"}, +] + +[package.dependencies] +platformdirs = ">=3.5.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[[package]] +name = "zipp" +version = "3.21.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.9" +groups = ["main", "dev"] +files = [ + {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, + {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, +] +markers = {main = "python_version < \"3.12\""} + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["big-O", "importlib-resources ; python_version < \"3.9\"", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +type = ["pytest-mypy"] + +[metadata] +lock-version = "2.1" +python-versions = ">=3.10,<3.14" +content-hash = "00f314f01db01ccd81dd6a77fcc2248f88ead0931e597d6cd91c0e6cee62e65f" diff --git a/pyproject.toml b/pyproject.toml index 64458cff9..ba1195e06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,11 @@ dependencies = [ [project.scripts] algokit = "algokit.cli:algokit" +[tool.poetry.group.docs.dependencies] +sphinx = "^6.0.0" +sphinx-click = "^4.4.0" +sphinxnotes-markdown-builder = "^0.5.6" + [build-system] requires = ["hatchling"] build-backend = "hatchling.build" @@ -55,8 +60,6 @@ dev = [ "python-semantic-release>=7.32.2,<8.0.0", "pytest-cov>=4.0.0,<5.0.0", "pre-commit>=2.20,<4.0", - "sphinx>=6.0.0,<7.0.0", - "sphinx-click>=4.4.0,<5.0.0", "poethepoet>=0.17.1,<0.37.0", "gfm-toc>=0.0.7,<0.0.8", "pytest-xdist>=3.4.0,<4.0.0", @@ -64,14 +67,16 @@ dev = [ "types-pyyaml>=6.0.12.20250402,<7.0.0", ] docs = [ + "sphinx>=6.0.0,<7.0.0", + "sphinx-click>=4.4.0,<5.0.0", "sphinxnotes-markdown-builder>=0.5.6,<0.6.0", ] [tool.poe.tasks] -docs_generate = "sphinx-build -b markdown -E docs/sphinx docs/cli" -docs_toc = "gfm-toc docs/cli/index.md -e 3" -docs_title = {shell = "(echo \"# AlgoKit CLI Reference Documentation\\n\\n\"; cat docs/cli/index.md) > docs/cli/temp.md && mv docs/cli/temp.md docs/cli/index.md"} -docs = ["docs_generate", "docs_toc", "docs_title"] +docs-cli = "python docs/cli_build.py" +docs-dev = { shell = "python docs/cli_build.py && pnpm --dir docs run dev" } +docs-build = { shell = "python docs/cli_build.py && pnpm --dir docs run build" } +docs-preview = "npm run --prefix docs preview" package_unix = "pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --hidden-import algokit_utils.algo25 --hidden-import algokit_utils.transact --hidden-import algokit_utils.common --hidden-import algokit_utils.clients --hidden-import algokit_utils.transactions.builders --hidden-import algokit_utils.transactions.types --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data './misc/multiformats_config:multiformats_config/' --add-data './src/algokit/resources:algokit/resources/'" package_windows = { cmd = "scripts/package_windows.bat" } package_mac = { cmd = "scripts/package_mac.sh" } @@ -166,6 +171,7 @@ target-version = "py310" [tool.ruff.lint.per-file-ignores] "tests/**/test_*.py" = ["PLR0913"] # too many args +"docs/cli_build.py" = ["T201"] # print is intentional in build scripts [tool.ruff.lint.flake8-annotations] allow-star-arg-any = true diff --git a/src/algokit/core/address_utils.py b/src/algokit/core/address_utils.py index 5abc5fd39..1b651b0d4 100644 --- a/src/algokit/core/address_utils.py +++ b/src/algokit/core/address_utils.py @@ -11,6 +11,8 @@ public_key_from_address, ) +PRIVATE_KEY_LENGTH = 64 # 32-byte seed + 32-byte public key + def is_valid_address(address: str) -> bool: """Check if an address is a valid Algorand address. @@ -47,6 +49,9 @@ def address_from_private_key(private_key: str) -> str: # Decode the base64 private key key_bytes = base64.b64decode(private_key) + if len(key_bytes) != PRIVATE_KEY_LENGTH: + raise ValueError(f"Invalid private key: expected {PRIVATE_KEY_LENGTH} bytes, got {len(key_bytes)}") + # Extract the public key (last 32 bytes of the 64-byte key) public_key = key_bytes[32:64] diff --git a/src/algokit/core/tasks/mint/mint.py b/src/algokit/core/tasks/mint/mint.py index e7cc2b8be..c560f5c96 100644 --- a/src/algokit/core/tasks/mint/mint.py +++ b/src/algokit/core/tasks/mint/mint.py @@ -6,8 +6,8 @@ import pathlib import re -from algokit_common import address_from_public_key, sha512_256 from algokit_utils.clients import AlgodClient, algod_models +from algokit_utils.common import address_from_public_key, sha512_256 from algokit_utils.transact import get_transaction_id from algokit_utils.transactions.builders.asset import build_asset_create_transaction from algokit_utils.transactions.types import AssetCreateParams diff --git a/tests/tasks/test_wallet.py b/tests/tasks/test_wallet.py index 448b7b101..69bc35485 100644 --- a/tests/tasks/test_wallet.py +++ b/tests/tasks/test_wallet.py @@ -2,8 +2,8 @@ import json import pytest -from algokit_common import address_from_public_key from algokit_utils.algo25 import secret_key_to_mnemonic +from algokit_utils.common import address_from_public_key from nacl.signing import SigningKey from pytest_mock import MockerFixture diff --git a/uv.lock b/uv.lock index 3d7709192..bf9714589 100644 --- a/uv.lock +++ b/uv.lock @@ -55,11 +55,11 @@ dev = [ { name = "pytest-xdist" }, { name = "python-semantic-release" }, { name = "ruff" }, - { name = "sphinx" }, - { name = "sphinx-click" }, { name = "types-pyyaml" }, ] docs = [ + { name = "sphinx" }, + { name = "sphinx-click" }, { name = "sphinxnotes-markdown-builder" }, ] @@ -104,11 +104,13 @@ dev = [ { name = "pytest-xdist", specifier = ">=3.4.0,<4.0.0" }, { name = "python-semantic-release", specifier = ">=7.32.2,<8.0.0" }, { name = "ruff", specifier = ">=0.1.6,<0.13.0" }, + { name = "types-pyyaml", specifier = ">=6.0.12.20250402,<7.0.0" }, +] +docs = [ { name = "sphinx", specifier = ">=6.0.0,<7.0.0" }, { name = "sphinx-click", specifier = ">=4.4.0,<5.0.0" }, - { name = "types-pyyaml", specifier = ">=6.0.12.20250402,<7.0.0" }, + { name = "sphinxnotes-markdown-builder", specifier = ">=0.5.6,<0.6.0" }, ] -docs = [{ name = "sphinxnotes-markdown-builder", specifier = ">=0.5.6,<0.6.0" }] [[package]] name = "algokit-utils" From 8e22c083d159c44a71debbcd21846a77e7553116 Mon Sep 17 00:00:00 2001 From: David Rojas Date: Thu, 12 Mar 2026 15:18:35 -0500 Subject: [PATCH 13/19] docs: updated script links to cli.algokit.io (#714) * chore: bump algokit-utils to 5.0.0a18 * docs: updated script links to cli.algokit.io --- README.md | 4 ++-- docs/tutorials/intro.md | 2 +- scripts/install/install.ps1 | 2 +- scripts/install/install.sh | 2 +- src/algokit/cli/__init__.py | 2 +- uv.lock | 6 +++--- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0fd4f5987..0351a2234 100644 --- a/README.md +++ b/README.md @@ -101,13 +101,13 @@ AlgoKit is installed via [uv](https://docs.astral.sh/uv/), which handles Python ### macOS / Linux ```shell -curl -fsSL https://raw.githubusercontent.com/algorandfoundation/algokit-cli/decoupling/scripts/install/install.sh | bash +curl -fsSL https://cli.algokit.io/install.sh | bash ``` ### Windows (PowerShell) ```powershell -irm https://raw.githubusercontent.com/algorandfoundation/algokit-cli/decoupling/scripts/install/install.ps1 | iex +irm https://cli.algokit.io/install.ps1 | iex ``` ### What the installer does diff --git a/docs/tutorials/intro.md b/docs/tutorials/intro.md index 509227999..fc0332578 100644 --- a/docs/tutorials/intro.md +++ b/docs/tutorials/intro.md @@ -26,7 +26,7 @@ Before proceeding, ensure you have the following components installed: To install AlgoKit, run the following command from a terminal. ```shell -curl -fsSL https://raw.githubusercontent.com/algorandfoundation/algokit-cli/main/scripts/install/install.sh | bash +curl -fsSL https://cli.algokit.io/install.sh | bash ``` After the installation completes, **restart the terminal**. diff --git a/scripts/install/install.ps1 b/scripts/install/install.ps1 index fa2b565a5..bdc89ebf9 100644 --- a/scripts/install/install.ps1 +++ b/scripts/install/install.ps1 @@ -1,5 +1,5 @@ # AlgoKit CLI Installer for Windows (PowerShell) -# Usage: irm https://raw.githubusercontent.com/algorandfoundation/algokit-cli/main/scripts/install/install.ps1 | iex +# Usage: irm https://cli.algokit.io/install.ps1 | iex [CmdletBinding()] param() diff --git a/scripts/install/install.sh b/scripts/install/install.sh index ccfea490e..219259731 100755 --- a/scripts/install/install.sh +++ b/scripts/install/install.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # AlgoKit CLI Installer for Unix/macOS -# Usage: curl -fsSL https://raw.githubusercontent.com/algorandfoundation/algokit-cli/main/scripts/install/install.sh | bash +# Usage: curl -fsSL https://cli.algokit.io/install.sh | bash set -euo pipefail UV_INSTALL_URL="https://astral.sh/uv/install.sh" diff --git a/src/algokit/cli/__init__.py b/src/algokit/cli/__init__.py index daf987abd..af51046db 100644 --- a/src/algokit/cli/__init__.py +++ b/src/algokit/cli/__init__.py @@ -24,7 +24,7 @@ from algokit.core.log_handlers import color_option, verbose_option from algokit.core.utils import find_all_on_path, is_binary_mode -_INSTALL_URL_BASE = "https://raw.githubusercontent.com/algorandfoundation/algokit-cli/main/scripts/install" +_INSTALL_URL_BASE = "https://cli.algokit.io" _INSTALL_URL_SH = f"{_INSTALL_URL_BASE}/install.sh" _INSTALL_URL_PS1 = f"{_INSTALL_URL_BASE}/install.ps1" _ADR_URL = ( diff --git a/uv.lock b/uv.lock index bf9714589..daedb532e 100644 --- a/uv.lock +++ b/uv.lock @@ -114,7 +114,7 @@ docs = [ [[package]] name = "algokit-utils" -version = "5.0.0a17" +version = "5.0.0a18" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -124,9 +124,9 @@ dependencies = [ { name = "pynacl" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f1/06/dc995bfddff9bf64e67f9b74b6bced79e404f3f87a4948d85de7e6516045/algokit_utils-5.0.0a17.tar.gz", hash = "sha256:378773ec6d24a9838c7be90b79810359544848d9a7ddafd38655e9a468809bd3", size = 217266, upload-time = "2026-02-20T20:40:24.165Z" } +sdist = { url = "https://files.pythonhosted.org/packages/92/39/0cbc94eeeb9abe70c7269e5efb0abed54afa431e81b5f26b6e9e682c7ff1/algokit_utils-5.0.0a18.tar.gz", hash = "sha256:80e534490331a11e46a25fbbd8c6bdf2ac9e81c4dbbb54240c0f663d7a1cc7ce", size = 217589, upload-time = "2026-03-11T16:11:05.429Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/19/d4f4be3aae15294f8ab90e07be71abe82a10da862b4544878a005a6fcd68/algokit_utils-5.0.0a17-py3-none-any.whl", hash = "sha256:4c896e8cdfaedc32b67ff0bce6981d999e4da5319fe0aafcc749e16a820c0fdc", size = 337339, upload-time = "2026-02-20T20:40:22.708Z" }, + { url = "https://files.pythonhosted.org/packages/a1/af/d4529f066c25189a7725ff1896699df84e10c320b0b89118ff622b51ce75/algokit_utils-5.0.0a18-py3-none-any.whl", hash = "sha256:da8b893c917f3fbebee8de5bc427ed804ac2c4ad46022eeebdf0d6abfc6e2b47", size = 337536, upload-time = "2026-03-11T16:11:03.902Z" }, ] [[package]] From 399eaa7c81ebbd183e27045fbc0293e1e4990fae Mon Sep 17 00:00:00 2001 From: David Rojas Date: Fri, 13 Mar 2026 12:19:43 -0500 Subject: [PATCH 14/19] ci: add devportal publishing workflow, extract sidebar config, and standardize pnpm usage - Add publish-devportal-docs.yml workflow - Extract sidebar from astro.config.mjs to sidebar.config.json - Use package_json_file for pnpm version auto-detection in CI - Add packageManager field to docs/package.json - Fix docs-preview poe task from npm to pnpm --- .github/actions/build-docs/action.yml | 6 +- .github/workflows/publish-devportal-docs.yml | 32 +++++++++ docs/astro.config.mjs | 72 +------------------- docs/package.json | 1 + docs/sidebar.config.json | 70 +++++++++++++++++++ pyproject.toml | 2 +- 6 files changed, 109 insertions(+), 74 deletions(-) create mode 100644 .github/workflows/publish-devportal-docs.yml create mode 100644 docs/sidebar.config.json diff --git a/.github/actions/build-docs/action.yml b/.github/actions/build-docs/action.yml index 0af248b28..ace2f0c98 100644 --- a/.github/actions/build-docs/action.yml +++ b/.github/actions/build-docs/action.yml @@ -16,11 +16,11 @@ runs: - uses: pnpm/action-setup@v4 with: - version: 10 + package_json_file: docs/package.json - name: Install docs dependencies shell: bash - run: cd docs && pnpm install --frozen-lockfile + run: pnpm install --frozen-lockfile --dir docs - name: Generate CLI reference shell: bash @@ -28,4 +28,4 @@ runs: - name: Build Starlight site shell: bash - run: cd docs && pnpm run build \ No newline at end of file + run: pnpm --dir docs build \ No newline at end of file diff --git a/.github/workflows/publish-devportal-docs.yml b/.github/workflows/publish-devportal-docs.yml new file mode 100644 index 000000000..d4d3c04cb --- /dev/null +++ b/.github/workflows/publish-devportal-docs.yml @@ -0,0 +1,32 @@ +name: Publish DevPortal Docs + +on: + workflow_dispatch: + push: + branches: [ci/add-publish-to-devportal-workflow] # change to the branch you want to publish doc artifacts from + tags: ['v*'] + +permissions: + contents: write + +jobs: + publish-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version: 22 + - uses: pnpm/action-setup@v4 + with: + package_json_file: docs/package.json + - name: Setup Python environment + uses: algorandfoundation/algokit-shared-config/.github/actions/setup-algokit-python@main + with: + install-algokit: "false" + - name: Generate CLI reference + run: uv run poe docs-cli + - name: Publish DevPortal Docs + uses: algorandfoundation/devportal/.github/actions/publish-devportal-docs@release/ak-v4 + with: + docs-dir: docs \ No newline at end of file diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 690dc215b..6933f0bc2 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -2,6 +2,7 @@ import starlight from "@astrojs/starlight"; import { defineConfig } from "astro/config"; import remarkGithubAlerts from "remark-github-alerts"; +import sidebar from "./sidebar.config.json"; export default defineConfig({ site: "https://algorandfoundation.github.io", @@ -32,76 +33,7 @@ export default defineConfig({ href: "https://discord.gg/algorand", }, ], - sidebar: [ - { label: "Home", link: "/" }, - { - label: "Getting Started", - items: [ - { slug: "tutorials/intro" }, - { slug: "tutorials/smart-contracts" }, - { slug: "tutorials/algokit-template" }, - ], - }, - { - label: "Features", - items: [ - { slug: "features/overview" }, - { slug: "features/init" }, - { slug: "features/localnet" }, - { slug: "features/compile" }, - { slug: "features/generate" }, - { slug: "features/config" }, - { slug: "features/doctor" }, - { slug: "features/explore" }, - { slug: "features/dispenser" }, - { slug: "features/goal" }, - { slug: "features/completions" }, - { - label: "AlgoKit Project", - collapsed: true, - items: [ - { slug: "features/project" }, - { slug: "features/project/bootstrap" }, - { slug: "features/project/deploy" }, - { slug: "features/project/link" }, - { slug: "features/project/list" }, - { slug: "features/project/run" }, - ], - }, - { - label: "AlgoKit Task", - collapsed: true, - items: [ - { slug: "features/tasks" }, - { slug: "features/tasks/analyze" }, - { slug: "features/tasks/ipfs" }, - { slug: "features/tasks/mint" }, - { slug: "features/tasks/nfd" }, - { slug: "features/tasks/opt" }, - { slug: "features/tasks/send" }, - { slug: "features/tasks/sign" }, - { slug: "features/tasks/transfer" }, - { slug: "features/tasks/vanity_address" }, - { slug: "features/tasks/wallet" }, - ], - }, - ], - }, - { - label: "Concepts", - items: [{ slug: "concepts/output-stability" }], - }, - { - label: "Architecture Decisions", - collapsed: true, - autogenerate: { directory: "architecture-decisions" }, - }, - { - label: "CLI Reference", - collapsed: true, - items: [{ slug: "cli", label: "AlgoKit CLI" }], - }, - ], + sidebar, }), ], }); diff --git a/docs/package.json b/docs/package.json index aaf1c26ed..7ba49bead 100644 --- a/docs/package.json +++ b/docs/package.json @@ -12,6 +12,7 @@ "engines": { "node": ">=20" }, + "packageManager": "pnpm@10.30.3", "dependencies": { "@astrojs/starlight": "^0.37.6", "astro": "^5.6.1", diff --git a/docs/sidebar.config.json b/docs/sidebar.config.json new file mode 100644 index 000000000..e1530478c --- /dev/null +++ b/docs/sidebar.config.json @@ -0,0 +1,70 @@ +[ + { "label": "Home", "link": "/" }, + { + "label": "Getting Started", + "items": [ + { "slug": "tutorials/intro" }, + { "slug": "tutorials/smart-contracts" }, + { "slug": "tutorials/algokit-template" } + ] + }, + { + "label": "Features", + "items": [ + { "slug": "features/overview" }, + { "slug": "features/init" }, + { "slug": "features/localnet" }, + { "slug": "features/compile" }, + { "slug": "features/generate" }, + { "slug": "features/config" }, + { "slug": "features/doctor" }, + { "slug": "features/explore" }, + { "slug": "features/dispenser" }, + { "slug": "features/goal" }, + { "slug": "features/completions" }, + { + "label": "AlgoKit Project", + "collapsed": true, + "items": [ + { "slug": "features/project" }, + { "slug": "features/project/bootstrap" }, + { "slug": "features/project/deploy" }, + { "slug": "features/project/link" }, + { "slug": "features/project/list" }, + { "slug": "features/project/run" } + ] + }, + { + "label": "AlgoKit Task", + "collapsed": true, + "items": [ + { "slug": "features/tasks" }, + { "slug": "features/tasks/analyze" }, + { "slug": "features/tasks/ipfs" }, + { "slug": "features/tasks/mint" }, + { "slug": "features/tasks/nfd" }, + { "slug": "features/tasks/opt" }, + { "slug": "features/tasks/send" }, + { "slug": "features/tasks/sign" }, + { "slug": "features/tasks/transfer" }, + { "slug": "features/tasks/vanity_address" }, + { "slug": "features/tasks/wallet" } + ] + } + ] + }, + { + "label": "Concepts", + "items": [{ "slug": "concepts/output-stability" }] + }, + { + "label": "Architecture Decisions", + "collapsed": true, + "autogenerate": { "directory": "architecture-decisions" } + }, + { + "label": "CLI Reference", + "collapsed": true, + "items": [{ "slug": "cli", "label": "AlgoKit CLI" }] + } +] \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index ba1195e06..3d2782e16 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,7 +76,7 @@ docs = [ docs-cli = "python docs/cli_build.py" docs-dev = { shell = "python docs/cli_build.py && pnpm --dir docs run dev" } docs-build = { shell = "python docs/cli_build.py && pnpm --dir docs run build" } -docs-preview = "npm run --prefix docs preview" +docs-preview = "pnpm --dir docs preview" package_unix = "pyinstaller --clean --onedir --hidden-import jinja2_ansible_filters --hidden-import multiformats_config --hidden-import algokit_utils.algo25 --hidden-import algokit_utils.transact --hidden-import algokit_utils.common --hidden-import algokit_utils.clients --hidden-import algokit_utils.transactions.builders --hidden-import algokit_utils.transactions.types --copy-metadata algokit --name algokit --noconfirm src/algokit/__main__.py --add-data './misc/multiformats_config:multiformats_config/' --add-data './src/algokit/resources:algokit/resources/'" package_windows = { cmd = "scripts/package_windows.bat" } package_mac = { cmd = "scripts/package_mac.sh" } From 0db1a43edcf1dfce2bfa1ffc0c89fe8e6cf2ba1f Mon Sep 17 00:00:00 2001 From: Luca Martini Date: Thu, 26 Mar 2026 18:47:02 +0100 Subject: [PATCH 15/19] docs: remove legacy markdown files and update startlight content --- docs/features/compile.md | 168 ------------------- docs/features/doctor.md | 53 ------ docs/features/generate.md | 179 --------------------- docs/src/content/docs/features/compile.md | 2 +- docs/src/content/docs/features/doctor.md | 30 ++-- docs/src/content/docs/features/generate.md | 4 +- docs/src/content/docs/index.mdx | 21 ++- docs/src/content/docs/tutorials/intro.md | 18 ++- docs/tutorials/intro.md | 167 ------------------- 9 files changed, 37 insertions(+), 605 deletions(-) delete mode 100644 docs/features/compile.md delete mode 100644 docs/features/doctor.md delete mode 100644 docs/features/generate.md delete mode 100644 docs/tutorials/intro.md diff --git a/docs/features/compile.md b/docs/features/compile.md deleted file mode 100644 index 90b3a5c49..000000000 --- a/docs/features/compile.md +++ /dev/null @@ -1,168 +0,0 @@ -# AlgoKit Compile - -The AlgoKit Compile feature enables you to compile smart contracts (apps) and smart signatures (logic signatures) written in a supported high-level language to a format deployable on the Algorand Virtual Machine (AVM). - -When running the compile command, AlgoKit will take care of working out which compiler you need and dynamically resolve it. Additionally, AlgoKit will detect if a matching compiler version is already installed globally on your machine or is included in your project and use that. - -## Prerequisites - -See [Compile Python - Prerequisites](#prerequisites-1) and [Compile TypeScript - Prerequisites](#prerequisites-2) for details. - -## What is Algorand Python & PuyaPy? - -Algorand Python is a semantically and syntactically compatible, typed Python language that works with standard Python tooling and allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM). - -Algorand Python can be deployed to Algorand by using the PuyaPy optimising compiler, which takes Algorand Python and outputs [ARC-32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) application spec files (among other formats) which, [when deployed](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients), will result in AVM bytecode execution semantics that match the given Python code. - -If you want to learn more, check out the [PuyaPy docs](https://github.com/algorandfoundation/puya/blob/main/docs/index.md). - -Below is an example Algorand Python smart contract. - -```py -from algopy import ARC4Contract, arc4 - -class HelloWorldContract(ARC4Contract): - @arc4.abimethod - def hello(self, name: arc4.String) -> arc4.String: - return "Hello, " + name -``` - -For more complex examples, see the [examples](https://github.com/algorandfoundation/puya/tree/main/examples) in the [PuyaPy repo](https://github.com/algorandfoundation/puya). - -## What is Algorand TypeScript & PuyaTs? - -Algorand TypeScript is a typed TypeScript language that allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM). Algorand TypeScript is currently in beta. - -Algorand TypeScript can be deployed to Algorand by using the PuyaTs optimising compiler, which takes Algorand TypeScript and outputs [ARC-32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) application spec files (among other formats) which, [when deployed](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients), will result in AVM bytecode execution semantics that match the given TypeScript code. - -Below is an example Algorand TypeScript smart contract. - -```typescript -import { Contract } from "@algorandfoundation/puya-sdk"; - -class HelloWorldContract extends Contract { - hello(name: string): string { - return "Hello, " + name; - } -} -``` - -## Usage - -Available commands and possible usage are as follows: - -``` -Usage: algokit compile [OPTIONS] COMMAND [ARGS]... - - Compile smart contracts and smart signatures written in a supported high-level language to a format deployable on - the Algorand Virtual Machine (AVM). - -Options: - -v, --version TEXT The compiler version to pin to, for example, 1.0.0. If no version is specified, AlgoKit checks - if the compiler is installed and runs the installed version. If the compiler is not installed, - AlgoKit runs the latest version. If a version is specified, AlgoKit checks if an installed - version matches and runs the installed version. Otherwise, AlgoKit runs the specified version. - -h, --help Show this message and exit. - -Commands: - py Compile Algorand Python contract(s) using the PuyaPy compiler. - python Compile Algorand Python contract(s) using the PuyaPy compiler. - ts Compile Algorand TypeScript contract(s) using the PuyaTs compiler. - typescript Compile Algorand TypeScript contract(s) using the PuyaTs compiler. -``` - -### Compile Python - -The command `algokit compile python` or `algokit compile py` will run the [PuyaPy](https://github.com/algorandfoundation/puya) compiler against the supplied Algorand Python smart contract. - -All arguments supplied to the command are passed directly to PuyaPy, therefore this command supports all options supported by the PuyaPy compiler. - -Any errors detected by PuyaPy during the compilation process will be printed to the output. - -#### Prerequisites - -PuyaPy requires Python 3.12+, so please ensure your Python version satisfies this requirement. - -This command will attempt to resolve a matching installed PuyaPy compiler, either globally installed in the system or locally installed in your project (via [uv](https://docs.astral.sh/uv/) or [Poetry](https://python-poetry.org/)). If no appropriate match is found, the PuyaPy compiler will be dynamically run using [uv](https://docs.astral.sh/uv/) (or [pipx](https://pipx.pypa.io/stable/) as a fallback). - -#### Examples - -To see a list of the supported PuyaPy options, run the following: - -```shell -algokit compile python -h -``` - -To determine the version of the PuyaPy compiler in use, execute the following command: - -```shell -algokit compile python --version -``` - -To compile a single Algorand Python smart contract and write the output to a specific location, run the following: - -```shell -algokit compile python hello_world/contract.py --out-dir hello_world/out -``` - -To compile multiple Algorand Python smart contracts and write the output to a specific location, run the following: - -```shell -algokit compile python hello_world/contract.py calculator/contract.py --out-dir my_contracts -``` - -To compile a directory of Algorand Python smart contracts and write the output to the default location, run the following: - -```shell -algokit compile python my_contracts -``` - -### Compile TypeScript - -The command `algokit compile typescript` or `algokit compile ts` will run the PuyaTs compiler against the supplied Algorand TypeScript smart contract. - -All arguments supplied to the command are passed directly to PuyaTs, therefore this command supports all options supported by the PuyaTs compiler. - -Any errors detected by PuyaTs during the compilation process will be printed to the output. - -#### Prerequisites - -PuyaTs requires Node 22+ and NPM 10+, so please ensure your versions satisfy this requirement. - -The command will attempt to find a correctly installed PuyaTs compiler in the following order: - -1. First, it checks if a matching version is installed at the project level (using `npm ls`). -2. Next, it checks if a matching version is installed globally (using `npm --global ls`). -3. If no appropriate match is found, it will run the compiler using npx with the `-y` flag. - -#### Examples - -To see a list of the supported PuyaTs options, run the following: - -```shell -algokit compile typescript -h -``` - -To determine the version of the PuyaTs compiler in use, execute the following command: - -```shell -algokit compile typescript --version -``` - -To compile a single Algorand TypeScript smart contract and write the output to a specific location, run the following: - -```shell -algokit compile typescript hello_world/contract.algo.ts --out-dir hello_world/out -``` - -To build multiple Algorand TypeScript smart contracts and write the output to a specific location, run the following: - -```shell -algokit compile typescript hello_world/contract.algo.ts calculator/contract.algo.ts --out-dir my_contracts -``` - -To compile a directory of Algorand TypeScript smart contracts and write the output to the default location, run the following: - -```shell -algokit compile typescript my_contracts -``` diff --git a/docs/features/doctor.md b/docs/features/doctor.md deleted file mode 100644 index bd002ea64..000000000 --- a/docs/features/doctor.md +++ /dev/null @@ -1,53 +0,0 @@ -# AlgoKit Doctor - -The AlgoKit Doctor feature allows you to check your AlgoKit installation along with its dependencies. This is useful for diagnosing potential issues with using AlgoKit. - -## Functionality - -The AlgoKit Doctor allows you to make sure that your system has the correct dependencies installed and that they satisfy the minimum required versions. All passed checks will appear in your command line natural color while warnings will be in yellow (warning) and errors or missing critical services will be in red (error). The critical services that AlgoKit will check for (since they are [directly used by certain commands](../../README.md#prerequisites)): Docker, docker compose and git. - -Please run this command to if you are facing an issue running AlgoKit. It is recommended to run it before [submitting an issue to AlgoKit](https://github.com/algorandfoundation/algokit-cli/issues/new). You can copy the contents of the Doctor command message (in Markdown format) to your clipboard by providing the `-c` flag to the command as follows `algokit doctor -c`. - -> NOTE: You can also use the `--verbose` or `-v` flag to show additional information including package dependencies of the AlgoKit CLI: `algokit -v doctor`. This only works when `algokit` is installed as a Python package (e.g., via `uv tool install algokit`). - -# Examples - -For example, running `algokit doctor` with all prerequisites installed will result in output similar to the following: - -``` -$ ~ algokit doctor -timestamp: 2023-03-29T03:58:05+00:00 -AlgoKit: 2.10.2 -AlgoKit Python: 3.12.11 (location: ~/.local/share/uv/tools/algokit) -OS: macOS-15.0-arm64-arm-64bit -docker: 27.5.1 -docker compose: 2.32.4 -git: 2.47.0 -python: 3.12.11 (location: ~/.local/share/uv/python/cpython-3.12.11) -python3: 3.12.11 (location: ~/.local/share/uv/python/cpython-3.12.11) -uv: 0.10.7 -node: 22.14.0 -npm: 10.9.2 - -If you are experiencing a problem with AlgoKit, feel free to submit an issue via: -https://github.com/algorandfoundation/algokit-cli/issues/new -Please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` -``` - -The doctor command will indicate if there is any issues to address, for example: - -If AlgoKit detects a newer version, this will be indicated next to the AlgoKit version - -``` -AlgoKit: 1.2.3 (latest: 4.5.6) -``` - -If the detected version of docker compose is unsupported, this will be shown: - -``` -docker compose: 2.1.3 - Docker Compose 2.5.0 required to run `algokit localnet command`; - install via https://docs.docker.com/compose/install/ -``` - -For more details about the `AlgoKit doctor` command, please refer to the [AlgoKit CLI reference documentation](../cli/index.md#doctor). diff --git a/docs/features/generate.md b/docs/features/generate.md deleted file mode 100644 index 0a94f97d0..000000000 --- a/docs/features/generate.md +++ /dev/null @@ -1,179 +0,0 @@ -# AlgoKit Generate - -The `algokit generate` [command](../cli/index.md#generate) is used to generate components used in an AlgoKit project. It also allows for custom generate commands which are loaded from the .algokit.toml file in your project directory. - -## 1. Typed clients - -The `algokit generate client` [command](../cli/index.md#client) can be used to generate a typed client from an [ARC-0032](https://arc.algorand.foundation/ARCs/arc-0032) or [ARC-0056](https://github.com/algorandfoundation/ARCs/pull/258) application specification with both Python and TypeScript available as target languages. - -### Prerequisites - -To generate Python clients an installation of Python and uv (or pipx) is required. -To generate TypeScript clients an installation of Node.js and npx is also required. - -Each generated client will also have a dependency on `algokit-utils` libraries for the target language. - -### Input file / directory - -You can either specify a path to an ARC-0032 JSON file, an ARC-0056 JSON file or to a directory that is recursively scanned for `application.json`, `*.arc32.json`, `*.arc56.json` file(s). - -### Output tokens - -The output path is interpreted as relative to the current working directory, however an absolute path may also be specified e.g. -`algokit generate client application.json --output /absolute/path/to/client.py` - -There are two tokens available for use with the `-o`, `--output` [option](../cli/index.md#-o---output-output_path_pattern): - -- `{contract_name}`: This will resolve to a name based on the ARC-0032/ARC-0056 contract name, formatted appropriately for the target language. -- `{app_spec_dir}`: This will resolve to the parent directory of the `application.json`, `*.arc32.json`, `*.arc56.json` file which can be useful to output a client relative to its source file. - -### Version Pinning - -If you want to ensure typed client output stability across different environments and additionally protect yourself from any potential breaking changes introduced in the client generator packages, you can specify a version you'd like to pin to. - -To make use of this feature, pass `-v`, `--version`, for example `algokit generate client --version 1.2.3 path/to/application.json`. - -Alternatively, you can achieve output stability by installing the underlying [Python](https://github.com/algorandfoundation/algokit-client-generator-py) or [TypeScript](https://github.com/algorandfoundation/algokit-client-generator-ts) client generator package either locally in your project (via `uv` or `npm` respectively) or globally on your system (via `uv tool` or `npm` respectively). AlgoKit will search for a matching installed version before dynamically resolving. - -### Usage - -Usage examples of using a generated client are below, typed clients allow your favourite IDE to provide better intellisense to provide better discoverability -of available operations and parameters. - -#### Python - -```python -# A similar working example can be seen in the algokit python template, when using Python deployment -from smart_contracts.artifacts.HelloWorldApp.client import ( - HelloWorldAppClient, -) - -app_client = HelloWorldAppClient( - algod_client, - creator=deployer, - indexer_client=indexer_client, -) -deploy_response = app_client.deploy( - on_schema_break=OnSchemaBreak.ReplaceApp, - on_update=OnUpdate.UpdateApp, - allow_delete=True, - allow_update=True, -) - -response = app_client.hello(name="World") -``` - -#### TypeScript - -```typescript -// A similar working example can be seen in the algokit python template with typescript deployer, when using TypeScript deployment -import { HelloWorldAppClient } from "./artifacts/HelloWorldApp/client"; - -const appClient = new HelloWorldAppClient( - { - resolveBy: "creatorAndName", - findExistingUsing: indexer, - sender: deployer, - creatorAddress: deployer.addr, - }, - algod -); -const app = await appClient.deploy({ - allowDelete: isLocal, - allowUpdate: isLocal, - onSchemaBreak: isLocal ? "replace" : "fail", - onUpdate: isLocal ? "update" : "fail", -}); -const response = await appClient.hello({ name: "world" }); -``` - -### Examples - -To output a single application.json to a python typed client: -`algokit generate client path/to/application.json --output client.py` - -To process multiple application.json in a directory structure and output to a typescript client for each in the current directory: -`algokit generate client smart_contracts/artifacts --output {contract_name}.ts` - -To process multiple application.json in a directory structure and output to a python client alongside each application.json: -`algokit generate client smart_contracts/artifacts --output {app_spec_path}/client.py` - -## 2. Using Custom Generate Commands - -Custom generate commands are defined in the `.algokit.toml` file within the project directory, typically supplied by community template builders or official AlgoKit templates. These commands are specified under the `generate` key and serve to execute a generator at a designated path with provided answer key/value pairs. - -### Understanding `Generators` - -A `generator` is essentially a compact, self-sufficient `copier` template. This template can optionally be defined within the primary `algokit templates` to offer supplementary functionality after a project is initialized from the template. For instance, the official [`algokit-python-template`](https://github.com/algorandfoundation/algokit-python-template/tree/main/template_content) provides a generator within the `.algokit/generators` directory. This generator can be employed for executing extra tasks on AlgoKit projects that have been initiated from this template, such as adding new smart contracts to an existing project. For a comprehensive explanation, please refer to the [`architecture decision record`](../architecture-decisions/2023-07-19_advanced_generate_command.md). - -### Requirements - -To utilize custom generate commands, you must have `copier` installed. This installation is included by default in the AlgoKit CLI. Therefore, no additional installation is necessary if you have already installed the `algokit cli`. - -### How to Use - -A custom command can be defined in the `.algokit.toml` as shown: - -```toml -[generate.my_generator] -path = "path/to/my_generator" -description = "A brief description of the function of my_generator" -``` - -Following this, you can execute the command as follows: - -`algokit generate my_generator --answer key value --path path/to/my_generator` - -If no `path` is given, the command will use the path specified in the `.algokit.toml`. If no `answer` is provided, the command will initiate an interactive `copier` prompt to request answers (similar to `algokit init`). - -The custom command employs the `copier` library to duplicate the files from the generator's path to the current working directory, substituting any values from the `answers` dictionary. - -### Examples - -As an example, let's use the `smart-contract` generator from the `algokit-python-template` to add new contract to an existing project based on that template. The `smart-contract` generator is defined as follows: - -```toml -[algokit] -min_version = "v1.3.1" - -... # other keys - -[generate.smart_contract] -description = "Adds a new smart contract to the existing project" -path = ".algokit/generators/create_contract" -``` - -To execute this generator, ensure that you are operating from the same directory as the `.algokit.toml` file, and then run: - -```bash -$ algokit generate - -# The output will be as follows: -# Note how algokit dynamically injects a new `smart-contract` command based -# on the `.algokit.toml` file - -Usage: algokit generate [OPTIONS] COMMAND [ARGS]... - - Generate code for an Algorand project. - -Options: - -h, --help Show this message and exit. - -Commands: - client Create a typed ApplicationClient from an ARC-32 application.json - smart-contract Adds a new smart contract to the existing project -``` - -To execute the `smart-contract` generator, run: - -```bash -$ algokit generate smart-contract - -# or - -$ algokit generate smart-contract -a contract_name "MyCoolContract" -``` - -#### Third Party Generators - -It is important to understand that by default, AlgoKit will always prompt you before executing a generator to ensure it's from a trusted source. If you are confident about the source of the generator, you can use the `--force` or `-f` option to execute the generator without this confirmation prompt. Be cautious while using this option and ensure the generator is from a trusted source. At the moment, a trusted source for a generator is defined as _a generator that is included in the official AlgoKit templates (e.g. `smart-contract` generator in `algokit-python-template`)_ diff --git a/docs/src/content/docs/features/compile.md b/docs/src/content/docs/features/compile.md index 86ca49a48..d3095a922 100644 --- a/docs/src/content/docs/features/compile.md +++ b/docs/src/content/docs/features/compile.md @@ -85,7 +85,7 @@ Any errors detected by PuyaPy during the compilation process will be printed to PuyaPy requires Python 3.12+, so please ensure your Python version satisfies this requirement. -This command will attempt to resolve a matching installed PuyaPy compiler, either globally installed in the system or locally installed in your project (via [Poetry](https://python-poetry.org/)). If no appropriate match is found, the PuyaPy compiler will be dynamically run using [pipx](https://pipx.pypa.io/stable/). In this case pipx is also required. +This command will attempt to resolve a matching installed PuyaPy compiler, either globally installed in the system or locally installed in your project (via [uv](https://docs.astral.sh/uv/) or [Poetry](https://python-poetry.org/)). If no appropriate match is found, the PuyaPy compiler will be dynamically run using [uv](https://docs.astral.sh/uv/) (or [pipx](https://pipx.pypa.io/stable/) as a fallback). #### Examples diff --git a/docs/src/content/docs/features/doctor.md b/docs/src/content/docs/features/doctor.md index d2691f9b8..fb3033199 100644 --- a/docs/src/content/docs/features/doctor.md +++ b/docs/src/content/docs/features/doctor.md @@ -10,28 +10,26 @@ The AlgoKit Doctor allows you to make sure that your system has the correct depe Please run this command to if you are facing an issue running AlgoKit. It is recommended to run it before [submitting an issue to AlgoKit](https://github.com/algorandfoundation/algokit-cli/issues/new). You can copy the contents of the Doctor command message (in Markdown format) to your clipboard by providing the `-c` flag to the command as follows `algokit doctor -c`. -> NOTE: You can also use the `--verbose` or `-v` flag to show additional information including package dependencies of the AlgoKit CLI: `algokit -v doctor`. This only works when `algokit` is installed as a Python package (e.g., via `pipx install algokit`). +> NOTE: You can also use the `--verbose` or `-v` flag to show additional information including package dependencies of the AlgoKit CLI: `algokit -v doctor`. This only works when `algokit` is installed as a Python package (e.g., via `uv tool install algokit`). # Examples For example, running `algokit doctor` with all prerequisites installed will result in output similar to the following: -```bash -algokit doctor +``` +$ ~ algokit doctor timestamp: 2023-03-29T03:58:05+00:00 -AlgoKit: 0.6.0 -AlgoKit Python: 3.11.2 (main, Mar 24 2023, 00:16:47) [Clang 14.0.0 (clang-1400.0.29.202)] (location: /Users/algokit/.local/pipx/venvs/algokit) -OS: macOS-13.2.1-arm64-arm-64bit -docker: 20.10.22 -docker compose: 2.15.1 -git: 2.39.1 -python: 3.10.9 (location: /Users/algokit/.asdf/shims/python) -python3: 3.10.9 (location: /Users/algokit/.asdf/shims/python3) -pipx: 1.2.0 -poetry: 1.3.2 -node: 18.12.1 -npm: 8.19.2 -brew: 4.0.10-34-gb753315 +AlgoKit: 2.10.2 +AlgoKit Python: 3.12.11 (location: ~/.local/share/uv/tools/algokit) +OS: macOS-15.0-arm64-arm-64bit +docker: 27.5.1 +docker compose: 2.32.4 +git: 2.47.0 +python: 3.12.11 (location: ~/.local/share/uv/python/cpython-3.12.11) +python3: 3.12.11 (location: ~/.local/share/uv/python/cpython-3.12.11) +uv: 0.10.7 +node: 22.14.0 +npm: 10.9.2 If you are experiencing a problem with AlgoKit, feel free to submit an issue via: https://github.com/algorandfoundation/algokit-cli/issues/new diff --git a/docs/src/content/docs/features/generate.md b/docs/src/content/docs/features/generate.md index b4d63e3d0..2668a25d1 100644 --- a/docs/src/content/docs/features/generate.md +++ b/docs/src/content/docs/features/generate.md @@ -10,7 +10,7 @@ The `algokit generate client` [command](/algokit-cli/cli/#client) can be used to ### Prerequisites -To generate Python clients an installation of pip and pipx is required. +To generate Python clients an installation of Python and uv (or pipx) is required. To generate TypeScript clients an installation of Node.js and npx is also required. Each generated client will also have a dependency on `algokit-utils` libraries for the target language. @@ -35,7 +35,7 @@ If you want to ensure typed client output stability across different environment To make use of this feature, pass `-v`, `--version`, for example `algokit generate client --version 1.2.3 path/to/application.json`. -Alternatively, you can achieve output stability by installing the underlying [Python](https://github.com/algorandfoundation/algokit-client-generator-py) or [TypeScript](https://github.com/algorandfoundation/algokit-client-generator-ts) client generator package either locally in your project (via `poetry` or `npm` respectively) or globally on your system (via `pipx` or `npm` respectively). AlgoKit will search for a matching installed version before dynamically resolving. +Alternatively, you can achieve output stability by installing the underlying [Python](https://github.com/algorandfoundation/algokit-client-generator-py) or [TypeScript](https://github.com/algorandfoundation/algokit-client-generator-ts) client generator package either locally in your project (via `uv` or `npm` respectively) or globally on your system (via `uv tool` or `npm` respectively). AlgoKit will search for a matching installed version before dynamically resolving. ### Usage diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 85203e54c..22922f0da 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -19,23 +19,20 @@ import { Card, CardGrid, Tabs, TabItem } from '@astrojs/starlight/components'; ## Installation - + ```bash - brew install algorandfoundation/tap/algokit + curl -fsSL https://cli.algokit.io/install.sh | bash ``` - ```bash - winget install AlgoKit - ``` - - - ```bash - pipx install algokit + ```powershell + irm https://cli.algokit.io/install.ps1 | iex ``` +> The install script handles installing `uv` and Python automatically. Legacy installation methods via `brew`, `winget`, and `snap` are also available — see the [official installation guide](https://github.com/algorandfoundation/algokit-cli#install). + ## Quick Start ```bash @@ -55,16 +52,16 @@ algokit explore ## Features - + Quickly scaffold new Algorand projects from official templates or community templates. Spin up a local isolated Algorand network for development and testing. - + Compile Algorand Python and other smart contract languages to AVM bytecode. - + Deploy smart contracts to LocalNet, TestNet or MainNet with a single command. diff --git a/docs/src/content/docs/tutorials/intro.md b/docs/src/content/docs/tutorials/intro.md index 4dcfe3900..9f1891f6c 100644 --- a/docs/src/content/docs/tutorials/intro.md +++ b/docs/src/content/docs/tutorials/intro.md @@ -20,8 +20,6 @@ This guide presents installing AlgoKit using an OS agnostic procedure. For OS sp Before proceeding, ensure you have the following components installed: -- [Python 3.10](https://www.python.org/downloads/) or higher -- [pipx](https://pypa.github.io/pipx/#on-linux-install-via-pip-requires-pip-190-or-later) - [git](https://github.com/git-guides/install-git#install-git) - [Docker](https://docs.docker.com/desktop/install/mac-install/) (or [Podman](https://podman.io/getting-started/installation/), see [details](/algokit-cli/features/localnet/#podman-support)) - [VSCode](https://code.visualstudio.com/download) @@ -30,15 +28,23 @@ Before proceeding, ensure you have the following components installed: To install AlgoKit, run the following command from a terminal. +**macOS / Linux:** + ```shell -pipx install algokit +curl -fsSL https://cli.algokit.io/install.sh | bash +``` + +**Windows (PowerShell):** + +```powershell +irm https://cli.algokit.io/install.ps1 | iex ``` After the installation completes, **restart the terminal**. For more detailed installation documentation, see the [official installation guide](https://github.com/algorandfoundation/algokit-cli#install). -> Please note, `pipx` is only one of the supported installation methods. You can also install AlgoKit via `brew` and _soon_ `winget` and `snap` as pre-build binaries. Refer to the official installation guide. +> The install script handles installing `uv` and Python automatically. Legacy installation methods via `brew`, `winget`, and `snap` are also available — see the [official installation guide](https://github.com/algorandfoundation/algokit-cli#install). ## Verify the Installation @@ -102,9 +108,7 @@ The structure of your fresh algokit project instance will look similar to below: ├── README.md # Quick start on Algorand Python smart contract template based project. ├── .algokit # Hidden folder for AlgoKit AVM debugger and custom generators. ├── .algokit.toml # Project-specific commands and custom generator references. - ├── poetry.lock - ├── poetry.toml # Dependency definitions for {your_project_name}. - ├── pyproject.toml # Project definitions for {your_project_name}. + ├── pyproject.toml # Dependency and project definitions for {your_project_name}. └── smart_contracts ├── README.md # Guide for adding new smart contracts. ├── ... diff --git a/docs/tutorials/intro.md b/docs/tutorials/intro.md deleted file mode 100644 index fc0332578..000000000 --- a/docs/tutorials/intro.md +++ /dev/null @@ -1,167 +0,0 @@ -# AlgoKit Quick Start Tutorial - -AlgoKit is the primary tool used by the Algorand community to develop smart contracts on the Algorand blockchain. It provides the capabilities to develop, test and deploy Algorand smart contracts within minutes! This guide is intended to help you setup AlgoKit and to start developing your application. - -## Quick start videos 📹 - -If you prefer videos, take a look at this 10 minute guide to getting started. - -[![Learn How to Build on Algorand in 10 Minutes](../imgs/algokit-intro-video-thumbnail.jpg)](https://www.youtube.com/embed/dow6U8DxOGc) - -Detailed video guides for both [Windows](https://www.youtube.com/embed/22RvINnZsRo) and [Mac](https://www.youtube.com/embed/zsurtpCGmgE) are also available. - -> Please note, the videos above are to be refreshed to cover v2.0 features. For now, its best to follow the instructions below to get started. - -## Prequisites ✅ - -This guide presents installing AlgoKit using an OS agnostic procedure. For OS specific instructions take a look that the [AlgoKit install](https://github.com/algorandfoundation/algokit-cli/blob/main/README.md#install) guide. - -Before proceeding, ensure you have the following components installed: - -- [git](https://github.com/git-guides/install-git#install-git) -- [Docker](https://docs.docker.com/desktop/install/mac-install/) (or [Podman](https://podman.io/getting-started/installation/), see [details](../features/localnet.md#podman-support)) -- [VSCode](https://code.visualstudio.com/download) -## Install AlgoKit 🛠 - -To install AlgoKit, run the following command from a terminal. - -```shell -curl -fsSL https://cli.algokit.io/install.sh | bash -``` - -After the installation completes, **restart the terminal**. - -For more detailed installation documentation, see the [official installation guide](https://github.com/algorandfoundation/algokit-cli#install). - -> The install script handles installing `uv` and Python automatically. For alternative installation methods, see the [official installation guide](https://github.com/algorandfoundation/algokit-cli#install). - -## Verify the Installation ✔ - -To verify AlgoKit Installed correctly run the following. - -```shell -algokit --version -``` - -Output similar to the following should be displayed: - -```shell -algokit, version 2.0.3 # or higher -``` - -## Start a LocalNet 🌐 - -AlgoKit supports using a [local version of the Algorand blockchain](../features/localnet.md). To start an instance of this LocalNet run the following command from the terminal: - -```shell -algokit localnet start -``` - -This should start an instance of the LocalNet within docker. If you open the Docker Desktop application you should see something similar to the following: - -![Docker Desktop LocalNet Instance](../imgs/localnet.png) - -## Create an AlgoKit project 🆕 - -Now that AlgoKit is installed, you can rapidly create a new project to get started quickly. This can be done by running: - -```shell -algokit init -``` - -This will launch a guided menu system to create a specific project tailored to your needs. The templates are basic starter applications for various Algorand development scenarios. To read more about templates checkout AlgoKit detailed documentation. - -For now we'll use the `python` template, which is a lightweight starting point for learning Algorand smart contract development using Algorand Python. You can initialize a project using this template by running: - -```shell -algokit init -t python -a preset_name "starter" -``` - -Next, you will be prompted for the name of your project. Finally, select the default value for the rest of the prompts (enter). - -Once finished, (if you have it installed) VS Code should automatically be opened with the initialised project and you will be prompted to install appropriate VS Code extensions. This starter app will contain one smart contract (built using the [Algorand Python](https://algorandfoundation.github.io/puya/) language) named `contract.py`, in the `smart_contracts/hello_world` folder, with one method (`hello`) that takes a `String` and returns a `String`. Notice that within the contract folder, there is a `deploy_config.py` which defines the parameters for deployment of your smart contract to the target chain (Algorand TestNet, Algorand MainNet, Algorand LocalNet or else). - -![AlgoKit Playground Contract](../imgs/algokitplayground.png) - -## AlgoKit Project structure 🏗 - -The structure of your fresh algokit project instance will look similar to below: - -```bash -. -├── .algokit.toml # Configuration for AlgoKit projects in the workspace. -├── README.md # Quick start guide for the AlgoKit Workspace. -├── {your_workspace|project_name}.code-workspace -└── projects - └── {your_project_name} # Root directory for the smart contract project. To add more projects into your algokit workspace run 'algokit init' from the root of your workspace repository. - ├── README.md # Quick start on Algorand Python smart contract template based project. - ├── .algokit # Hidden folder for AlgoKit AVM debugger and custom generators. - ├── .algokit.toml # Project-specific commands and custom generator references. - ├── pyproject.toml # Dependency definitions for {your_project_name}. - ├── pyproject.toml # Project definitions for {your_project_name}. - └── smart_contracts - ├── README.md # Guide for adding new smart contracts. - ├── ... - ├── hello_world # Contract logic for 'hello_world'. - │ ├── contract.py # Contract logic. - │ └── deploy_config.py # Deployment logic for 'hello_world'. - └── helpers # Helper functions for contract build and deployment. -``` - -Additionally, each official smart contract template includes an interactive codespace walkthrough powered by [CodeTour](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour). - -To start the interactive walkthrough, install the extension and click on the green play button in the left bottom corner of the `Explorer` pane as demonstrated on the screenshot below (See `Getting Started with Your AlgoKit Project`). - -![CodeTour Play Button](../imgs/algokitcodetour.png) - -Upon execution, the walkthrough will guide you through the key components of your fresh AlgoKit project, which is an important prerequisite to learn before running and deploying your first smart contract. Certainly, not because its hard to learn, but because it will save you a lot of time and effort having the correct foundations. - -## Run the Demo Application 🏃‍♂️ - -Once the `Algorand Python` based project is created, you can get started by building and deploying your first smart contract. There are a few possible ways to do so as demonstrated on the following video. - -[![Watch the video](https://ipfs.algonode.xyz/ipfs/Qmc9mRaPoDyhUFmek4ETxVfKUKzUg9pf3Tss5xwkBGdQis)](https://ipfs.algonode.xyz/ipfs/Qma6gNqxsSFc9Jbh8kBTZyVLv5gqFj1xnrsjoeT6MAAwCw/) - -The App ID of the deployed contract and its Algorand address is displayed, followed by the message returned from the smart contract call (`Hello, Python`). - -1. Start LocalNet -2. Build the smart contract. Notice how a folder named `artifacts` is created with the [AVM (Algorand Virtual Machine)](https://dev.algorand.co/concepts/smart-contracts/avm/) related artifacts for deploying your smart contract. -3. Deploy and call the `HelloWorld` smart contract (from `contract.py` file). - -After execution, the `App ID` of the deployed contract and its Algorand address are displayed, followed by the message returned from the smart contract call (`Hello, world`). - -At this point you have deployed a simple contract to a LocalNet Algorand network (running in your Docker environment) and called it successfully! - -Additionally, you can find the native AVM related artifacts and the appropriate smart contract manifest JSON files have been output to the `artifacts` folder. Note that in this example, AVM bytecode is compiled using the `PuyaPy` compiler, which is what `Algorand Python` relies on to compile your Python smart contract code to TEAL ([Transaction Execution Approval Language](https://dev.algorand.co/concepts/smart-contracts/languages/teal)). - -### Using AlgoKit CLI to build and deploy contracts 🛠️ - -When using official AlgoKit templates via `algokit init`, you can manage your projects using the AlgoKit CLI at the convenience of your terminal. - -For example, to achieve the same results as in the demo earlier, build and deploy the `HelloWorld` contract from the `contract.py` file by running the following command from the terminal: - -```shell -algokit project run build -``` - -This command will recompile your python contracts from `contract.py` and produce the necessary artefacts for deploying your contract. - -```shell -algokit project deploy localnet -``` - -This will then deploy to your LocalNet instance and display the same output as in the earlier demo. - -> Please note, as highlighted in the [structure](#algokit-project-structure) section above, the `project run ...` commands are defined in the respective `.algokit.toml` file under `[project]` sections. - -## Next steps 🚶‍♂️ - -We have only covered a tiny fraction of the capabilities of the AlgoKit CLI and its related ecosystem of templates and utilities for an efficient developer experience. - -- To get the most out of `AlgoKit`, we recommend to get started with learning more about AlgoKit and what you can do with it by checking out our extensive [AlgoKit CLI documentation](../algokit.md). -- Explore the `README.md` files at the root of any project created via `algokit init`. All official AlgoKit templates include detailed quick started guides, an interactive code tour and various presets which can be customized to your needs. -- To learn more about `Algorand Python`, take a look at the [documentation](https://algorandfoundation.github.io/puya/). -- To learn more about the commands demonstrated in this tutorial, refer to [`init`](../features/init.md) and [`project`](../features/project.md) to get a comprehensive understanding of their further capabilities. -- If you'd like to learn more on structuring your `AlgoKit Project` as a monorepo, refer to `workspace` mode as described in [`init`](../features/init.md#workspaces-vs-standalone-projects). You can also pass the `--no-workspace` flag to setup a standalone algokit project, if preferred. -- If you'd like to **create your own** `AlgoKit` template, refer to the [template tutorial](./algokit-template.md). -- More information on Algorand smart contracts is also available in the [smart contract documentation](https://dev.algorand.co/concepts/smart-contracts/overview). From 6ccb3946e6ea8b7d1d8974e57199ea43e402b868 Mon Sep 17 00:00:00 2001 From: Luca Martini Date: Fri, 5 Jun 2026 11:14:28 +0200 Subject: [PATCH 16/19] docs: refresh cli reference content and fix broken links --- docs/astro.config.mjs | 2 + docs/package.json | 2 + docs/pnpm-lock.yaml | 828 ++++++++++++++++++ docs/src/content/docs/features/compile.md | 6 +- docs/src/content/docs/features/completions.md | 26 +- docs/src/content/docs/features/config.md | 9 +- docs/src/content/docs/features/dispenser.md | 4 +- docs/src/content/docs/features/doctor.md | 2 +- docs/src/content/docs/features/explore.md | 6 +- docs/src/content/docs/features/generate.md | 8 +- docs/src/content/docs/features/goal.md | 17 +- docs/src/content/docs/features/init.md | 16 +- docs/src/content/docs/features/localnet.md | 28 +- docs/src/content/docs/features/overview.md | 5 +- .../docs/features/project/bootstrap.md | 64 +- .../content/docs/features/project/deploy.md | 34 +- .../src/content/docs/features/project/link.md | 16 +- .../src/content/docs/features/project/list.md | 22 +- docs/src/content/docs/features/project/run.md | 16 +- .../content/docs/features/tasks/analyze.md | 6 +- docs/src/content/docs/features/tasks/ipfs.md | 21 +- docs/src/content/docs/features/tasks/mint.md | 16 +- docs/src/content/docs/features/tasks/nfd.md | 2 +- docs/src/content/docs/features/tasks/opt.md | 4 +- docs/src/content/docs/features/tasks/send.md | 2 +- docs/src/content/docs/features/tasks/sign.md | 6 +- .../content/docs/features/tasks/transfer.md | 8 +- .../docs/features/tasks/vanity_address.md | 8 +- .../src/content/docs/features/tasks/wallet.md | 10 +- .../docs/tutorials/algokit-template.md | 22 +- docs/src/content/docs/tutorials/intro.md | 4 +- src/algokit/cli/goal.py | 2 +- src/algokit/cli/tasks/mint.py | 6 +- src/algokit/cli/tasks/vanity_address.py | 2 +- src/algokit/core/project/bootstrap.py | 2 +- 35 files changed, 1051 insertions(+), 181 deletions(-) diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 6933f0bc2..888dc1bce 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -1,6 +1,7 @@ // @ts-check import starlight from "@astrojs/starlight"; import { defineConfig } from "astro/config"; +import mermaid from "astro-mermaid"; import remarkGithubAlerts from "remark-github-alerts"; import sidebar from "./sidebar.config.json"; @@ -12,6 +13,7 @@ export default defineConfig({ remarkPlugins: [remarkGithubAlerts], }, integrations: [ + mermaid({ theme: "default", autoTheme: true }), starlight({ title: "AlgoKit CLI", tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 4 }, diff --git a/docs/package.json b/docs/package.json index 7ba49bead..bd7517a8a 100644 --- a/docs/package.json +++ b/docs/package.json @@ -16,6 +16,8 @@ "dependencies": { "@astrojs/starlight": "^0.37.6", "astro": "^5.6.1", + "astro-mermaid": "^2.0.2", + "mermaid": "^11.15.0", "remark-github-alerts": "^0.1.1", "sharp": "^0.34.2" } diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml index 4baff2b3b..2326c784a 100644 --- a/docs/pnpm-lock.yaml +++ b/docs/pnpm-lock.yaml @@ -14,6 +14,12 @@ importers: astro: specifier: ^5.6.1 version: 5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3) + astro-mermaid: + specifier: ^2.0.2 + version: 2.0.2(astro@5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3))(mermaid@11.15.0) + mermaid: + specifier: ^11.15.0 + version: 11.15.0 remark-github-alerts: specifier: ^0.1.1 version: 0.1.1(@types/mdast@4.0.4)(unified@11.0.5) @@ -23,6 +29,9 @@ importers: packages: + '@antfu/install-pkg@1.1.0': + resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} + '@astrojs/compiler@2.13.1': resolution: {integrity: sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==} @@ -75,10 +84,16 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@braintree/sanitize-url@7.1.2': + resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==} + '@capsizecss/unpack@4.0.0': resolution: {integrity: sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==} engines: {node: '>=18'} + '@chevrotain/types@11.1.2': + resolution: {integrity: sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==} + '@ctrl/tinycolor@4.2.0': resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} engines: {node: '>=14'} @@ -410,6 +425,12 @@ packages: '@expressive-code/plugin-text-markers@0.41.7': resolution: {integrity: sha512-Ewpwuc5t6eFdZmWlFyeuy3e1PTQC0jFvw2Q+2bpcWXbOZhPLsT7+h8lsSIJxb5mS7wZko7cKyQ2RLYDyK6Fpmw==} + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@3.1.3': + resolution: {integrity: sha512-LPKOXPn/zV+zis1oOfGWogaXVpqUybF3ZS6SCZIsz8vg0ivVp9+fVqyYB7xq0aiST/VhUQYGO1qo6uoYSiEJqw==} + '@img/colour@1.1.0': resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} engines: {node: '>=18'} @@ -569,6 +590,9 @@ packages: '@mdx-js/mdx@3.1.1': resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==} + '@mermaid-js/parser@1.1.1': + resolution: {integrity: sha512-VuHdsYMK1bT6X2JbcAaWAhugTRvRBRyuZgd+c22swUeI9g/ntaxF7CY7dYarhZovofCbUNO0G7JesfmNtjYOCw==} + '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} @@ -773,6 +797,99 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + '@types/d3-array@3.2.2': + resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} + + '@types/d3-axis@3.0.6': + resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} + + '@types/d3-brush@3.0.6': + resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} + + '@types/d3-chord@3.0.6': + resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} + + '@types/d3-color@3.1.3': + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + + '@types/d3-contour@3.0.6': + resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} + + '@types/d3-delaunay@6.0.4': + resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} + + '@types/d3-dispatch@3.0.7': + resolution: {integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==} + + '@types/d3-drag@3.0.7': + resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} + + '@types/d3-dsv@3.0.7': + resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} + + '@types/d3-ease@3.0.2': + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} + + '@types/d3-fetch@3.0.7': + resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} + + '@types/d3-force@3.0.10': + resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} + + '@types/d3-format@3.0.4': + resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} + + '@types/d3-geo@3.1.0': + resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} + + '@types/d3-hierarchy@3.1.7': + resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} + + '@types/d3-interpolate@3.0.4': + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + + '@types/d3-path@3.1.1': + resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==} + + '@types/d3-polygon@3.0.2': + resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} + + '@types/d3-quadtree@3.0.6': + resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} + + '@types/d3-random@3.0.3': + resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==} + + '@types/d3-scale-chromatic@3.1.0': + resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} + + '@types/d3-scale@4.0.9': + resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} + + '@types/d3-selection@3.0.11': + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} + + '@types/d3-shape@3.1.8': + resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} + + '@types/d3-time-format@4.0.3': + resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} + + '@types/d3-time@3.0.4': + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} + + '@types/d3-timer@3.0.2': + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + + '@types/d3-transition@3.0.9': + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} + + '@types/d3-zoom@3.0.8': + resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} + + '@types/d3@7.4.3': + resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} + '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -782,6 +899,9 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/geojson@7946.0.16': + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} @@ -806,6 +926,9 @@ packages: '@types/sax@1.2.7': resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -815,6 +938,9 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@upsetjs/venn.js@2.0.0': + resolution: {integrity: sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -866,6 +992,16 @@ packages: peerDependencies: astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta + astro-mermaid@2.0.2: + resolution: {integrity: sha512-ihx63qwZ0hlu9mDjs6auQEXyo13s9h5HFHFIHovjTJH6ot97u0VqyGk3P1kkjPYZeOMrZ1Y7QAOevUfLs9cDfA==} + peerDependencies: + '@mermaid-js/layout-elk': ^0.2.0 + astro: '>=4' + mermaid: ^10.0.0 || ^11.0.0 + peerDependenciesMeta: + '@mermaid-js/layout-elk': + optional: true + astro@5.18.1: resolution: {integrity: sha512-m4VWilWZ+Xt6NPoYzC4CgGZim/zQUO7WFL0RHCH0AiEavF1153iC3+me2atDvXpf/yX4PyGUeD8wZLq1cirT3g==} engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} @@ -943,6 +1079,14 @@ packages: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + common-ancestor-path@1.0.1: resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} @@ -953,6 +1097,12 @@ packages: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} + cose-base@1.0.3: + resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + + cose-base@2.2.0: + resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} + crossws@0.3.5: resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} @@ -983,6 +1133,165 @@ packages: resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + cytoscape-cose-bilkent@4.1.0: + resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape-fcose@2.2.0: + resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape@3.34.0: + resolution: {integrity: sha512-62rNSrioXw93uliKFBwjukeQyeWwH2PqDrTac31r2P6464u3AUvTk0xS4LVvT251g7IgkFunrI48ZEZGjywSOg==} + engines: {node: '>=0.10'} + + d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + + d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + + d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + + d3-delaunay@6.0.4: + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + + d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + hasBin: true + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + + d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + + d3-format@3.1.2: + resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==} + engines: {node: '>=12'} + + d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} + engines: {node: '>=12'} + + d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-path@1.0.9: + resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} + + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + + d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + + d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + + d3-sankey@0.12.3: + resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==} + + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + + d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + + d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + + d3-shape@1.3.7: + resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + + d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + + d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-transition@3.0.1: + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + + d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + + d3@7.9.0: + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} + + dagre-d3-es@7.0.14: + resolution: {integrity: sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==} + + dayjs@1.11.21: + resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -998,6 +1307,9 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + delaunator@5.1.0: + resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -1040,6 +1352,9 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} + dompurify@3.4.8: + resolution: {integrity: sha512-yb1cEmaOum7wFvOCSQxyfgVlv5D47Rc30iZWoMpbDIWTnJ6grDDQyu2KFJzB2k7u0pMuJcQ1zphH//fFnw2tjQ==} + domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} @@ -1064,6 +1379,9 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-toolkit@1.47.0: + resolution: {integrity: sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw==} + esast-util-from-estree@2.0.0: resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} @@ -1152,6 +1470,9 @@ packages: h3@1.15.6: resolution: {integrity: sha512-oi15ESLW5LRthZ+qPCi5GNasY/gvynSKUQxgiovrY63bPAtG59wtM+LSrlcwvOHAXzGrXVLnI97brbkdPF9WoQ==} + hachure-fill@0.5.2: + resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} + hast-util-embedded@3.0.0: resolution: {integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==} @@ -1227,12 +1548,23 @@ packages: i18next@23.16.8: resolution: {integrity: sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==} + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + import-meta-resolve@4.2.0: resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} inline-style-parser@0.2.7: resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} + internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + iron-webcrypto@1.2.1: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} @@ -1274,6 +1606,13 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true + katex@0.16.47: + resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==} + hasBin: true + + khroma@2.1.0: + resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} + kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} @@ -1282,6 +1621,15 @@ packages: resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} engines: {node: '>= 8'} + layout-base@1.0.2: + resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} + + layout-base@2.0.1: + resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} + + lodash-es@4.18.1: + resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} + longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -1302,6 +1650,11 @@ packages: markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + marked@16.4.2: + resolution: {integrity: sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==} + engines: {node: '>= 20'} + hasBin: true + mdast-util-definitions@6.0.0: resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} @@ -1362,6 +1715,9 @@ packages: mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + mermaid@11.15.0: + resolution: {integrity: sha512-pTMbcf3rWdtLiYGpmoTjHEpeY8seiy6sR+9nD7LOs8KfUbHE4lOUAprTRqRAcWSQ6MQpdX+YEsxShtGsINtPtw==} + micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} @@ -1542,6 +1898,9 @@ packages: parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + path-data-parser@0.1.0: + resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} + piccolore@0.1.3: resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==} @@ -1556,6 +1915,12 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + points-on-curve@0.2.0: + resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==} + + points-on-path@0.2.1: + resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} + postcss-nested@6.2.0: resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} engines: {node: '>=12.0'} @@ -1672,11 +2037,23 @@ packages: retext@9.0.0: resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} + robust-predicates@3.0.3: + resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} + rollup@4.59.0: resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + roughjs@4.6.6: + resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} + + rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sax@1.5.0: resolution: {integrity: sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==} engines: {node: '>=11.0.0'} @@ -1744,6 +2121,9 @@ packages: style-to-object@1.0.14: resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} + stylis@4.4.0: + resolution: {integrity: sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==} + svgo@4.0.1: resolution: {integrity: sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==} engines: {node: '>=16'} @@ -1766,6 +2146,10 @@ packages: trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + ts-dedent@2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + tsconfck@3.1.6: resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} engines: {node: ^18 || >=20} @@ -1901,6 +2285,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@14.0.0: + resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} + hasBin: true + vfile-location@5.0.3: resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} @@ -2014,6 +2402,11 @@ packages: snapshots: + '@antfu/install-pkg@1.1.0': + dependencies: + package-manager-detector: 1.6.0 + tinyexec: 1.0.2 + '@astrojs/compiler@2.13.1': {} '@astrojs/internal-helpers@0.7.6': {} @@ -2134,10 +2527,14 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@braintree/sanitize-url@7.1.2': {} + '@capsizecss/unpack@4.0.0': dependencies: fontkitten: 1.0.3 + '@chevrotain/types@11.1.2': {} + '@ctrl/tinycolor@4.2.0': {} '@emnapi/runtime@1.8.1': @@ -2326,6 +2723,14 @@ snapshots: dependencies: '@expressive-code/core': 0.41.7 + '@iconify/types@2.0.0': {} + + '@iconify/utils@3.1.3': + dependencies: + '@antfu/install-pkg': 1.1.0 + '@iconify/types': 2.0.0 + import-meta-resolve: 4.2.0 + '@img/colour@1.1.0': {} '@img/sharp-darwin-arm64@0.34.5': @@ -2454,6 +2859,10 @@ snapshots: transitivePeerDependencies: - supports-color + '@mermaid-js/parser@1.1.1': + dependencies: + '@chevrotain/types': 11.1.2 + '@oslojs/encoding@1.1.0': {} '@pagefind/darwin-arm64@1.4.0': @@ -2592,6 +3001,123 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} + '@types/d3-array@3.2.2': {} + + '@types/d3-axis@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-brush@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-chord@3.0.6': {} + + '@types/d3-color@3.1.3': {} + + '@types/d3-contour@3.0.6': + dependencies: + '@types/d3-array': 3.2.2 + '@types/geojson': 7946.0.16 + + '@types/d3-delaunay@6.0.4': {} + + '@types/d3-dispatch@3.0.7': {} + + '@types/d3-drag@3.0.7': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-dsv@3.0.7': {} + + '@types/d3-ease@3.0.2': {} + + '@types/d3-fetch@3.0.7': + dependencies: + '@types/d3-dsv': 3.0.7 + + '@types/d3-force@3.0.10': {} + + '@types/d3-format@3.0.4': {} + + '@types/d3-geo@3.1.0': + dependencies: + '@types/geojson': 7946.0.16 + + '@types/d3-hierarchy@3.1.7': {} + + '@types/d3-interpolate@3.0.4': + dependencies: + '@types/d3-color': 3.1.3 + + '@types/d3-path@3.1.1': {} + + '@types/d3-polygon@3.0.2': {} + + '@types/d3-quadtree@3.0.6': {} + + '@types/d3-random@3.0.3': {} + + '@types/d3-scale-chromatic@3.1.0': {} + + '@types/d3-scale@4.0.9': + dependencies: + '@types/d3-time': 3.0.4 + + '@types/d3-selection@3.0.11': {} + + '@types/d3-shape@3.1.8': + dependencies: + '@types/d3-path': 3.1.1 + + '@types/d3-time-format@4.0.3': {} + + '@types/d3-time@3.0.4': {} + + '@types/d3-timer@3.0.2': {} + + '@types/d3-transition@3.0.9': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-zoom@3.0.8': + dependencies: + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + + '@types/d3@7.4.3': + dependencies: + '@types/d3-array': 3.2.2 + '@types/d3-axis': 3.0.6 + '@types/d3-brush': 3.0.6 + '@types/d3-chord': 3.0.6 + '@types/d3-color': 3.1.3 + '@types/d3-contour': 3.0.6 + '@types/d3-delaunay': 6.0.4 + '@types/d3-dispatch': 3.0.7 + '@types/d3-drag': 3.0.7 + '@types/d3-dsv': 3.0.7 + '@types/d3-ease': 3.0.2 + '@types/d3-fetch': 3.0.7 + '@types/d3-force': 3.0.10 + '@types/d3-format': 3.0.4 + '@types/d3-geo': 3.1.0 + '@types/d3-hierarchy': 3.1.7 + '@types/d3-interpolate': 3.0.4 + '@types/d3-path': 3.1.1 + '@types/d3-polygon': 3.0.2 + '@types/d3-quadtree': 3.0.6 + '@types/d3-random': 3.0.3 + '@types/d3-scale': 4.0.9 + '@types/d3-scale-chromatic': 3.1.0 + '@types/d3-selection': 3.0.11 + '@types/d3-shape': 3.1.8 + '@types/d3-time': 3.0.4 + '@types/d3-time-format': 4.0.3 + '@types/d3-timer': 3.0.2 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + '@types/debug@4.1.12': dependencies: '@types/ms': 2.1.0 @@ -2602,6 +3128,8 @@ snapshots: '@types/estree@1.0.8': {} + '@types/geojson@7946.0.16': {} + '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.3 @@ -2628,12 +3156,20 @@ snapshots: dependencies: '@types/node': 24.12.0 + '@types/trusted-types@2.0.7': + optional: true + '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} '@ungap/structured-clone@1.3.0': {} + '@upsetjs/venn.js@2.0.0': + optionalDependencies: + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + acorn-jsx@5.3.2(acorn@8.16.0): dependencies: acorn: 8.16.0 @@ -2670,6 +3206,14 @@ snapshots: astro: 5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3) rehype-expressive-code: 0.41.7 + astro-mermaid@2.0.2(astro@5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3))(mermaid@11.15.0): + dependencies: + astro: 5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3) + import-meta-resolve: 4.2.0 + mdast-util-to-string: 4.0.0 + mermaid: 11.15.0 + unist-util-visit: 5.1.0 + astro@5.18.1(@types/node@24.12.0)(rollup@4.59.0)(typescript@5.9.3): dependencies: '@astrojs/compiler': 2.13.1 @@ -2829,12 +3373,24 @@ snapshots: commander@11.1.0: {} + commander@7.2.0: {} + + commander@8.3.0: {} + common-ancestor-path@1.0.1: {} cookie-es@1.2.2: {} cookie@1.1.1: {} + cose-base@1.0.3: + dependencies: + layout-base: 1.0.2 + + cose-base@2.2.0: + dependencies: + layout-base: 2.0.1 + crossws@0.3.5: dependencies: uncrypto: 0.1.3 @@ -2867,6 +3423,192 @@ snapshots: dependencies: css-tree: 2.2.1 + cytoscape-cose-bilkent@4.1.0(cytoscape@3.34.0): + dependencies: + cose-base: 1.0.3 + cytoscape: 3.34.0 + + cytoscape-fcose@2.2.0(cytoscape@3.34.0): + dependencies: + cose-base: 2.2.0 + cytoscape: 3.34.0 + + cytoscape@3.34.0: {} + + d3-array@2.12.1: + dependencies: + internmap: 1.0.1 + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-axis@3.0.0: {} + + d3-brush@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3-chord@3.0.1: + dependencies: + d3-path: 3.1.0 + + d3-color@3.1.0: {} + + d3-contour@4.0.2: + dependencies: + d3-array: 3.2.4 + + d3-delaunay@6.0.4: + dependencies: + delaunator: 5.1.0 + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-dsv@3.0.1: + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + + d3-ease@3.0.1: {} + + d3-fetch@3.0.1: + dependencies: + d3-dsv: 3.0.1 + + d3-force@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + + d3-format@3.1.2: {} + + d3-geo@3.1.1: + dependencies: + d3-array: 3.2.4 + + d3-hierarchy@3.1.2: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-path@1.0.9: {} + + d3-path@3.1.0: {} + + d3-polygon@3.0.1: {} + + d3-quadtree@3.0.1: {} + + d3-random@3.0.1: {} + + d3-sankey@0.12.3: + dependencies: + d3-array: 2.12.1 + d3-shape: 1.3.7 + + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.2 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-selection@3.0.0: {} + + d3-shape@1.3.7: + dependencies: + d3-path: 1.0.9 + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + d3-timer@3.0.1: {} + + d3-transition@3.0.1(d3-selection@3.0.0): + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3@7.9.0: + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.2 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + + dagre-d3-es@7.0.14: + dependencies: + d3: 7.9.0 + lodash-es: 4.18.1 + + dayjs@1.11.21: {} + debug@4.4.3: dependencies: ms: 2.1.3 @@ -2877,6 +3619,10 @@ snapshots: defu@6.1.4: {} + delaunator@5.1.0: + dependencies: + robust-predicates: 3.0.3 + dequal@2.0.3: {} destr@2.0.5: {} @@ -2911,6 +3657,10 @@ snapshots: dependencies: domelementtype: 2.3.0 + dompurify@3.4.8: + optionalDependencies: + '@types/trusted-types': 2.0.7 + domutils@3.2.2: dependencies: dom-serializer: 2.0.0 @@ -2929,6 +3679,8 @@ snapshots: es-module-lexer@1.7.0: {} + es-toolkit@1.47.0: {} + esast-util-from-estree@2.0.0: dependencies: '@types/estree-jsx': 1.0.5 @@ -3082,6 +3834,8 @@ snapshots: ufo: 1.6.3 uncrypto: 0.1.3 + hachure-fill@0.5.2: {} + hast-util-embedded@3.0.0: dependencies: '@types/hast': 3.0.4 @@ -3283,10 +4037,18 @@ snapshots: dependencies: '@babel/runtime': 7.28.6 + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + import-meta-resolve@4.2.0: {} inline-style-parser@0.2.7: {} + internmap@1.0.1: {} + + internmap@2.0.3: {} + iron-webcrypto@1.2.1: {} is-alphabetical@2.0.1: {} @@ -3318,10 +4080,22 @@ snapshots: dependencies: argparse: 2.0.1 + katex@0.16.47: + dependencies: + commander: 8.3.0 + + khroma@2.1.0: {} + kleur@3.0.3: {} klona@2.0.6: {} + layout-base@1.0.2: {} + + layout-base@2.0.1: {} + + lodash-es@4.18.1: {} + longest-streak@3.1.0: {} lru-cache@11.2.6: {} @@ -3340,6 +4114,8 @@ snapshots: markdown-table@3.0.4: {} + marked@16.4.2: {} + mdast-util-definitions@6.0.0: dependencies: '@types/mdast': 4.0.4 @@ -3527,6 +4303,30 @@ snapshots: mdn-data@2.27.1: {} + mermaid@11.15.0: + dependencies: + '@braintree/sanitize-url': 7.1.2 + '@iconify/utils': 3.1.3 + '@mermaid-js/parser': 1.1.1 + '@types/d3': 7.4.3 + '@upsetjs/venn.js': 2.0.0 + cytoscape: 3.34.0 + cytoscape-cose-bilkent: 4.1.0(cytoscape@3.34.0) + cytoscape-fcose: 2.2.0(cytoscape@3.34.0) + d3: 7.9.0 + d3-sankey: 0.12.3 + dagre-d3-es: 7.0.14 + dayjs: 1.11.21 + dompurify: 3.4.8 + es-toolkit: 1.47.0 + katex: 0.16.47 + khroma: 2.1.0 + marked: 16.4.2 + roughjs: 4.6.6 + stylis: 4.4.0 + ts-dedent: 2.2.0 + uuid: 14.0.0 + micromark-core-commonmark@2.0.3: dependencies: decode-named-character-reference: 1.3.0 @@ -3884,6 +4684,8 @@ snapshots: dependencies: entities: 6.0.1 + path-data-parser@0.1.0: {} + piccolore@0.1.3: {} picocolors@1.1.1: {} @@ -3892,6 +4694,13 @@ snapshots: picomatch@4.0.3: {} + points-on-curve@0.2.0: {} + + points-on-path@0.2.1: + dependencies: + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + postcss-nested@6.2.0(postcss@8.5.8): dependencies: postcss: 8.5.8 @@ -4090,6 +4899,8 @@ snapshots: retext-stringify: 4.0.0 unified: 11.0.5 + robust-predicates@3.0.3: {} + rollup@4.59.0: dependencies: '@types/estree': 1.0.8 @@ -4121,6 +4932,17 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.59.0 fsevents: 2.3.3 + roughjs@4.6.6: + dependencies: + hachure-fill: 0.5.2 + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + points-on-path: 0.2.1 + + rw@1.3.3: {} + + safer-buffer@2.1.2: {} + sax@1.5.0: {} semver@7.7.4: {} @@ -4219,6 +5041,8 @@ snapshots: dependencies: inline-style-parser: 0.2.7 + stylis@4.4.0: {} + svgo@4.0.1: dependencies: commander: 11.1.0 @@ -4242,6 +5066,8 @@ snapshots: trough@2.2.0: {} + ts-dedent@2.2.0: {} + tsconfck@3.1.6(typescript@5.9.3): optionalDependencies: typescript: 5.9.3 @@ -4336,6 +5162,8 @@ snapshots: util-deprecate@1.0.2: {} + uuid@14.0.0: {} + vfile-location@5.0.3: dependencies: '@types/unist': 3.0.3 diff --git a/docs/src/content/docs/features/compile.md b/docs/src/content/docs/features/compile.md index d3095a922..8e67baa1e 100644 --- a/docs/src/content/docs/features/compile.md +++ b/docs/src/content/docs/features/compile.md @@ -14,7 +14,7 @@ See [Compile Python - Prerequisites](#prerequisites-1) and [Compile TypeScript - Algorand Python is a semantically and syntactically compatible, typed Python language that works with standard Python tooling and allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM). -Algorand Python can be deployed to Algorand by using the PuyaPy optimising compiler, which takes Algorand Python and outputs [ARC-32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) application spec files (among other formats) which, [when deployed](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients), will result in AVM bytecode execution semantics that match the given Python code. +Algorand Python can be deployed to Algorand by using the PuyaPy optimising compiler, which takes Algorand Python and outputs [ARC-32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) application spec files (among other formats) which, [when deployed](/algokit-cli/features/generate/#1-typed-clients), will result in AVM bytecode execution semantics that match the given Python code. If you want to learn more, check out the [PuyaPy docs](https://github.com/algorandfoundation/puya/blob/main/docs/index.md). @@ -35,12 +35,12 @@ For more complex examples, see the [examples](https://github.com/algorandfoundat Algorand TypeScript is a typed TypeScript language that allows you to express smart contracts (apps) and smart signatures (logic signatures) for deployment on the Algorand Virtual Machine (AVM). Algorand TypeScript is currently in beta. -Algorand TypeScript can be deployed to Algorand by using the PuyaTs optimising compiler, which takes Algorand TypeScript and outputs [ARC-32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) application spec files (among other formats) which, [when deployed](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients), will result in AVM bytecode execution semantics that match the given TypeScript code. +Algorand TypeScript can be deployed to Algorand by using the PuyaTs optimising compiler, which takes Algorand TypeScript and outputs [ARC-32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) application spec files (among other formats) which, [when deployed](/algokit-cli/features/generate/#1-typed-clients), will result in AVM bytecode execution semantics that match the given TypeScript code. Below is an example Algorand TypeScript smart contract. ```typescript -import { Contract } from "@algorandfoundation/puya-sdk"; +import { Contract } from "@algorandfoundation/algorand-typescript"; class HelloWorldContract extends Contract { hello(name: string): string { diff --git a/docs/src/content/docs/features/completions.md b/docs/src/content/docs/features/completions.md index 22d42e044..062a8d1cb 100644 --- a/docs/src/content/docs/features/completions.md +++ b/docs/src/content/docs/features/completions.md @@ -8,21 +8,25 @@ AlgoKit supports shell completions for zsh and bash shells, e.g. ```bash algokit -bootstrap completions config doctor explore goal init sandbox +compile completions config dispenser doctor explore generate goal init localnet project task ``` **zsh** -```bash +```zsh algokit -bootstrap -- Bootstrap AlgoKit project dependencies. -completions -- Install and Uninstall AlgoKit shell integration. -config -- Configure AlgoKit options. -doctor -- Run the Algorand doctor CLI. -explore -- Explore the specified network in the... -goal -- Run the Algorand goal CLI against the AlgoKit Sandbox. -init -- Initializes a new project. -sandbox -- Manage the AlgoKit sandbox. +compile -- Compile smart contracts and smart signatures... +completions -- Install and Uninstall AlgoKit shell integrations. +config -- Configure AlgoKit settings. +dispenser -- Interact with the AlgoKit TestNet Dispenser. +doctor -- Diagnose potential environment issues that may affect AlgoKit. +explore -- Explore the specified network using lora. +generate -- Generate code for an Algorand project. +goal -- Run the Algorand goal CLI against the AlgoKit LocalNet. +init -- Initializes a new project from a template;... +localnet -- Manage the AlgoKit LocalNet. +project -- Provides a suite of commands for managing your... +task -- Collection of useful tasks to help you... ``` ## Installing @@ -53,6 +57,6 @@ AlgoKit completions uninstalled for zsh 🎉 ## Shell Option -To install/uninstall the completions for a specific [shell](/algokit-cli/cli/#--shell-) the `--shell` option can be used e.g. `algokit completions install --shell bash`. +To install/uninstall the completions for a specific [shell](/algokit-cli/cli/#shell) the `--shell` option can be used e.g. `algokit completions install --shell bash`. To learn more about the `algokit completions` command, please refer to [completions](/algokit-cli/cli/#completions) in the AlgoKit CLI reference documentation. diff --git a/docs/src/content/docs/features/config.md b/docs/src/content/docs/features/config.md index 2318597cc..67d242fbb 100644 --- a/docs/src/content/docs/features/config.md +++ b/docs/src/content/docs/features/config.md @@ -17,13 +17,12 @@ Subcommands ### Version Prompt Configuration ```bash -algokit config version-prompt [OPTIONS] +algokit config version-prompt [OPTIONS] [ENABLE] ``` This command configures the version prompt settings for AlgoKit. -- `--enable`: Enable the version prompt. -- `--disable`: Disable the version prompt. +- `ENABLE`: Optional positional argument; one of `enable` or `disable`. If omitted, the command prints the current setting (`enable` or `disable`) instead of changing it. ### Container Engine Configuration @@ -31,10 +30,10 @@ This command configures the version prompt settings for AlgoKit. algokit config container-engine [OPTIONS] [ENGINE] ``` -This command configures the container engine settings for AlgoKit. +This command sets the default container engine used by AlgoKit CLI to run LocalNet images. - `--force`, `-f`: Skip confirmation prompts. Defaults to 'yes' to all prompts. -- `ENGINE`: Optional argument to specify the container engine (docker or podman). +- `ENGINE`: Optional argument to specify the container engine (docker or podman). If omitted, AlgoKit will prompt you to select one interactively. ### JavaScript Package Manager Configuration diff --git a/docs/src/content/docs/features/dispenser.md b/docs/src/content/docs/features/dispenser.md index 7da469a8e..73e1e226c 100644 --- a/docs/src/content/docs/features/dispenser.md +++ b/docs/src/content/docs/features/dispenser.md @@ -38,7 +38,7 @@ Options - `--ci`: Generate an access token for CI. Issued for 30 days. - `--output`, -o: Output mode where you want to store the generated access token. Defaults to stdout. Only applicable when --ci flag is set. -- `--file`, -f: Output filename where you want to store the generated access token. Defaults to `ci_token.txt`. Only applicable when --ci flag is set and --output mode is `file`. +- `--file`, -f: Output filename where you want to store the generated access token. Defaults to `algokit_ci_token.txt`. Only applicable when --ci flag is set and --output mode is `file`. > Please note, algokit relies on [keyring](https://pypi.org/project/keyring/) for storing your API credentials. This implies that your credentials are stored in your system's keychain. By default it will prompt for entering your system password unless you have set it up to always allow access for `algokit-cli` to obtain API credentials. @@ -74,7 +74,7 @@ Options - `--txID`, -t: Transaction ID of your refund operation. This option is required. The receiver address of the transaction must be the same as the dispenser wallet address that you can obtain by observing a `sender` field of [`fund`](#fund) transaction. -> Please note, performing a refund operation will not immediately change your daily fund limit. Your daily fund limit is reset daily at midnigth UTC. If you have reached your daily fund limit, you will not be able to perform a refund operation until your daily fund limit is reset. +> Please note, performing a refund operation will not immediately change your daily fund limit. Your daily fund limit is reset daily at midnight UTC. If you have reached your daily fund limit, you will not be able to perform a refund operation until your daily fund limit is reset. ## Limit diff --git a/docs/src/content/docs/features/doctor.md b/docs/src/content/docs/features/doctor.md index fb3033199..e5ba9929c 100644 --- a/docs/src/content/docs/features/doctor.md +++ b/docs/src/content/docs/features/doctor.md @@ -6,7 +6,7 @@ The AlgoKit Doctor feature allows you to check your AlgoKit installation along w ## Functionality -The AlgoKit Doctor allows you to make sure that your system has the correct dependencies installed and that they satisfy the minimum required versions. All passed checks will appear in your command line natural color while warnings will be in yellow (warning) and errors or missing critical services will be in red (error). The critical services that AlgoKit will check for (since they are [directly used by certain commands](../../README.md#prerequisites)): Docker, docker compose and git. +The AlgoKit Doctor allows you to make sure that your system has the correct dependencies installed and that they satisfy the minimum required versions. All passed checks will appear in your command line natural color while warnings will be in yellow (warning) and errors or missing critical services will be in red (error). The critical services that AlgoKit will check for (since they are directly used by certain commands): Docker, docker compose and git. Please run this command to if you are facing an issue running AlgoKit. It is recommended to run it before [submitting an issue to AlgoKit](https://github.com/algorandfoundation/algokit-cli/issues/new). You can copy the contents of the Doctor command message (in Markdown format) to your clipboard by providing the `-c` flag to the command as follows `algokit doctor -c`. diff --git a/docs/src/content/docs/features/explore.md b/docs/src/content/docs/features/explore.md index 0550fb372..1733aaa0c 100644 --- a/docs/src/content/docs/features/explore.md +++ b/docs/src/content/docs/features/explore.md @@ -2,7 +2,7 @@ title: "AlgoKit Explore" --- -AlgoKit provides a quick shortcut to [explore](/algokit-cli/cli/#explore) various Algorand networks using [lora](https://lora.algokit.io/) including [AlgoKit LocalNet](/algokit-cli/features/localnet/)! +AlgoKit provides a quick shortcut to [explore](/algokit-cli/cli/#explore) various Algorand networks using [lora](https://explore.algokit.io/) including [AlgoKit LocalNet](/algokit-cli/features/localnet/)! ## LocalNet @@ -14,10 +14,10 @@ The following three commands are all equivalent and will open lora pointing to t ## Testnet -`algokit explore testnet` will open lora pointing to TestNet via the [node](https://algonode.io/api/). +`algokit explore testnet` will open lora pointing to TestNet via the [node](https://nodely.io/). ## Mainnet -`algokit explore mainnet` will open lora pointing to MainNet via the [node](https://algonode.io/api/). +`algokit explore mainnet` will open lora pointing to MainNet via the [node](https://nodely.io/). To learn more about the `algokit explore` command, please refer to [explore](/algokit-cli/cli/#explore) in the AlgoKit CLI reference documentation. diff --git a/docs/src/content/docs/features/generate.md b/docs/src/content/docs/features/generate.md index 2668a25d1..c2025f01e 100644 --- a/docs/src/content/docs/features/generate.md +++ b/docs/src/content/docs/features/generate.md @@ -24,7 +24,7 @@ You can either specify a path to an ARC-0032 JSON file, an ARC-0056 JSON file or The output path is interpreted as relative to the current working directory, however an absolute path may also be specified e.g. `algokit generate client application.json --output /absolute/path/to/client.py` -There are two tokens available for use with the `-o`, `--output` [option](/algokit-cli/cli/#-o---output-output_path_pattern): +There are two tokens available for use with the `-o`, `--output` [option](/algokit-cli/cli/#-o-output-output_path_pattern): - `{contract_name}`: This will resolve to a name based on the ARC-0032/ARC-0056 contract name, formatted appropriately for the target language. - `{app_spec_dir}`: This will resolve to the parent directory of the `application.json`, `*.arc32.json`, `*.arc56.json` file which can be useful to output a client relative to its source file. @@ -78,7 +78,7 @@ const appClient = new HelloWorldAppClient( sender: deployer, creatorAddress: deployer.addr, }, - algod + algod, ); const app = await appClient.deploy({ allowDelete: isLocal, @@ -98,7 +98,7 @@ To process multiple application.json in a directory structure and output to a ty `algokit generate client smart_contracts/artifacts --output {contract_name}.ts` To process multiple application.json in a directory structure and output to a python client alongside each application.json: -`algokit generate client smart_contracts/artifacts --output {app_spec_path}/client.py` +`algokit generate client smart_contracts/artifacts --output {app_spec_dir}/client.py` ## 2. Using Custom Generate Commands @@ -162,7 +162,7 @@ Options: -h, --help Show this message and exit. Commands: - client Create a typed ApplicationClient from an ARC-32 application.json + client Create a typed ApplicationClient from an ARC-32/56 application.json smart-contract Adds a new smart contract to the existing project ``` diff --git a/docs/src/content/docs/features/goal.md b/docs/src/content/docs/features/goal.md index 2139d4a9b..f82ba2909 100644 --- a/docs/src/content/docs/features/goal.md +++ b/docs/src/content/docs/features/goal.md @@ -2,7 +2,7 @@ title: "AlgoKit Goal" --- -AlgoKit goal command provides the user with a mechanism to run [goal cli](https://dev.algorand.co/algokit/algokit-cli/goal/) commands against the current [AlgoKit LocalNet](/algokit-cli/features/localnet/). +AlgoKit goal command provides the user with a mechanism to run [goal cli](https://developer.algorand.org/docs/clis/goal/goal/) commands against the current [AlgoKit LocalNet](/algokit-cli/features/localnet/). You can explore all possible goal commands by running `algokit goal` e.g.: @@ -66,18 +66,11 @@ algokit goal report Genesis hash: vEg1NCh6SSXwS6O5HAfjYCCNAs4ug328s3RYMr9syBg= ``` -If the AlgoKit Sandbox `algod` docker container is not present or not running, the command will fail with a clear error, e.g.: +If the AlgoKit LocalNet `algod` docker container is not running, AlgoKit will automatically attempt to start it for you. If the LocalNet definition is out of date, you will see an error such as: ```bash algokit goal - Error: No such container: algokit_algod - Error: Error executing goal; ensure the Sandbox is started by executing `algokit sandbox status` -``` - -```bash -algokit goal - Error response from daemon: Container 5a73961536e2c98e371465739053d174066c40d00647c8742f2bb39eb793ed7e is not running - Error: Error executing goal; ensure the Sandbox is started by executing `algokit sandbox status` + Error: LocalNet definition is out of date; please run `algokit localnet reset` first! ``` ## Working with Files in the Container @@ -101,10 +94,10 @@ Here, `/Path/to/inputfile/approval.teal` and `/Path/to/outputfile/approval.compi In case you want to manually copy files into the container, you can do so using `docker cp`: ```bash -docker cp foo.txt algokit_algod:/root +docker cp foo.txt algokit_sandbox_algod:/root ``` -This command copies the `foo.txt` from your local system into the root directory of the `algokit_algod` container. +This command copies the `foo.txt` from your local system into the root directory of the `algokit_sandbox_algod` container. Note: Manual copying is optional and generally only necessary if you have specific reasons for doing so since the system will auto-mount paths specified in commands. diff --git a/docs/src/content/docs/features/init.md b/docs/src/content/docs/features/init.md index e71047550..c286574ce 100644 --- a/docs/src/content/docs/features/init.md +++ b/docs/src/content/docs/features/init.md @@ -10,7 +10,7 @@ For a quick start template with all of the defaults you can run: `algokit init` ## Prerequisites -Git is a prerequisite for the init command as it is used to clone templates and initialize git repos. Please consult the [README](../../README.md#prerequisites) for installation instructions. +Git is a prerequisite for the init command as it is used to clone templates and initialize git repos. Please consult the [README](https://github.com/algorandfoundation/algokit-cli#prerequisites) for installation instructions. ## Functionality @@ -18,11 +18,11 @@ As outlined in [quick start](#quick-start), the simplest use of the command is t ```bash algokit init -? Which of these options best describes the project you want to start? `Smart Contract` | `Dapp Frontend` | `Smart Contract & Dapp Frontend` | `Custom` +? Which of these options best describes the project you want to build? `Smart Contracts 📜` | `DApp Frontend 🖥️` | `Smart Contracts & DApp Frontend 🎛️` | `Custom Template 🛠️` ? Name of project / directory to create the project in: my-cool-app ``` -Once above 2 questions are answered, the `cli` will start instantiating the project and will start asking questions specific to the template you are instantiating. By default official templates such as `python`, `typescript`, `fullstack`, `react`, `python` include a notion of a `preset`. If you want to skip all questions and let the tool preset the answers tailored for a starter project you can pick `Starter`, for a more advanced project that includes unit tests, CI automation and other advanced features, pick `Production`. Lastly, if you prefer to modify the experience and tailor the template to your needs, pick the `Custom` preset. +Once the above 2 questions are answered, the `cli` will start instantiating the project and will start asking questions specific to the template you are instantiating. Many official templates (e.g. `python`, `typescript`, `fullstack`, `react`) expose their own template-level `preset` question via Copier; typical options include `Starter` (skip remaining questions and accept starter-tier answers), `Production` (a more advanced setup with unit tests, CI automation and other extras) or `Custom` (answer each question yourself). The exact presets and their behaviour are defined by the selected template, not by AlgoKit itself. If you want to accept the default for each option simply hit [enter] or alternatively to speed things up you can run `algokit init --defaults` and they will be auto-accepted. @@ -38,11 +38,11 @@ For more details on workspaces and standalone projects, refer to the [AlgoKit Pr ## Bootstrapping -You will also be prompted if you wish to run the [bootstrap](/algokit-cli/cli/#bootstrap) command, this is useful if you plan to immediately begin developing in the new project. If you passed in `--defaults` or `--bootstrap` then it will automatically run bootstrapping unless you passed in `--no-bootstrap`. +You will also be prompted if you wish to run the [project bootstrap](/algokit-cli/cli/#bootstrap) command, this is useful if you plan to immediately begin developing in the new project. If you passed in `--defaults` or `--bootstrap` then it will automatically run bootstrapping unless you passed in `--no-bootstrap`. ```bash -? Do you want to run `algokit bootstrap` to bootstrap dependencies for this new project so it can be run immediately? Yes +? Do you want to run `algokit project bootstrap` for this new project? This will install and configure dependencies allowing it to be run immediately. Yes Installing Python dependencies and setting up Python virtual environment via Poetry poetry: Creating virtualenv my-smart-contract in /Users/algokit/algokit-init/my-smart-contract/.venv poetry: Updating dependencies @@ -71,7 +71,7 @@ As a suggestion, if you wanted to open the project in VS Code you could execute: After bootstrapping you are also given the opportunity to initialize a git repo, upon successful completion of the init command the project is ready to be used. If you pass in `--git` it will automatically initialise the git repository and if you pass in `--no-git` it won't. -> Please note, when using `--no-workspaces`, algokit init will assume a max lookup depth of 1 for a fresh template based project. Otherwise it will assume a max depth of 2, since default algokit workspace structure is at most 2 levels deep. +> Please note, when using `--no-workspace`, algokit init will assume a max lookup depth of 1 for a fresh template based project. Otherwise it will assume a max depth of 2, since default algokit workspace structure is at most 2 levels deep. ## Options @@ -97,7 +97,7 @@ Please inspect the template repository, and pay particular attention to the valu ``` -If you want to create a community template, you can use the [AlgoKit guidelines on template building](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/tutorials/algokit-template.md#creating-algokit-templates) and [Copier documentation](https://copier.readthedocs.io/en/stable/) as a starting point. +If you want to create a community template, you can use the [AlgoKit guidelines on template building](/algokit-cli/tutorials/algokit-template/) and [Copier documentation](https://copier.readthedocs.io/en/stable/) as a starting point. ## Template Answers @@ -140,7 +140,7 @@ algokit init example -l/--list algokit init example ``` -When run without an example ID, the command launches an interactive selector that displays available examples with their descriptions and categories. Examples are copied to a new directory in your current location, named after the example ID. +When run without an example ID, the command launches an interactive selector that displays available examples with their name and type. Examples are copied to a new directory in your current location, named after the example ID. ### Available Examples diff --git a/docs/src/content/docs/features/localnet.md b/docs/src/content/docs/features/localnet.md index cf7456f4f..b58015320 100644 --- a/docs/src/content/docs/features/localnet.md +++ b/docs/src/content/docs/features/localnet.md @@ -63,20 +63,20 @@ If it's the first time running it on your machine then it will download the foll - [`algorand/algod`](https://hub.docker.com/r/algorand/algod) (~500 MB) - [`algorand/indexer`](https://hub.docker.com/r/algorand/indexer) (~96 MB) -- [`algorand/conduit`](https://hub.docker.com/r/algorand/conduit) (~98 MB) -- [`postgres:13-alpine`](https://hub.docker.com/_/postgres) (~80 MB) +- [`algorandfoundation/conduit-localnet`](https://hub.docker.com/r/algorandfoundation/conduit-localnet) (~98 MB) +- [`postgres:16-alpine`](https://hub.docker.com/_/postgres) (~100 MB) -Once they have downloaded, it won't try and re-download images unless you perform a `algokit localnet reset`. +Once they have downloaded, AlgoKit will not re-download images unless you run `algokit localnet reset --update`. Once the LocalNet has started, the following endpoints will be available: -- [algod](https://dev.algorand.co/reference/rest-apis/algod/): +- [algod](https://dev.algorand.co/reference/rest-api/algod/): - address: - token: `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` -- [kmd](https://dev.algorand.co/reference/rest-apis/kmd/): +- [kmd](https://dev.algorand.co/reference/rest-api/kmd/): - address: - token: `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` -- [indexer](https://dev.algorand.co/reference/rest-apis/indexer/): +- [indexer](https://dev.algorand.co/reference/rest-api/indexer/): - address: - tealdbg port: - address: @@ -128,7 +128,7 @@ If you change this setting for an existing LocalNet instance, AlgoKit will promp To stop the LocalNet you can execute `algokit localnet stop`. This will turn off the containers, but keep them ready to be started again in the same state by executing `algokit localnet start`. -To reset the LocalNet you can execute `algokit localnet reset`, which will tear down the existing containers, refresh the container definition from the latest stored within AlgoKit and update to the latest Docker images. If you want to keep the same container spec and versions as you currently have, but quickly tear down and start a new instance then run `algokit localnet reset --no-update`. +To reset the LocalNet you can execute `algokit localnet reset`, which will tear down the existing containers and refresh the container definition from the latest stored within AlgoKit. By default it does not pull new Docker images; pass `--update` to also pull the latest images (e.g. `algokit localnet reset --update`). ### Viewing transactions in the LocalNet @@ -141,7 +141,7 @@ See the [AlgoKit Goal](/algokit-cli/features/goal/) feature. You can also execut Note: if you want to copy files into the container so you can access them via goal then you can use the following: ``` -docker cp foo.txt algokit_algod:/root +docker cp foo.txt algokit_sandbox_algod:/root ``` ### Getting access to the private key of the faucet account @@ -163,14 +163,14 @@ Needing to do this manual step every time you spin up a new development environm AlgoKit Utils provides methods to help you do this: -- TypeScript - [`ensureFunded`](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/docs/capabilities/transfer.md#ensurefunded) and [`getDispenserAccount`](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/docs/capabilities/transfer.md#dispenser) -- Python - [`ensure_funded`](https://algorandfoundation.github.io/algokit-utils-py/html/apidocs/algokit_utils/algokit_utils.html#algokit_utils.ensure_funded) and [`get_dispenser_account`](https://algorandfoundation.github.io/algokit-utils-py/html/apidocs/algokit_utils/algokit_utils.html#algokit_utils.get_dispenser_account) +- TypeScript - [`ensureFunded`](https://algorandfoundation.github.io/algokit-utils-ts/concepts/building/transfer/#ensurefunded) and [`getDispenserAccount`](https://algorandfoundation.github.io/algokit-utils-ts/concepts/building/transfer/#dispenser) +- Python - [`ensure_funded`](https://algorandfoundation.github.io/algokit-utils-py/concepts/building/transfer/#ensure_funded) and [`get_dispenser_account`](https://algorandfoundation.github.io/algokit-utils-py/concepts/building/transfer/#dispenser) For more details about the `AlgoKit localnet` command, please refer to the [AlgoKit CLI reference documentation](/algokit-cli/cli/#localnet). ## GitHub Codespaces-based LocalNet -The AlgoKit LocalNet feature also supports running the LocalNet in a GitHub Codespace with port forwarding by utilizing the [GitHub CLI](https://github.com/cli/gh). This allows you to run the LocalNet without the need to use Docker. This is especially useful for scenarios where certain hardware or software limitations may prevent you from being able to run Docker. +The AlgoKit LocalNet feature also supports running the LocalNet in a GitHub Codespace with port forwarding by utilizing the [GitHub CLI](https://github.com/cli/cli). This allows you to run the LocalNet without the need to use Docker. This is especially useful for scenarios where certain hardware or software limitations may prevent you from being able to run Docker. To run the LocalNet in a GitHub Codespace, you can use the `algokit localnet codespace` command. By default without `--force` flag it will prompt you to delete stale codespaces created earlier (if any). Upon termination it will also prompt to delete the codespace that was used prior to termination. @@ -179,13 +179,13 @@ Running an interactive session ensures that you have control over the lifecycle ### Options -- `-m`, `--machine`: Specifies the GitHub Codespace machine type to use. Defaults to `basicLinux32gb`. Available options are `basicLinux32gb`, `standardLinux32gb`, `premiumLinux`, and `largePremiumLinux`. Refer to [GitHub Codespaces documentation](https://docs.github.com/en/codespaces/overview/machine-types) for more details. +- `-m`, `--machine`: Specifies the GitHub Codespace machine type to use. Defaults to `basicLinux32gb`. Available options are `basicLinux32gb`, `standardLinux32gb`, `premiumLinux`, and `largePremiumLinux`. Refer to [GitHub Codespaces documentation](https://docs.github.com/en/codespaces/customizing-your-codespace/changing-the-machine-type-for-your-codespace) for more details. - `-a`, `--algod-port`: Sets the port for the Algorand daemon. Defaults to `4001`. - `-i`, `--indexer-port`: Sets the port for the Algorand indexer. Defaults to `8980`. - `-k`, `--kmd-port`: Sets the port for the Algorand kmd. Defaults to `4002`. - `-n`, `--codespace-name`: Specifies the name of the codespace. Defaults to a random name with a timestamp. -- `-t`, `--timeout`: Max duration for running the port forwarding process. Defaults to 1 hour. This timeout ensures the codespace **will automatically shut down** after the specified duration to prevent accidental overspending of free quota on GitHub Codespaces. [More details](https://docs.github.com/en/codespaces/setting-your-user-preferences/setting-your-timeout-period-for-github-codespaces). -- `-r`, `--repo-url`: The URL of the repository to use. Defaults to the AlgoKit base template repository (`algorandfoundation/algokit-base-template`). The reason why algokit-base-template is used by default is due to [.devcontainer.json](https://github.com/algorandfoundation/algokit-base-template/blob/main/template_content/.devcontainer.json) which defines the scripts that take care of setting up AlgoKit CLI during container start. You can use any custom repo as a base, however it's important to ensure the reference [.devcontainer.json](https://github.com/algorandfoundation/algokit-base-template/blob/main/template_content/.devcontainer.json) file exists in your repository **otherwise there will be no ports to forward from the codespace**. +- `-t`, `--timeout`: Max duration for running the port forwarding process, in minutes. Defaults to 240 (4 hours). This timeout ensures the codespace **will automatically shut down** after the specified duration to prevent accidental overspending of free quota on GitHub Codespaces. [More details](https://docs.github.com/en/codespaces/setting-your-user-preferences/setting-your-timeout-period-for-github-codespaces). +- `-r`, `--repo-url`: The URL of the repository to use. Defaults to the AlgoKit base template repository (`algorandfoundation/algokit-base-template`). The reason why algokit-base-template is used by default is due to [.devcontainer.json](https://github.com/algorandfoundation/algokit-base-template/blob/main/.devcontainer.json) which defines the scripts that take care of setting up AlgoKit CLI during container start. You can use any custom repo as a base, however it's important to ensure the reference [.devcontainer.json](https://github.com/algorandfoundation/algokit-base-template/blob/main/.devcontainer.json) file exists in your repository **otherwise there will be no ports to forward from the codespace**. - `--force`, `-f`: Force deletes stale codespaces and skips confirmation prompts. Defaults to explicitly prompting for confirmation. For more details about managing LocalNet in GitHub Codespaces, please refer to the [AlgoKit CLI reference documentation](/algokit-cli/cli/#codespace). diff --git a/docs/src/content/docs/features/overview.md b/docs/src/content/docs/features/overview.md index 32a3b3670..41d4d02f5 100644 --- a/docs/src/content/docs/features/overview.md +++ b/docs/src/content/docs/features/overview.md @@ -9,14 +9,15 @@ The Algorand AlgoKit CLI is the one-stop shop tool for developers building on th For details on how to use individual features see the following - [Bootstrap](/algokit-cli/features/project/bootstrap/) - Bootstrap AlgoKit project dependencies -- [Compile](/algokit-cli/features/compile/) - Compile Algorand Python code +- [Compile](/algokit-cli/features/compile/) - Compile Algorand smart contracts (Python and TypeScript) - [Completions](/algokit-cli/features/completions/) - Install shell completions for AlgoKit +- [Config](/algokit-cli/features/config/) - Configure AlgoKit settings - [Deploy](/algokit-cli/features/project/deploy/) - Deploy your smart contracts effortlessly to various networks - [Dispenser](/algokit-cli/features/dispenser/) - Fund your TestNet account with ALGOs from the AlgoKit TestNet Dispenser - [Doctor](/algokit-cli/features/doctor/) - Check AlgoKit installation and dependencies - [Explore](/algokit-cli/features/explore/) - Explore Algorand Blockchains using lora - [Generate](/algokit-cli/features/generate/) - Generate code for an Algorand project -- [Goal](/algokit-cli/features/goal/) - Run the Algorand goal CLI against the AlgoKit Sandbox +- [Goal](/algokit-cli/features/goal/) - Run the Algorand goal CLI against the AlgoKit LocalNet - [Init](/algokit-cli/features/init/) - Quickly initialize new projects using official Algorand Templates or community provided templates - [LocalNet](/algokit-cli/features/localnet/) - Manage a locally sandboxed private Algorand network - [Project](/algokit-cli/features/project/) - Manage an AlgoKit project workspace on your file system diff --git a/docs/src/content/docs/features/project/bootstrap.md b/docs/src/content/docs/features/project/bootstrap.md index 0b08a8d63..6684c5d9a 100644 --- a/docs/src/content/docs/features/project/bootstrap.md +++ b/docs/src/content/docs/features/project/bootstrap.md @@ -2,14 +2,14 @@ title: "AlgoKit Project Bootstrap" --- -The AlgoKit Project Bootstrap feature allows you to bootstrap different project dependencies by looking up specific files in your current directory and immediate sub directories by convention. +The AlgoKit Project Bootstrap feature allows you to bootstrap different project dependencies by looking up specific files in your current directory and up to two levels of sub directories by convention. -This is useful to allow for expedited initial setup for each developer e.g. when they clone a repository for the first time. It's also useful to provide a quick getting started experience when initialising a new project via [AlgoKit Init](./init.md) and meeting our goal of "nothing to debugging code in 5 minutes". +This is useful to allow for expedited initial setup for each developer e.g. when they clone a repository for the first time. It's also useful to provide a quick getting started experience when initialising a new project via [AlgoKit Init](../init.md) and meeting our goal of "nothing to debugging code in 5 minutes". It can bootstrap one or all of the following (with other options potentially being added in the future): -- Python projects - Supports Poetry and uv package managers. Installs the configured package manager if not present and runs the appropriate install command. -- JavaScript/Node.js projects - Supports npm and pnpm package managers. Runs the appropriate install command for the configured package manager. +- Python projects - Supports Poetry and uv package managers. If the configured Python package manager isn't found, AlgoKit will offer to install it and then run the appropriate install command. +- JavaScript/Node.js projects - Supports npm and pnpm package managers. Runs the appropriate install command for the configured package manager. The Node.js package manager itself must already be installed; AlgoKit will not install `npm` or `pnpm` for you. - dotenv (.env) file - Checks for `.env.template` files, copies them to `.env` (which should be in `.gitignore` so developers can safely make local specific changes) and prompts for any blank values (so the developer has an easy chance to fill in their initial values where there isn't a clear default). > **Note**: Invoking bootstrap from `algokit bootstrap` is not recommended. Please prefer using `algokit project bootstrap` instead. @@ -39,7 +39,7 @@ The bootstrap command follows this precedence order when determining which packa 1. **Project override** - Configuration in `.algokit.toml` (highest priority) 2. **User preference** - Global configuration set via `algokit config` (respects your explicit choice) -3. **Smart defaults** - Based on project structure (e.g., `poetry.toml` → Poetry, `pnpm-lock.yaml` → PNPM) +3. **Smart defaults** - Based on project structure. For Python, in order: `uv.lock` → uv, then `poetry.toml` → Poetry, then `pyproject.toml` containing `[tool.poetry]` → Poetry. For JavaScript: `pnpm-lock.yaml` → pnpm, then `package-lock.json` → npm. 4. **Interactive prompt** - Asked on first use if no preference is set This means if you set a global preference (e.g., `algokit config py-package-manager uv`), it will be used across all projects unless explicitly overridden at the project level. Smart defaults only apply when you haven't set a preference yet. @@ -67,12 +67,12 @@ When you run `algokit project bootstrap`, if your project contains run commands **Commands that DON'T translate** (will show a warning): -- `npm exec` / `npx` ↔ `pnpm exec` / `pnpm dlx` - Different behavior: +- `npm exec` / `npx` and `pnpm exec` / `pnpm dlx` - Different behavior: - `npx` searches locally in `node_modules/.bin`, then in global installs, then downloads remotely if not found - `pnpm exec` only searches locally in project dependencies (fails if not found locally) - `pnpm dlx` always fetches from remote registry (never checks local dependencies) - `npm fund` - No pnpm equivalent (pnpm does not provide funding information display) -- `npm audit` ↔ `pnpm audit` - May report different vulnerabilities due to differences in auditing algorithms and vulnerability databases (command translates with warning) +- `npm audit` and `pnpm audit` - Behave differently across the two managers, so AlgoKit leaves them unchanged and emits a warning rather than translating between them. ### Python Translation (poetry ↔ uv) @@ -128,8 +128,8 @@ deps = { commands = ["poetry show --tree"] } # ⚠️ Not translated (warnin You'll see warnings: ``` -⚠️ Command 'npx create-next-app' behaves differently in pnpm. Consider using 'pnpm exec' for local binaries or 'pnpm dlx' for remote packages. The command will remain unchanged. -⚠️ Command 'poetry show --tree' has no direct equivalent in uv. The command will remain unchanged and may not work as expected. +⚠️ Command 'npx create-next-app' may not be compatible with pnpm. The command will remain unchanged and may not work as expected. +⚠️ Command 'poetry show --tree' may not be compatible with uv. The command will remain unchanged and may not work as expected. ``` This approach ensures your project commands work correctly while being transparent about limitations. @@ -143,13 +143,16 @@ algokit project bootstrap Usage: algokit project bootstrap [OPTIONS] COMMAND [ARGS]... Options: + --force Continue even if minimum AlgoKit version is not met -h, --help Show this message and exit. Commands: - all Bootstrap all aspects of the current directory and immediate sub directories by convention. - env Bootstrap .env file in the current working directory. - npm Bootstrap Node.js project in the current working directory. - poetry Bootstrap Python Poetry and install in the current working directory. + all Runs all bootstrap sub-commands in the current directory and immediate sub directories. + env Copies .env.template file to .env in the current working directory and prompts for any unspecified values. + npm Runs `npm install` in the current working directory to install Node.js dependencies. + pnpm Runs `pnpm install` in the current working directory to install Node.js dependencies. + poetry Installs Python Poetry (if not present) and runs `poetry install` in the current working directory to install Python dependencies. + uv Installs UV (if not present) and runs `uv sync` in the current working directory to install Python dependencies. ``` ## Functionality @@ -158,8 +161,8 @@ Commands: The command `algokit project bootstrap env` runs two main tasks in the current directory: -- Searching for `.env.template` file in the current directory and use it as template to create a new `.env` file in the same directory. -- Prompting the user to enter a value for any empty token values in the `env.` including printing the comments above that empty token +- Searching for `.env*.template` files in the current directory (e.g. `.env.template`, `.env.testnet.template`) and using each as a template to create the matching `.env` / `.env.{network}` file in the same directory. +- Prompting the user to enter a value for any empty token values in the `.env` file, including printing the comments above that empty token. For instance, a sample `.env.template` file as follows: @@ -175,7 +178,7 @@ Running the `algokit project bootstrap env` command while the above `.env.templa ```bash algokit project bootstrap env Copying /Users/me/my-project/.env.template to /Users/me/my-project/.env and prompting for empty values -# This is a mandatory field to run the server, please enter a value value +# This is a mandatory field to run the server, please enter a value # For example: 5000 ? Please provide a value for SERVER_PORT: @@ -190,7 +193,7 @@ SERVER_URL=https://myserver.com SERVER_PORT=4000 ``` -### Bootstrap Node.js project +### Bootstrap Node.js npm project The command `algokit project bootstrap npm` installs Node.js project dependencies if there is a `package.json` file in the current directory by running `npm install` command to install all node modules specified in that file. However, when running in CI mode **with** present `package-lock.json` file (either by setting the `CI` environment variable or using the `--ci` flag), it will run `npm ci` instead, which provides a cleaner and more deterministic installation. If `package-lock.json` is missing, it will show a clear error message and resolution instructions. If you don't have `npm` available it will show a clear error message and resolution instructions. @@ -208,12 +211,16 @@ npm: npm: found 0 vulnerabilities ``` +### Bootstrap Node.js pnpm project + +The command `algokit project bootstrap pnpm` installs Node.js project dependencies if there is a `package.json` file in the current directory by running `pnpm install`. In CI mode (either by setting the `CI` environment variable or using the `--ci` flag) AlgoKit checks that `pnpm-lock.yaml` exists first and fails fast with a clear error message if it doesn't; the install command itself is still `pnpm install` and relies on pnpm's own CI auto-detection to behave as `--frozen-lockfile`. If `pnpm` isn't available it will show a clear error message and resolution instructions. + ### Bootstrap Python poetry project The command `algokit project bootstrap poetry` does two main actions: -- Checking for Poetry version by running `poetry --version` and upgrades it if required -- Installing Python dependencies and setting up Python virtual environment via Poetry in the current directory by running `poetry install`. +- Checking for an installed Poetry by running `poetry --version`. If Poetry isn't found, AlgoKit looks for a tool runner (`uv` or `pipx`) and offers to install Poetry through whichever it finds (preferring `uv`); if neither is available it surfaces a clear error message pointing to the upstream install docs. +- Installing Python dependencies and setting up the Python virtual environment via Poetry in the current directory by running `poetry install`. If `poetry` isn't on `PATH` immediately after install, AlgoKit retries via the tool runner (e.g. `uv tool run --from=poetry poetry install`, or the equivalent `uvx --from=poetry poetry install` / `pipx run --spec=poetry poetry install`). Here is an example of running `algokit project bootstrap poetry` command: @@ -231,13 +238,28 @@ poetry: poetry: Installing the current project: algokit (0.1.0) ``` +### Bootstrap Python uv project + +The command `algokit project bootstrap uv` does the following: + +- Checks for an installed `uv` by running `uv --version`. If `uv` isn't found, AlgoKit prompts to install it directly via the official installer (`curl -LsSf https://astral.sh/uv/install.sh | sh` on macOS/Linux, the PowerShell equivalent on Windows). If you decline, or installation fails, it raises a clear error with instructions pointing to . +- If `pyproject.toml` exists **and** still contains a `[tool.poetry]` section, AlgoKit prompts to migrate the project to a uv-compatible format using the third-party [`migrate-to-uv`](https://osprey-oss.github.io/migrate-to-uv/) tool (executed via `uvx`). If you decline, the command errors out; you'll need to either use `algokit project bootstrap poetry` instead, switch your default via `algokit config py-package-manager`, or update `pyproject.toml` manually. +- Installs Python dependencies and sets up the virtual environment by running `uv sync` in the project directory. If `uv` was just installed in this same run and isn't on `PATH` yet, the command errors with a clear message asking you to restart your terminal and re-run. + ### Bootstrap all -Execute `algokit project bootstrap all` to initiate `algokit project bootstrap env`, `algokit project bootstrap npm`, and `algokit project bootstrap poetry` commands within the current directory and all its immediate sub-directories. This comprehensive command is automatically triggered following the initialization of a new project through the [AlgoKit Init](./init.md) command. +Execute `algokit project bootstrap all` to bootstrap the current directory and its sub-directories (up to two levels deep). For each directory, AlgoKit: + +1. Runs `algokit project bootstrap env` if any `.env*.template` files are present. +2. If the directory looks like a Python project (`poetry.toml` or `pyproject.toml` present), runs whichever Python package manager applies (`uv` or `poetry`, based on configuration; see [Package Manager Override](#package-manager-override) and [Configuration Precedence](#configuration-precedence)). +3. If the directory looks like a JavaScript project (`package.json` present), runs the corresponding JavaScript package manager (`npm` or `pnpm`). +4. If a Python and/or JavaScript manager was used, rewrites any matching commands under `[project.run]` in that directory's `.algokit.toml` to use the selected manager; see [Package Manager Command Translation](#package-manager-command-translation). + +This comprehensive command is automatically triggered following the initialization of a new project through the [AlgoKit Init](../init.md) command. #### Filtering Options -The `algokit project bootstrap all` command includes flags for more granular control over the bootstrapping process within [AlgoKit workspaces](/algokit-cli/features/init/#workspaces): +The `algokit project bootstrap all` command includes flags for more granular control over the bootstrapping process within [AlgoKit workspaces](/algokit-cli/features/init/#workspaces-vs-standalone-projects): - `--project-name`: This flag allows you to specify one or more project names to bootstrap. Only projects matching the provided names will be bootstrapped. This is particularly useful in monorepos or when working with multiple projects in the same directory structure. diff --git a/docs/src/content/docs/features/project/deploy.md b/docs/src/content/docs/features/project/deploy.md index 0a1a2e72e..ff27e48e3 100644 --- a/docs/src/content/docs/features/project/deploy.md +++ b/docs/src/content/docs/features/project/deploy.md @@ -17,7 +17,7 @@ This command deploys smart contracts from an AlgoKit compliant repository to the ### Options - `--command, -C TEXT`: Specifies a custom deploy command. If this option is not provided, the deploy command will be loaded from the `.algokit.toml` file. -- `--interactive / --non-interactive, --ci`: Enables or disables the interactive prompt for mnemonics. When the CI environment variable is set, it defaults to non-interactive. +- `--interactive / --non-interactive, --ci`: Enables or disables interactive prompts (for mnemonics and the MainNet deployment confirmation). Defaults to non-interactive when the `CI` environment variable is set. - `--path, -P DIRECTORY`: Specifies the project directory. If not provided, the current working directory will be used. - `--deployer`: Specifies the deployer alias. If not provided and if the deployer is specified in `.algokit.toml` file its mnemonic will be prompted. - `--dispenser`: Specifies the dispenser alias. If not provided and if the dispenser is specified in `.algokit.toml` file its mnemonic will be prompted. @@ -41,19 +41,21 @@ The directory layout would look like this: ├── ... (your project files and directories) ├── .algokit.toml # Configuration file for AlgoKit ├── .env # (OPTIONAL) General environment variables common across all deployments -└── .env.[{mainnet|testnet|localnet|betanet|custom}] # (OPTIONAL) Environment variables specific to deployments to a network +└── .env.[{mainnet|testnet|localnet|custom}] # (OPTIONAL) Environment variables specific to deployments to a network ``` -> ⚠️ Please note that creating `.env` and `.env.[network_name]` files is only necessary if you're deploying to a custom network or if you want to override the default network configurations provided by AlgoKit. AlgoKit comes with predefined configurations for popular networks like `TestNet`, `MainNet`, `BetaNet`, or AlgoKit's `LocalNet`. +> ⚠️ Please note that creating `.env` and `.env.[network_name]` files is only necessary if you're deploying to a custom network or if you want to override the default network configurations provided by AlgoKit. AlgoKit comes with predefined configurations for `TestNet`, `MainNet`, and AlgoKit's `LocalNet`. Other networks (e.g. `BetaNet`) require an explicit `.env.[network_name]` file. -The logic for loading environment variables is as follows: +Environment variables are loaded with the following precedence (lowest to highest): -- If a `.env` file exists, the environment variables contained in it are loaded first. -- If a `.env.[network_name]` file exists, the environment variables in it are loaded, overriding any previously loaded values from the `.env` file for the same variables. +1. `.env` +2. `.env.[network_name]`, which overrides values from `.env` for matching keys. +3. AlgoKit built-in defaults for known networks (see below). These are applied unconditionally when deploying to `localnet`, `testnet`, or `mainnet`, and override any matching keys from the `.env` files. +4. Process environment variables (i.e. variables set in your shell or CI environment), which override everything else. ### Default Network Configurations -The `deploy` command assumes default configurations for `mainnet`, `localnet`, and `testnet` environments. If you're deploying to one of these networks and haven't provided specific environment variables, AlgoKit will use these default values: +When deploying to `localnet`, `testnet`, or `mainnet`, AlgoKit injects the following defaults for the algod and indexer connection variables. As noted above, these are applied after the `.env` files are loaded and will override any matching keys set there. To point at a different node for these networks, set the variable in your shell or CI environment rather than in `.env.[network_name]`. - **Localnet**: @@ -73,9 +75,7 @@ The `deploy` command assumes default configurations for `mainnet`, `localnet`, a - `ALGOD_SERVER`: "https://testnet-api.algonode.cloud" - `INDEXER_SERVER`: "https://testnet-idx.algonode.cloud" -These default values are used when no specific `.env.[network_name]` file is present and the corresponding environment variables are not set. This feature simplifies the deployment process for these common networks, reducing the need for manual configuration in many cases. - -If you need to override these defaults or add additional configuration for these networks, you can still do so by creating the appropriate `.env.[network_name]` file or setting the environment variables explicitly or via generic `.env` file. +Variables not listed above (including any custom variables your deploy script needs) follow the normal `.env` → `.env.[network_name]` → process-environment precedence, without any built-in overrides. ## AlgoKit Configuration File @@ -132,7 +132,7 @@ Root `.algokit.toml`: ```toml [project] type = "workspace" -projects_root_dir = 'projects' +projects_root_path = 'projects' ``` Contract project `.algokit.toml`: @@ -154,29 +154,29 @@ This command deploys the smart contracts to TestNet from a sub project named 'my ## Custom Project Directory -By default, the deploy command looks for the `.algokit.toml` file in the current working directory. You can specify a custom project directory using the `--project-dir` option. +By default, the deploy command looks for the `.algokit.toml` file in the current working directory. You can specify a custom project directory using the `--path` (`-P`) option. Example: ```bash -algokit project deploy testnet --project-dir="path/to/project" +algokit project deploy testnet --path="path/to/project" ``` ## Custom Deploy Command -You can provide a custom deploy command using the `--custom-deploy-command` option. If this option is not provided, the deploy command will be loaded from the `.algokit.toml` file. +You can provide a custom deploy command using the `--command` (`-C`) option. If this option is not provided, the deploy command will be loaded from the `.algokit.toml` file. Example: ```bash -algokit project deploy testnet --custom-deploy-command="your-custom-command" +algokit project deploy testnet --command="your-custom-command" ``` >⚠️ Please note, chaining multiple commands with `&&` is **not** currently supported. If you need to run multiple commands, you can defer to a custom script. Refer to [run](/algokit-cli/features/project/run/#custom-command-injection) for scenarios where multiple sub-command invocations are required. ## CI Mode -By using the `--ci` or `--non-interactive` flag, you can skip the interactive prompt for mnemonics. +By using the `--ci` or `--non-interactive` flag, you can skip the interactive prompts (including the MainNet deployment confirmation and any mnemonic prompts). This is useful in CI/CD environments where user interaction is not possible. When using this flag, you need to make sure that the mnemonics are set as environment variables. @@ -203,7 +203,7 @@ In this example, `my_contract_name` and `--some_contract_related_param` are extr ## Example of a Full Deployment ```bash -algokit project deploy testnet --custom-deploy-command="your-custom-command" +algokit project deploy testnet --command="your-custom-command" ``` This example shows how to deploy smart contracts to the testnet using a custom deploy command. This also assumes that .algokit.toml file is present in the current working directory, and .env.testnet file is present in the current working directory and contains the required environment variables for deploying to TestNet environment. diff --git a/docs/src/content/docs/features/project/link.md b/docs/src/content/docs/features/project/link.md index 8937979bf..ba0dee497 100644 --- a/docs/src/content/docs/features/project/link.md +++ b/docs/src/content/docs/features/project/link.md @@ -16,9 +16,9 @@ This command must be invoked from the root of a standalone 'frontend' typed proj ## Options -- `--project-name`, `-p`: Specify one or more contract projects for the command. If not provided, the command defaults to all contract projects in the current workspace. This option can be repeated to specify multiple projects. +- `--project-name`, `-p`: Specify one or more contract projects for the command. If neither this option nor `--all` is provided, you will be prompted to interactively select a single contract project from the workspace. This option can be repeated to specify multiple projects. -- `--language`, `-l`: Set the programming language of the generated client code. The default is `typescript`, but you can specify other supported languages as well. +- `--language`, `-l`: Set the programming language of the generated client code. The default is `typescript`. The supported values are `typescript` and `python`. - `--all`, `-a`: Link all contract projects with the frontend project. This option is mutually exclusive with `--project-name`. @@ -32,13 +32,9 @@ Below is a visual representation of the `algokit project link` command in action ```mermaid graph LR - F[Frontend Project] -->|algokit generate client| C1[Contract Project 1] - F -->|algokit generate client| C2[Contract Project 2] - F -->|algokit generate client| CN[Contract Project N] - - C1 -->|algokit generate client| F - C2 -->|algokit generate client| F - CN -->|algokit generate client| F + C1[Contract Project 1] -->|algokit generate client| F[Frontend Project] + C2[Contract Project 2] -->|algokit generate client| F + CN[Contract Project N] -->|algokit generate client| F classDef frontend fill:#f9f,stroke:#333,stroke-width:4px; classDef contract fill:#bbf,stroke:#333,stroke-width:2px; @@ -50,7 +46,7 @@ graph LR 2. **Contract Project Selection**: Based on the provided options, it selects the contract projects to link. This can be all contract projects within the workspace, a subset specified by name, or a single project selected interactively. -3. **Client Code Generation**: For each selected contract project, it generates typed client code using the specified language. The generated code is placed in the frontend project's directory specified for contract clients. +3. **Client Code Generation**: For each selected contract project, it generates typed client code using the specified language. The generated code is written into the directory the frontend project advertises via the `artifacts` key under `[project]` in its `.algokit.toml`. 4. **Feedback**: The command provides feedback for each contract project it processes, indicating success or failure in generating the client code. diff --git a/docs/src/content/docs/features/project/list.md b/docs/src/content/docs/features/project/list.md index 78940ea87..d48f52592 100644 --- a/docs/src/content/docs/features/project/list.md +++ b/docs/src/content/docs/features/project/list.md @@ -16,18 +16,20 @@ algokit project list [OPTIONS] [WORKSPACE_PATH] ## How It Works -1. **Workspace Verification**: Initially, the command checks if the specified directory (or the current directory by default) is an AlgoKit workspace. This is determined by looking for a `.algokit.toml` configuration file and verifying if the `project.type` is set to `workspace`. +1. **Workspace Verification**: Initially, the command checks if the specified directory (or the current directory by default) is an AlgoKit workspace. This is determined by looking for a `.algokit.toml` configuration file and verifying if the `project.type` is set to `workspace`. If the starting directory is not a workspace, the command walks up to two parent directories looking for one, which is why it can be invoked anywhere within a workspace. -2. **Project Enumeration**: If the directory is confirmed as a workspace, the command proceeds to enumerate all projects within the workspace. This is achieved by scanning the workspace's subdirectories for `.algokit.toml` files and extracting project names. +2. **Project Enumeration**: If a workspace is found, the command enumerates its sub-projects by reading the `project.projects_root_path` defined in the workspace's `.algokit.toml`, then iterating over immediate subdirectories of that path which themselves contain an `.algokit.toml`. The results are sorted alphanumerically by directory name. -3. **Output**: The names of all discovered projects are printed to the console. If the `-v` or `--verbose` option is used, additional details about each project are displayed. +3. **Output**: The command first prints the workspace header with the resolved workspace path, followed by each sub-project's name and directory. A project's directory is shown as `this directory` only when it equals the current working directory; otherwise the absolute path is shown. ## Example Output +Run from inside the workspace root with two sub-projects (a contract and a frontend): + ```bash -workspace: {path_to_workspace} 📁 - - myapp ({path_to_myapp}) 📜 - - myproject-app ({path_to_myproject_app}) 🖥️ +workspace: /path/to/workspace 📁 + - myapp (/path/to/workspace/projects/myapp) 📜 + - myproject-app (/path/to/workspace/projects/myproject-app) 🖥️ ``` ## Error Handling @@ -38,7 +40,13 @@ If the command is executed in a directory that is not recognized as an AlgoKit w WARNING: No AlgoKit workspace found. Check [project.type] definition at .algokit.toml ``` -This message indicates that either the current directory does not contain a `.algokit.toml` file or the `project.type` within the file is not set to `workspace`. +This message indicates that no `.algokit.toml` with `project.type = "workspace"` was found in the target directory or its parents (up to two levels up). + +If a workspace is found but contains no sub-projects, a different warning is emitted: + +```bash +WARNING: No AlgoKit project(s) found in the workspace. Check [project.type] definition at .algokit.toml +``` ## Further Reading diff --git a/docs/src/content/docs/features/project/run.md b/docs/src/content/docs/features/project/run.md index 295ef510a..2b2c7b9e9 100644 --- a/docs/src/content/docs/features/project/run.md +++ b/docs/src/content/docs/features/project/run.md @@ -14,11 +14,14 @@ This command executes a custom command defined in the `.algokit.toml` file of th ### Options +The `-l`, `-p`, `-t`, `-s` and `-c` flags below are only available when running from a workspace root. + - `-l, --list`: List all projects associated with the workspace command. (Optional) - `-p, --project-name`: Execute the command on specified projects. Defaults to all projects in the current directory. (Optional) - `-t, --type`: Limit execution to specific project types if executing from workspace. (Optional) -- `-s, --sequential`: Execute workspace commands sequentially, for cases where you do not have a preference on the execution order, but want to disable concurrency. (Optional, defaults to concurrent) -- `[ARGS]...`: Additional arguments to pass to the custom command. These will be appended to the end of the command specified in the `.algokit.toml` file. +- `-s, --sequential`: Execute workspace commands sequentially. (Optional, defaults to concurrent) +- `-c, --concurrent`: Execute workspace commands concurrently. (Optional, the default) +- `[ARGS]...`: Additional arguments to pass to the custom command. These will be appended to the last command in the `.algokit.toml` entry (relevant when a command defines multiple commands). To get detailed help on the above options, execute: @@ -67,7 +70,10 @@ Below is only visible and available when running from a workspace root. - `-l, --list`: List all projects associated with the workspace command. (Optional) - `-p, --project-name`: Execute the command on specified projects. Defaults to all projects in the current directory. (Optional) - `-t, --type`: Limit execution to specific project types if executing from workspace. (Optional) - To get a detailed help on the above commands execute: +- `-s, --sequential`: Execute workspace commands sequentially. (Optional, defaults to concurrent) +- `-c, --concurrent`: Execute workspace commands concurrently. (Optional, the default) + +To get a detailed help on the above commands execute: ```bash algokit project run {name_of_your_command} --help @@ -108,6 +114,8 @@ name = 'project_a' [project.run] hello = { commands = ['echo hello'], description = 'Prints hello' } +# Each command also accepts an optional `env_file` to load extra env vars before execution: +# greet = { commands = ['echo "hello $USER_NAME"'], description = 'Greets', env_file = '.env.greet' } # ... other non [project.run] related metadata ``` @@ -135,7 +143,7 @@ Customize the execution order of commands in workspaces for precise control: 1. Define order in `.algokit.toml`: - ```yaml + ```toml [project] type = 'workspace' projects_root_path = 'projects' diff --git a/docs/src/content/docs/features/tasks/analyze.md b/docs/src/content/docs/features/tasks/analyze.md index c2b90568a..b1089a6ff 100644 --- a/docs/src/content/docs/features/tasks/analyze.md +++ b/docs/src/content/docs/features/tasks/analyze.md @@ -18,7 +18,7 @@ algokit task analyze INPUT_PATHS [OPTIONS] - `-r, --recursive`: Recursively search for all TEAL files within any provided directories. - `--force`: Force verification without the disclaimer confirmation prompt. -- `--diff`: Exit with a non-zero code if differences are found between current and last reports. +- `--diff`: Compare against the previously stored report (requires a prior run without `--diff` to produce a baseline). Exits with a non-zero code if the current report differs from the previous one, or if no previous report exists. - `-o, --output OUTPUT_PATH`: Directory path where to store the reports of the static analysis. - `-e, --exclude DETECTORS`: Exclude specific vulnerabilities from the analysis. Supports multiple exclusions in a single run. @@ -28,8 +28,8 @@ algokit task analyze INPUT_PATHS [OPTIONS] algokit task analyze ./contracts -r --exclude rekey-to --exclude missing-fee-check ``` -This command will recursively analyze all TEAL files in the `contracts` directory and exclude the `missing-fee-check` vulnerability from the analysis. +This command will recursively analyze all TEAL files in the `contracts` directory and exclude the `rekey-to` and `missing-fee-check` vulnerabilities from the analysis. ## Security considerations -This task uses [`tealer`](https://github.com/crytic/tealer), a third-party tool, to suggest improvements for your TEAL programs, but remember to always test your smart contracts code, follow modern software engineering practices and use the [guidelines for smart contract development](https://dev.algorand.co/docs/concepts/smart-contracts/overview/). This should not be used as a substitute for an actual audit. +This task uses [`tealer`](https://github.com/crytic/tealer), a third-party tool, to suggest improvements for your TEAL programs, but remember to always test your smart contracts code, follow modern software engineering practices and use the [guidelines for smart contract development](https://dev.algorand.co/concepts/smart-contracts/overview/). This should not be used as a substitute for an actual audit. diff --git a/docs/src/content/docs/features/tasks/ipfs.md b/docs/src/content/docs/features/tasks/ipfs.md index 2a522d05a..9a7e5530d 100644 --- a/docs/src/content/docs/features/tasks/ipfs.md +++ b/docs/src/content/docs/features/tasks/ipfs.md @@ -10,24 +10,27 @@ Available commands and possible usage as follows: ```bash algokit task ipfs -Usage: algokit task ipfs [OPTIONS] +Usage: algokit task ipfs [OPTIONS] COMMAND [ARGS]... -Upload files to IPFS using Pinata provider. + Upload files to IPFS using Pinata provider. Options: - -f, --file PATH Path to the file to upload. [required] - -n, --name TEXT Human readable name for this upload, for use in file listings. - -h, --help Show this message and exit. + -h, --help Show this message and exit. + +Commands: + login Login to Pinata ipfs provider. + logout Logout of Pinata ipfs provider. + upload Upload a file to Pinata ipfs provider. ``` -## Options +## Upload options - `--file, -f PATH`: Specifies the path to the file to upload. This option is required. - `--name, -n TEXT`: Specifies a human readable name for this upload, for use in file listings. ## Prerequisites -Before you can use this feature, you need to ensure that you have signed up for a Piñata account and have a JWT. You can sign up for a Piñata account by reading [quickstart](https://docs.pinata.cloud/docs/getting-started). +Before you can use this feature, you need to ensure that you have signed up for a Piñata account and have a JWT. You can sign up for a Piñata account by reading [quickstart](https://docs.pinata.cloud/quickstart). ## Login @@ -41,10 +44,10 @@ This will prompt you to enter your Piñata JWT. Once you are logged in, you can ## Upload -To upload a file to IPFS, you can use the `ipfs` command as follows: +To upload a file to IPFS, use the `upload` subcommand: ```bash -algokit task ipfs --file {PATH_TO_YOUR_FILE} +algokit task ipfs upload --file {PATH_TO_YOUR_FILE} ``` This will upload the file to IPFS using the Piñata provider and return the CID (Content Identifier) of the uploaded file. diff --git a/docs/src/content/docs/features/tasks/mint.md b/docs/src/content/docs/features/tasks/mint.md index 58ee1e75d..6f3d05aac 100644 --- a/docs/src/content/docs/features/tasks/mint.md +++ b/docs/src/content/docs/features/tasks/mint.md @@ -15,18 +15,20 @@ Usage: algokit task mint [OPTIONS] Options: --creator TEXT Address or alias of the asset creator. [required] - -n, --name TEXT Asset name. [required] + --name TEXT Asset name. -u, --unit TEXT Unit name of the asset. [required] -t, --total INTEGER Total supply of the asset. Defaults to 1. -d, --decimals INTEGER Number of decimals. Defaults to 0. + --nft / --ft Whether the asset should be validated as NFT or FT. Refers to FT by default; when + `--nft` is set the values of `total` and `decimals` are validated as a pure or + fractional NFT per the ARC3 standard. -i, --image FILE Path to the asset image file to be uploaded to IPFS. [required] -m, --metadata FILE Path to the ARC19 compliant asset metadata file to be uploaded to IPFS. If not provided, a default metadata object will be generated automatically based on asset- name, decimals and image. For more details refer to https://arc.algorand.foundation/ARCs/arc-0003#json-metadata-file-schema. - --mutable / --immutable Whether the asset should be mutable or immutable. Refers to `ARC19` by default. - --nft / --ft Whether the asset should be validated as NFT or FT. Refers to NFT by default and - validates canonical definitions of pure or fractional NFTs as per ARC3 standard. + --mutable / --immutable Whether the asset should be mutable or immutable. Refers to `ARC3` (immutable) by + default. -n, --network [localnet|testnet|mainnet] Network to use. Refers to `localnet` by default. -h, --help Show this message and exit. @@ -35,14 +37,14 @@ Options: ## Options - `--creator TEXT`: Specifies the address or alias of the asset creator. This option is required. -- `-n, --name TEXT`: Specifies the asset name. This option is required. +- `--name TEXT`: Specifies the asset name. Required either via this flag or via the interactive prompt. - `-u, --unit TEXT`: Specifies the unit name of the asset. This option is required. - `-t, --total INTEGER`: Specifies the total supply of the asset. Defaults to 1. - `-d, --decimals INTEGER`: Specifies the number of decimals. Defaults to 0. - `-i, --image PATH`: Specifies the path to the asset image file to be uploaded to IPFS. This option is required. - `-m, --metadata PATH`: Specifies the path to the ARC19 compliant asset metadata file to be uploaded to IPFS. If not provided, a default metadata object will be generated automatically based on asset-name, decimals and image. -- `--mutable / --immutable`: Specifies whether the asset should be mutable or immutable. Refers to `ARC19` by default. -- `--nft / --ft`: Specifies whether the asset should be validated as NFT or FT. Refers to NFT by default and validates canonical definitions of pure or fractional NFTs as per ARC3 standard. +- `--mutable / --immutable`: Specifies whether the asset should be mutable or immutable. Refers to `ARC3` (immutable) by default. +- `--nft / --ft`: Specifies whether the asset should be validated as NFT or FT. Refers to FT by default; when `--nft` is set the values of `total` and `decimals` are validated as a pure or fractional NFT per the ARC3 standard. - `-n, --network [localnet|testnet|mainnet]`: Specifies the network to use. Refers to `localnet` by default. ## Example diff --git a/docs/src/content/docs/features/tasks/nfd.md b/docs/src/content/docs/features/tasks/nfd.md index 5e21b8aae..748a48e25 100644 --- a/docs/src/content/docs/features/tasks/nfd.md +++ b/docs/src/content/docs/features/tasks/nfd.md @@ -40,7 +40,7 @@ This will perform a lookup and return the associated address or domain. If you w algokit task nfd-lookup {NFD_DOMAIN_OR_ALGORAND_ADDRESS} --output full ``` -If the lookup is successful, the result will be output to the console in a JSON format. +If the lookup is successful, the result will be output to the console. With the default `address` output format the resolved address or domain is printed as a plain string; with the `full` or `tiny` output formats the NFD API response is printed as indented JSON. ## Further Reading diff --git a/docs/src/content/docs/features/tasks/opt.md b/docs/src/content/docs/features/tasks/opt.md index af66e2fae..dec1a5c2c 100644 --- a/docs/src/content/docs/features/tasks/opt.md +++ b/docs/src/content/docs/features/tasks/opt.md @@ -27,7 +27,7 @@ Options: ```bash Usage: algokit task opt-out [OPTIONS] [ASSET_IDS]... - Opt-out of an asset(s). You can only opt out of an asset with a zero balance. + opt-out of an asset(s). You can only opt out of an asset with a zero balance. Use -n to specify localnet, testnet, or mainnet. To supply multiple asset IDs, separate them with a whitespace. Options: @@ -70,4 +70,4 @@ algokit task opt-out --account {YOUR_ACCOUNT} --all ## Further Reading -For in-depth details, visit the [opt-in](/algokit-cli/cli/#opt-in) and [opt-out](../../cli/index#opt-out) sections in the AlgoKit CLI reference documentation. +For in-depth details, visit the [opt-in](/algokit-cli/cli/#opt-in) and [opt-out](/algokit-cli/cli/#opt-out) sections in the AlgoKit CLI reference documentation. diff --git a/docs/src/content/docs/features/tasks/send.md b/docs/src/content/docs/features/tasks/send.md index 9a91a8461..13444bc10 100644 --- a/docs/src/content/docs/features/tasks/send.md +++ b/docs/src/content/docs/features/tasks/send.md @@ -55,7 +55,7 @@ If the transaction is successfully sent, the transaction ID (txid) will be outpu ## Goal Compatibility -Please note, at the moment this feature only supports [`goal clerk`](https://dev.algorand.co/algokit/algokit-cli/goal/) compatible transaction objects. +Please note, at the moment this feature only supports [`goal clerk`](https://developer.algorand.org/docs/clis/goal/goal/) compatible transaction objects. ## Further Reading diff --git a/docs/src/content/docs/features/tasks/sign.md b/docs/src/content/docs/features/tasks/sign.md index a334e6173..83efd1cf8 100644 --- a/docs/src/content/docs/features/tasks/sign.md +++ b/docs/src/content/docs/features/tasks/sign.md @@ -57,19 +57,19 @@ This will write the signed transaction to the specified file. ## Goal Compatibility -Please note, at the moment this feature only supports [`goal clerk`](https://dev.algorand.co/algokit/algokit-cli/goal/) compatible transaction objects. +Please note, at the moment this feature only supports [`goal clerk`](https://developer.algorand.org/docs/clis/goal/goal/) compatible transaction objects. When `--output` option is not specified, the signed transaction(s) will be output to the console in a following JSON format: ``` [ - {transaction_id: "TRANSACTION_ID", content: "BASE64_ENCODED_SIGNED_TRANSACTION"}, + {"transaction_id": "TRANSACTION_ID", "content": "BASE64_ENCODED_SIGNED_TRANSACTION"} ] ``` On the other hand, when `--output` option is specified, the signed transaction(s) will be stored to a file as a message pack encoded binary file. -### Encoding transactins for signing +### Encoding transactions for signing Algorand provides a set of options in [py-algorand-sdk](https://github.com/algorand/py-algorand-sdk) and [js-algorand-sdk](https://github.com/algorand/js-algorand-sdk) to encode transactions for signing. diff --git a/docs/src/content/docs/features/tasks/transfer.md b/docs/src/content/docs/features/tasks/transfer.md index 06e153809..fb259baa3 100644 --- a/docs/src/content/docs/features/tasks/transfer.md +++ b/docs/src/content/docs/features/tasks/transfer.md @@ -15,10 +15,10 @@ Usage: algokit task transfer [OPTIONS] Transfer algos or assets from one account to another. Options: - -s, --sender TEXT Address or alias of the sender account [required] - -r, --receiver TEXT Address or alias to an account that will receive the asset(s) [required] - --asset, --id INTEGER ASA asset id to transfer - -a, --amount INTEGER Amount to transfer [required] + -s, --sender TEXT Address or alias of the sender account. [required] + -r, --receiver TEXT Address or alias to an account that will receive the asset(s). [required] + --asset, --id INTEGER Asset ID to transfer. Defaults to 0 (Algo). + -a, --amount INTEGER Amount to transfer. [required] --whole-units Use whole units (Algos | ASAs) instead of smallest divisible units (for example, microAlgos). Disabled by default. -n, --network [localnet|testnet|mainnet] diff --git a/docs/src/content/docs/features/tasks/vanity_address.md b/docs/src/content/docs/features/tasks/vanity_address.md index 2a8ecf128..13d01e54b 100644 --- a/docs/src/content/docs/features/tasks/vanity_address.md +++ b/docs/src/content/docs/features/tasks/vanity_address.md @@ -22,8 +22,8 @@ Options: -o, --output [stdout|alias|file] How the output will be presented. -a, --alias TEXT Alias for the address. Required if output is "alias". - --file-path PATH File path where to dump the output. Required if output is "file". - -f, --force Allow overwriting an aliases without confirmation, if output option is 'alias'. + --file-path FILE File path where to dump the output. Required if output is "file". + -f, --force Allow overwriting aliases without confirmation, if output option is 'alias'. -h, --help Show this message and exit. ``` @@ -38,13 +38,13 @@ algokit task vanity-address ALGO Generate a vanity address with the keyword "ALGO" at the start of the address with output to a file: ```bash -algokit task vanity-address ALGO -o file -f vanity-address.txt +algokit task vanity-address ALGO -o file --file-path vanity-address.txt ``` Generate a vanity address with the keyword "ALGO" anywhere in the address with output to a file: ```bash -algokit task vanity-address ALGO -m anywhere -o file -f vanity-address.txt +algokit task vanity-address ALGO -m anywhere -o file --file-path vanity-address.txt ``` Generate a vanity address with the keyword "ALGO" at the start of the address and store into a [wallet alias](/algokit-cli/features/tasks/wallet/): diff --git a/docs/src/content/docs/features/tasks/wallet.md b/docs/src/content/docs/features/tasks/wallet.md index 85c2475aa..b69730328 100644 --- a/docs/src/content/docs/features/tasks/wallet.md +++ b/docs/src/content/docs/features/tasks/wallet.md @@ -32,7 +32,7 @@ reset Remove all aliases. This command adds an address or account to be stored against a named alias. If the `--mnemonic` flag is used, it will prompt the user for a mnemonic phrase interactively using masked input. If the `--force` flag is used, it will allow overwriting an existing alias. Maximum number of aliases that can be stored at a time is 50. ```bash -algokit wallet add [OPTIONS] ALIAS_NAME +algokit task wallet add [OPTIONS] ALIAS_NAME ``` > Please note, the command is not designed to be used in CI scope, there is no option to skip interactive masked input of the mnemonic, if you want to alias an `Account` (both private and public key) entity. @@ -48,7 +48,7 @@ algokit wallet add [OPTIONS] ALIAS_NAME This command retrieves an address or account stored against a named alias. ```bash -algokit wallet get ALIAS +algokit task wallet get ALIAS ``` ### List @@ -56,7 +56,7 @@ algokit wallet get ALIAS This command lists all addresses and accounts stored against a named alias. If a record contains a `private_key` it will show a boolean flag indicating whether it exists, actual private key values are never exposed. As a user you can obtain the content of the stored aliases by navigating to your dedicated password manager (see [keyring details](https://pypi.org/project/keyring/)). ```bash -algokit wallet list +algokit task wallet list ``` ### Remove @@ -65,7 +65,7 @@ This command removes an address or account stored against a named alias. You must confirm the prompt interactively or pass `--force` | `-f` flag to ignore the prompt. ```bash -algokit wallet remove ALIAS [--force | -f] +algokit task wallet remove ALIAS [--force | -f] ``` ### Reset @@ -73,7 +73,7 @@ algokit wallet remove ALIAS [--force | -f] This command removes all aliases. You must confirm the prompt interactively or pass `--force` | `-f` flag to ignore the prompt. ```bash -algokit wallet reset [--force | -f] +algokit task wallet reset [--force | -f] ``` ## Keyring diff --git a/docs/src/content/docs/tutorials/algokit-template.md b/docs/src/content/docs/tutorials/algokit-template.md index 268742f42..0e69baa8d 100644 --- a/docs/src/content/docs/tutorials/algokit-template.md +++ b/docs/src/content/docs/tutorials/algokit-template.md @@ -20,7 +20,7 @@ We will also refer to the official [`algokit-python-template`](https://github.co - [Bootstrap Option](#bootstrap-option) - [Predefined Copier Answers](#predefined-copier-answers) - [Default Behaviors](#default-behaviors) - - [Generators](#generators) + - [Generators](#working-with-generators) - [Recommendations](#recommendations) - [Conclusion](#conclusion) @@ -104,13 +104,15 @@ This example shows how Jinja syntax is used within `package.json` to allow place ### Bootstrap Option -When instantiating your template via AlgoKit CLI it will optionally prompt the user to automatically run [algokit bootstrap](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/bootstrap.md) after the project is initialized and can perform various setup tasks like installing dependencies or setting up databases. +When instantiating your template via AlgoKit CLI it will optionally prompt the user to automatically run [algokit project bootstrap](/algokit-cli/features/project/bootstrap/) after the project is initialized and can perform various setup tasks like installing dependencies or setting up environment variables. - `env`: Searches for and copies an `.env*.template` file to an equivalent `.env*` file in the current working directory, prompting for any unspecified values. This feature is integral for securely managing environment variables, as it prevents sensitive data from inadvertently ending up in version control. - By default, Algokit will scan for network-prefixed `.env` variables (e.g., `.env.localnet`), which can be particularly useful when relying on the [Algokit deploy command](https://github.com/algorandfoundation/algokit-cli/blob/deploy-command/docs/features/deploy.md). If no such prefixed files are located, Algokit will then attempt to load default `.env` files. This functionality provides greater flexibility for different network configurations. + By default, Algokit will scan for network-prefixed `.env` variables (e.g., `.env.localnet`), which can be particularly useful when relying on the [Algokit deploy command](/algokit-cli/features/project/deploy/). If no such prefixed files are located, Algokit will then attempt to load default `.env` files. This functionality provides greater flexibility for different network configurations. - `poetry`: If your Python project uses Poetry for dependency management, the `poetry` command installs Poetry (if not present) and runs `poetry install` in the current working directory to install Python dependencies. -- `npm`: If you're developing a JavaScript or TypeScript project, the `npm` command runs npm install in the current working directory to install Node.js dependencies. +- `uv`: If your Python project uses uv for dependency management, the `uv` command installs uv (if not present) and runs `uv sync` in the current working directory to install Python dependencies. +- `npm`: If you're developing a JavaScript or TypeScript project, the `npm` command runs `npm install` in the current working directory to install Node.js dependencies. +- `pnpm`: Alternatively, the `pnpm` command runs `pnpm install` in the current working directory to install Node.js dependencies. - `all`: The `all` command runs all the aforementioned bootstrap sub-commands in the current directory and its subdirectories. This command is a comprehensive way to ensure all project dependencies and environment variables are properly set up. ### Predefined Copier Answers @@ -133,11 +135,11 @@ This would prompt the user for the project name, and the input can then be used When creating an AlgoKit template, there are a few default behaviors that you can expect to be provided by algokit-cli itself without introducing any extra code to your templates: -- **Git**: If Git is installed on the user's system and the user's working directory is a Git repository, AlgoKit CLI will commit the newly created project as a new commit in the repository. This feature helps to maintain a clean version history for the project. If you wish to add a specific commit message for this action, you can specify a `commit_message` in the `_commit` option in your `copier.yaml` file. +- **Git**: If Git is installed on the user's system and the user's working directory is not already a Git repository, AlgoKit CLI will initialize a new Git repository in the project directory and create an initial commit capturing the newly generated project. This feature helps to maintain a clean version history for the project. -- **VSCode**: If the user has Visual Studio Code (VSCode) installed and the path to VSCode is added to their system's PATH, AlgoKit CLI will automatically open the newly created VSCode window unless user provides specific flags into the init command. +- **VSCode**: If the user has Visual Studio Code (VSCode) installed and the path to VSCode is added to their system's PATH, AlgoKit CLI will automatically open the newly created project in VSCode unless the user passes `--no-ide` to the init command. -- **Bootstrap**: AlgoKit CLI is equipped to execute a bootstrap script after a project has been initialized. This script, included in AlgoKit templates, can be automatically run to perform various setup tasks, such as installing dependencies or setting up databases. This is managed by AlgoKit CLI and not within the user-created codebase. By default, if a `bootstrap` task is defined in the `copier.yaml`, AlgoKit CLI will execute it, unless the user opts out during the prompt. +- **Bootstrap**: After a project has been initialized, AlgoKit CLI can run `algokit project bootstrap` on the new project to perform various setup tasks, such as installing dependencies (Poetry, uv, npm, pnpm) and populating `.env` files from `.env*.template` files. This is managed by AlgoKit CLI and not within the user-created codebase. By default, AlgoKit CLI will prompt the user to run bootstrap unless `--bootstrap`/`--no-bootstrap` or `--defaults` are provided. By combining predefined Copier answers with these default behaviors, you can create a smooth, efficient, and intuitive initialization experience for the users of your template. @@ -181,10 +183,10 @@ For example, the official [`algokit-python-template`](https://github.com/algoran Outlined below are the fundamental steps to create a generator. Although `copier` provides complete autonomy in structuring your template, you may prefer to define your generator to meet your specific needs. Nevertheless, as a starting point, we suggest: 1. Generate a new directory hierarchy within your template directory under the `.algokit/generators` folder (this is merely a suggestion, you can define your custom path if necessary and point to it via the algokit.toml file). -2. Develop a `copier.yaml` file within the generator directory and outline the generator's behavior. This file bears similarities with the root `copier.yaml` file in your template directory, but it is exclusively for the generator. The `tasks` section of the `copier.yaml` file is where you can determine the generator's behavior. Here's an example of a generator that copies the `smart-contract` directory from the template to the current working directory: +2. Develop a `copier.yaml` file within the generator directory and outline the generator's behavior. This file bears similarities with the root `copier.yaml` file in your template directory, but it is exclusively for the generator. The `_tasks` section of the `copier.yaml` file is where you can determine the generator's behavior. Here's an example of a generator that copies the `smart-contract` directory from the template to the current working directory: ```yaml -_task: +_tasks: - "echo '==== Successfully initialized new smart contract 🚀 ===='" contract_name: @@ -213,7 +215,7 @@ This should dynamically load and display your generator as an optional `cli` com - **Versioning**: Use `.algokit.toml` to specify the minimum compatible version of AlgoKit. - **Testing**: Include test configurations and scripts in your templates to encourage testing best practices. - **Linting and Formatting**: Integrate linters and code formatters in your templates to ensure code quality. -- **Algokit Principle**: for details on generic principles on designing templates refer to [algokit design principles](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md#guiding-principles). +- **Algokit Principle**: for details on generic principles on designing templates refer to [algokit design principles](/algokit-cli/features/overview/#guiding-principles). ## Conclusion diff --git a/docs/src/content/docs/tutorials/intro.md b/docs/src/content/docs/tutorials/intro.md index 9f1891f6c..c0fec2060 100644 --- a/docs/src/content/docs/tutorials/intro.md +++ b/docs/src/content/docs/tutorials/intro.md @@ -21,7 +21,7 @@ This guide presents installing AlgoKit using an OS agnostic procedure. For OS sp Before proceeding, ensure you have the following components installed: - [git](https://github.com/git-guides/install-git#install-git) -- [Docker](https://docs.docker.com/desktop/install/mac-install/) (or [Podman](https://podman.io/getting-started/installation/), see [details](/algokit-cli/features/localnet/#podman-support)) +- [Docker](https://docs.docker.com/desktop/install/mac-install/) (or [Podman](https://podman.io/docs/installation), see [details](/algokit-cli/features/localnet/#podman-support)) - [VSCode](https://code.visualstudio.com/download) ## Install AlgoKit @@ -57,7 +57,7 @@ algokit --version Output similar to the following should be displayed: ```shell -algokit, version 2.0.3 # or higher +algokit, version 2.10.2 # or higher ``` ## Start a LocalNet diff --git a/src/algokit/cli/goal.py b/src/algokit/cli/goal.py index b879acc88..b02566bee 100644 --- a/src/algokit/cli/goal.py +++ b/src/algokit/cli/goal.py @@ -39,7 +39,7 @@ def goal_command(*, console: bool, interactive: bool, goal_args: list[str]) -> N """ Run the Algorand goal CLI against the AlgoKit LocalNet. - Look at https://dev.algorand.co/algokit/algokit-cli/goal for more information. + Look at https://dev.algorand.co/algokit/cli/goal/ for more information. """ goal_args = list(goal_args) container_engine = get_container_engine() diff --git a/src/algokit/cli/tasks/mint.py b/src/algokit/cli/tasks/mint.py index 3d7837052..faec99578 100644 --- a/src/algokit/cli/tasks/mint.py +++ b/src/algokit/cli/tasks/mint.py @@ -244,8 +244,8 @@ def _validate_supply_for_nft(context: click.Context, _: click.Parameter, value: prompt="Validate asset as NFT? Checks values of `total` and `decimals` as per ARC3 if set to True.", default=False, callback=_validate_supply_for_nft, - help="""Whether the asset should be validated as NFT or FT. Refers to NFT by default and validates canonical - definitions of pure or fractional NFTs as per ARC3 standard.""", + help="""Whether the asset should be validated as NFT or FT. Refers to FT by default; when `--nft` is set + the values of `total` and `decimals` are validated as a pure or fractional NFT per the ARC3 standard.""", ) @click.option( "-i", @@ -272,7 +272,7 @@ def _validate_supply_for_nft(context: click.Context, _: click.Parameter, value: type=click.BOOL, prompt="Would you like to make the asset mutable?", default=False, - help="Whether the asset should be mutable or immutable. Refers to `ARC19` by default.", + help="Whether the asset should be mutable or immutable. Refers to `ARC3` (immutable) by default.", ) @click.option( "-n", diff --git a/src/algokit/cli/tasks/vanity_address.py b/src/algokit/cli/tasks/vanity_address.py index 8d4115377..f4772c3b2 100644 --- a/src/algokit/cli/tasks/vanity_address.py +++ b/src/algokit/cli/tasks/vanity_address.py @@ -97,7 +97,7 @@ def _store_vanity_to_alias(*, alias: str, vanity_account: VanityAccount, force: required=False, default=False, type=click.BOOL, - help="Allow overwriting an aliases without confirmation, if output option is 'alias'.", + help="Allow overwriting aliases without confirmation, if output option is 'alias'.", ) def vanity_address( # noqa: PLR0913 *, diff --git a/src/algokit/core/project/bootstrap.py b/src/algokit/core/project/bootstrap.py index 1b613665c..472149d46 100644 --- a/src/algokit/core/project/bootstrap.py +++ b/src/algokit/core/project/bootstrap.py @@ -613,7 +613,7 @@ def _maybe_migrate_poetry_project(project_dir: Path) -> None: if questionary_extensions.prompt_confirm( "Would you like to attempt to migrate the pyproject configuration to uv compliant format?\n" - "\u26a0\ufe0f This will run a third-party tool (https://mkniewallner.github.io/migrate-to-uv/) " + "\u26a0\ufe0f This will run a third-party tool (https://osprey-oss.github.io/migrate-to-uv/) " "that will attempt to convert your poetry project to uv. " "You are advised to double check the migrated file and it's recommended to run this " "in a version controlled repository to revert changes if needed.", From d448a869be8fd744a98588dfd3c6a2a90d7c788c Mon Sep 17 00:00:00 2001 From: Luca Martini Date: Fri, 5 Jun 2026 11:15:41 +0200 Subject: [PATCH 17/19] ci: trigger publish-devportal-docs on main, pin actions to SHAs and bump node to 24 --- .github/workflows/publish-devportal-docs.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish-devportal-docs.yml b/.github/workflows/publish-devportal-docs.yml index d4d3c04cb..044130f26 100644 --- a/.github/workflows/publish-devportal-docs.yml +++ b/.github/workflows/publish-devportal-docs.yml @@ -3,7 +3,7 @@ name: Publish DevPortal Docs on: workflow_dispatch: push: - branches: [ci/add-publish-to-devportal-workflow] # change to the branch you want to publish doc artifacts from + branches: [main] tags: ['v*'] permissions: @@ -13,20 +13,25 @@ jobs: publish-docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: - node-version: 22 - - uses: pnpm/action-setup@v4 + node-version: 24.x + + - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6 with: package_json_file: docs/package.json + - name: Setup Python environment uses: algorandfoundation/algokit-shared-config/.github/actions/setup-algokit-python@main with: install-algokit: "false" + - name: Generate CLI reference run: uv run poe docs-cli + - name: Publish DevPortal Docs uses: algorandfoundation/devportal/.github/actions/publish-devportal-docs@release/ak-v4 with: - docs-dir: docs \ No newline at end of file + docs-dir: docs From 4561b1286bea568cb41797061ac1166a1398c815 Mon Sep 17 00:00:00 2001 From: Luca Martini Date: Fri, 5 Jun 2026 11:25:35 +0200 Subject: [PATCH 18/19] chore: bump pyjwt to 2.13.0 to fix PYSEC-2026-175/177/178/179 --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index b573a9f28..31c8d013d 100644 --- a/uv.lock +++ b/uv.lock @@ -1974,14 +1974,14 @@ wheels = [ [[package]] name = "pyjwt" -version = "2.12.1" +version = "2.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c2/27/a3b6e5bf6ff856d2509292e95c8f57f0df7017cf5394921fc4e4ef40308a/pyjwt-2.12.1.tar.gz", hash = "sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b", size = 102564, upload-time = "2026-03-13T19:27:37.25Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl", hash = "sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c", size = 29726, upload-time = "2026-03-13T19:27:35.677Z" }, + { url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" }, ] [[package]] From 3b9a12e9c2dc249454e1e6e5e6d2157a9e98b8ac Mon Sep 17 00:00:00 2001 From: Luca Martini Date: Fri, 5 Jun 2026 11:45:28 +0200 Subject: [PATCH 19/19] test: update goal help approval snapshot for new docs url --- tests/goal/test_goal.test_goal_help.approved.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/goal/test_goal.test_goal_help.approved.txt b/tests/goal/test_goal.test_goal_help.approved.txt index c51c46d5f..b95e6ef8f 100644 --- a/tests/goal/test_goal.test_goal_help.approved.txt +++ b/tests/goal/test_goal.test_goal_help.approved.txt @@ -2,7 +2,7 @@ Usage: algokit goal [OPTIONS] [GOAL_ARGS]... Run the Algorand goal CLI against the AlgoKit LocalNet. - Look at https://dev.algorand.co/algokit/algokit-cli/goal for more information. + Look at https://dev.algorand.co/algokit/cli/goal/ for more information. Options: --console Open a Bash console so you can execute multiple goal commands