From 2ecf716f1e95e32d17d563a4ffffe208ad9570fa Mon Sep 17 00:00:00 2001 From: Jannis-Mittenzwei <145327095+Jannis-Mittenzwei@users.noreply.github.com> Date: Fri, 29 Nov 2024 12:34:08 +0100 Subject: [PATCH] add and use exasol toolbox (#78) fixes #77 --- .github/workflows/checks.yaml | 38 + .gitignore | 6 +- .pre-commit-config.yaml | 36 + doc/changes/changelog.md | 1 + doc/changes/changes_1.6.0.md | 27 + .../__init__.py | 14 +- .../cli/commands/deploy_ci_build.py | 34 +- .../cli/commands/deploy_release_build.py | 35 +- .../cli/commands/deploy_source_credentials.py | 53 +- .../cli/commands/generate_buildspec.py | 52 +- .../commands/generate_release_buildspec.py | 52 +- .../cli/commands/health.py | 12 +- .../cli/commands/start_ci_build.py | 58 +- .../cli/commands/start_release_build.py | 83 +- .../cli/commands/start_test_release_build.py | 84 +- .../cli/commands/validate_ci_build.py | 35 +- .../cli/commands/validate_release_build.py | 35 +- .../commands/validate_source_credentials.py | 52 +- .../cli/common.py | 1 - .../cli/options/aws_options.py | 5 +- .../cli/options/logging.py | 20 +- .../health_check.py | 53 +- .../lib/aws/aws_access.py | 146 +- .../lib/aws/deployer.py | 130 +- .../lib/aws/wrapper/aws_client.py | 43 +- .../lib/aws/wrapper/cloudformation_service.py | 60 +- .../lib/aws/wrapper/codebuild_service.py | 55 +- .../aws/wrapper/datamodels/cloudformation.py | 62 +- .../lib/aws/wrapper/datamodels/codebuild.py | 28 +- .../lib/aws/wrapper/datamodels/common.py | 2 + .../aws/wrapper/datamodels/secretsmanager.py | 9 +- .../lib/aws/wrapper/secretsmanager_service.py | 28 +- .../lib/ci_build.py | 39 +- .../lib/generate_buildspec_common.py | 39 +- .../lib/github_draft_release_creator.py | 16 +- .../lib/release_build.py | 32 +- .../lib/render_template.py | 7 +- .../lib/run_generate_buildspec.py | 28 +- .../lib/run_generate_release_buildspec.py | 27 +- .../lib/run_start_build.py | 163 +- .../lib/source_credentials.py | 45 +- .../main.py | 2 +- .../version.py | 10 + noxconfig.py | 26 + noxfile.py | 7 + poetry.lock | 2601 ++++++++++++----- pyproject.toml | 44 +- scripts/build/check_release.py | 10 +- test/conftest.py | 2 - .../aws_access/cloudformation_service.py | 56 +- .../aws_access/code_build_service.py | 67 +- .../aws_access/secretmanager_service.py | 13 +- .../__init__.py | 0 .../test_deploy_ci.py | 26 +- .../test_deploy_source_credentials.py | 14 +- test/mock_cast.py | 5 +- test/{unit_tests => unit}/__init__.py | 0 test/{unit_tests => unit}/aws/__init__.py | 0 .../aws/wrapper/__init__.py | 0 .../aws/wrapper/datamodels/__init__.py | 0 .../datamodels/cloudformation/__init__.py | 0 .../test_list_stack_resources_result.py | 104 +- .../test_stack_resource_summary.py | 36 +- .../cloudformation/test_validation_result.py | 9 +- .../wrapper/datamodels/codebuild/__init__.py | 0 .../datamodels/codebuild/test_build_batch.py | 53 +- .../datamodels/secretsmanager/__init__.py | 0 .../datamodels/secretsmanager/test_secret.py | 18 +- .../aws/wrapper/test_aws_client.py | 60 +- .../wrapper/test_cloudformation_service.py | 76 +- .../aws/wrapper/test_codebuild_service.py | 60 +- .../wrapper/test_secretsmanager_service.py | 23 +- .../cloudformation_validation.py | 5 +- test/unit/conftest.py | 0 .../test_aws_access_start_code_build.py | 135 +- test/{unit_tests => unit}/test_deploy_ci.py | 75 +- test/unit/test_deploy_source_credentials.py | 58 + .../test_generate_buildspec.py | 112 +- test/unit/test_start_ci_build.py | 56 + .../test_start_release_build.py | 72 +- .../test_start_test_release_build.py | 81 +- .../test_webhook_filter_pattern.py | 7 +- test/unit_tests/conftest.py | 2 - .../test_deploy_source_credentials.py | 40 - test/unit_tests/test_start_ci_build.py | 36 - 85 files changed, 3985 insertions(+), 1761 deletions(-) create mode 100644 .github/workflows/checks.yaml create mode 100644 .pre-commit-config.yaml create mode 100644 doc/changes/changes_1.6.0.md create mode 100644 exasol_script_languages_container_ci_setup/version.py create mode 100644 noxconfig.py create mode 100644 noxfile.py rename test/{integration_tests => integration}/__init__.py (100%) rename test/{integration_tests => integration}/test_deploy_ci.py (59%) rename test/{integration_tests => integration}/test_deploy_source_credentials.py (66%) rename test/{unit_tests => unit}/__init__.py (100%) rename test/{unit_tests => unit}/aws/__init__.py (100%) rename test/{unit_tests => unit}/aws/wrapper/__init__.py (100%) rename test/{unit_tests => unit}/aws/wrapper/datamodels/__init__.py (100%) rename test/{unit_tests => unit}/aws/wrapper/datamodels/cloudformation/__init__.py (100%) rename test/{unit_tests => unit}/aws/wrapper/datamodels/cloudformation/test_list_stack_resources_result.py (51%) rename test/{unit_tests => unit}/aws/wrapper/datamodels/cloudformation/test_stack_resource_summary.py (79%) rename test/{unit_tests => unit}/aws/wrapper/datamodels/cloudformation/test_validation_result.py (75%) rename test/{unit_tests => unit}/aws/wrapper/datamodels/codebuild/__init__.py (100%) rename test/{unit_tests => unit}/aws/wrapper/datamodels/codebuild/test_build_batch.py (64%) rename test/{unit_tests => unit}/aws/wrapper/datamodels/secretsmanager/__init__.py (100%) rename test/{unit_tests => unit}/aws/wrapper/datamodels/secretsmanager/test_secret.py (76%) rename test/{unit_tests => unit}/aws/wrapper/test_aws_client.py (64%) rename test/{unit_tests => unit}/aws/wrapper/test_cloudformation_service.py (58%) rename test/{unit_tests => unit}/aws/wrapper/test_codebuild_service.py (62%) rename test/{unit_tests => unit}/aws/wrapper/test_secretsmanager_service.py (78%) rename test/{unit_tests => unit}/cloudformation_validation.py (81%) create mode 100644 test/unit/conftest.py rename test/{unit_tests => unit}/test_aws_access_start_code_build.py (67%) rename test/{unit_tests => unit}/test_deploy_ci.py (55%) create mode 100644 test/unit/test_deploy_source_credentials.py rename test/{unit_tests => unit}/test_generate_buildspec.py (64%) create mode 100644 test/unit/test_start_ci_build.py rename test/{unit_tests => unit}/test_start_release_build.py (57%) rename test/{unit_tests => unit}/test_start_test_release_build.py (60%) rename test/{unit_tests => unit}/test_webhook_filter_pattern.py (94%) delete mode 100644 test/unit_tests/conftest.py delete mode 100644 test/unit_tests/test_deploy_source_credentials.py delete mode 100644 test/unit_tests/test_start_ci_build.py diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml new file mode 100644 index 0000000..467dc18 --- /dev/null +++ b/.github/workflows/checks.yaml @@ -0,0 +1,38 @@ +name: Checks + +on: + pull_request: + +jobs: + + lint-job: + name: Linting and Type checks (Python-${{ matrix.python-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12"] + + steps: + - name: SCM Checkout + uses: actions/checkout@v4 + + - name: Setup Python & Poetry Environment + uses: exasol/python-toolbox/.github/actions/python-environment@0.15.0 + with: + python-version: ${{ matrix.python-version }} + + - name: Run Unit Tests + run: poetry run nox -s test:unit + + - name: Run Lint + run: poetry run nox -s lint:code + + - name: Run type-check + run: poetry run nox -s lint:typing + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: ".lint-python-${{ matrix.python-version }}.txt" + path: .lint.txt \ No newline at end of file diff --git a/.gitignore b/.gitignore index d5974f2..e6400e0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,8 @@ .pytest_cache .gitignore dist -__pycache__ \ No newline at end of file +__pycache__.html-documentation +.lint.txt +.lint.json +.security.json +.coverage \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..017e6b8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,36 @@ +default_stages: [ commit ] +repos: + + - repo: local + hooks: + - id: code-format + name: code-format + types: [ python ] + pass_filenames: false + language: system + entry: poetry run nox -s fix + + - repo: local + hooks: + - id: type-check + name: type-check + types: [ python ] + pass_filenames: false + language: system + entry: poetry run nox -s type-check + + - repo: local + hooks: + - id: lint + name: lint + types: [ python ] + pass_filenames: false + language: system + entry: poetry run nox -s lint + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace diff --git a/doc/changes/changelog.md b/doc/changes/changelog.md index a50b179..ef73092 100644 --- a/doc/changes/changelog.md +++ b/doc/changes/changelog.md @@ -1,5 +1,6 @@ # Changes +* [1.6.0](changes_1.6.0.md) * [1.5.0](changes_1.5.0.md) * [1.4.0](changes_1.4.0.md) * [1.3.1](changes_1.3.1.md) diff --git a/doc/changes/changes_1.6.0.md b/doc/changes/changes_1.6.0.md new file mode 100644 index 0000000..505543c --- /dev/null +++ b/doc/changes/changes_1.6.0.md @@ -0,0 +1,27 @@ +# script-languages-container-ci-setup 1.6.0, tbd. + +Code name: tbd + +## Summary + +tbd + +## Bug Fixes + +n/a + +## Features / Enhancements + +n/a + +## Documentation + +n/a + +## Refactoring + +n/a + +## Dependencies + +n/a diff --git a/exasol_script_languages_container_ci_setup/__init__.py b/exasol_script_languages_container_ci_setup/__init__.py index d07550b..17ac242 100644 --- a/exasol_script_languages_container_ci_setup/__init__.py +++ b/exasol_script_languages_container_ci_setup/__init__.py @@ -1,14 +1,14 @@ from exasol_script_languages_container_ci_setup.cli.commands import ( - health, - generate_buildspec, - generate_release_buildspec, - deploy_source_credentials, deploy_ci_build, deploy_release_build, + deploy_source_credentials, + generate_buildspec, + generate_release_buildspec, + health, + start_ci_build, + start_release_build, + start_test_release_build, validate_ci_build, validate_release_build, validate_source_credentials, - start_release_build, - start_test_release_build, - start_ci_build ) diff --git a/exasol_script_languages_container_ci_setup/cli/commands/deploy_ci_build.py b/exasol_script_languages_container_ci_setup/cli/commands/deploy_ci_build.py index 4bbb0c0..0aa5659 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/deploy_ci_build.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/deploy_ci_build.py @@ -6,28 +6,38 @@ from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.logging import logging_options, set_log_level +from exasol_script_languages_container_ci_setup.cli.options.aws_options import ( + aws_options, +) +from exasol_script_languages_container_ci_setup.cli.options.logging import ( + logging_options, + set_log_level, +) from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess from exasol_script_languages_container_ci_setup.lib.ci_build import run_deploy_ci_build -from exasol_script_languages_container_ci_setup.cli.options.aws_options import aws_options @cli.command() @add_options(aws_options) @add_options(logging_options) -@click.option('--project', type=str, required=True, - help="""The project for which the stack will be created.""") -@click.option('--project-url', type=str, required=True, - help="""The URL of the project on Github.""") +@click.option( + "--project", + type=str, + required=True, + help="""The project for which the stack will be created.""", +) +@click.option( + "--project-url", + type=str, + required=True, + help="""The URL of the project on Github.""", +) def deploy_ci_build( - aws_profile: Optional[str], - log_level: str, - project: str, - project_url: str): + aws_profile: Optional[str], log_level: str, project: str, project_url: str +): set_log_level(log_level) try: - run_deploy_ci_build(AwsAccess(aws_profile), project, - project_url) + run_deploy_ci_build(AwsAccess(aws_profile), project, project_url) except Exception: logging.error("run_deploy_ci_build failed.") sys.exit(1) diff --git a/exasol_script_languages_container_ci_setup/cli/commands/deploy_release_build.py b/exasol_script_languages_container_ci_setup/cli/commands/deploy_release_build.py index da34260..56cddd1 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/deploy_release_build.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/deploy_release_build.py @@ -6,24 +6,37 @@ from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.logging import logging_options, set_log_level +from exasol_script_languages_container_ci_setup.cli.options.aws_options import ( + aws_options, +) +from exasol_script_languages_container_ci_setup.cli.options.logging import ( + logging_options, + set_log_level, +) from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.cli.options.aws_options import aws_options -from exasol_script_languages_container_ci_setup.lib.release_build import run_deploy_release_build +from exasol_script_languages_container_ci_setup.lib.release_build import ( + run_deploy_release_build, +) @cli.command() @add_options(aws_options) @add_options(logging_options) -@click.option('--project', type=str, required=True, - help="""The project for which the stack will be created.""") -@click.option('--project-url', type=str, required=True, - help="""The URL of the project on Github.""") +@click.option( + "--project", + type=str, + required=True, + help="""The project for which the stack will be created.""", +) +@click.option( + "--project-url", + type=str, + required=True, + help="""The URL of the project on Github.""", +) def deploy_release_build( - aws_profile: Optional[str], - log_level: str, - project: str, - project_url: str): + aws_profile: Optional[str], log_level: str, project: str, project_url: str +): set_log_level(log_level) try: run_deploy_release_build(AwsAccess(aws_profile), project, project_url) diff --git a/exasol_script_languages_container_ci_setup/cli/commands/deploy_source_credentials.py b/exasol_script_languages_container_ci_setup/cli/commands/deploy_source_credentials.py index faec467..ada2cf7 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/deploy_source_credentials.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/deploy_source_credentials.py @@ -6,31 +6,52 @@ from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.logging import logging_options, set_log_level +from exasol_script_languages_container_ci_setup.cli.options.aws_options import ( + aws_options, +) +from exasol_script_languages_container_ci_setup.cli.options.logging import ( + logging_options, + set_log_level, +) from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.source_credentials import run_deploy_source_credentials -from exasol_script_languages_container_ci_setup.cli.options.aws_options import aws_options +from exasol_script_languages_container_ci_setup.lib.source_credentials import ( + run_deploy_source_credentials, +) @cli.command() @add_options(aws_options) @add_options(logging_options) -@click.option('--secret-name', required=True, type=str, - help="Secret stored in AWS Secret Manager.") -@click.option('--secret-user-key', required=True, type=str, - help="User key stored as secret in AWS Secret Manager.") -@click.option('--secret-token-key', required=True, type=str, - help="Token key stored as secret in AWS Secret Manager.") +@click.option( + "--secret-name", + required=True, + type=str, + help="Secret stored in AWS Secret Manager.", +) +@click.option( + "--secret-user-key", + required=True, + type=str, + help="User key stored as secret in AWS Secret Manager.", +) +@click.option( + "--secret-token-key", + required=True, + type=str, + help="Token key stored as secret in AWS Secret Manager.", +) def deploy_source_credentials( - aws_profile: Optional[str], - log_level: str, - secret_name: str, - secret_user_key: str, - secret_token_key: str): + aws_profile: Optional[str], + log_level: str, + secret_name: str, + secret_user_key: str, + secret_token_key: str, +): set_log_level(log_level) try: - run_deploy_source_credentials(AwsAccess(aws_profile), secret_name, secret_user_key, secret_token_key) + run_deploy_source_credentials( + AwsAccess(aws_profile), secret_name, secret_user_key, secret_token_key + ) except Exception: logging.error("deploy_source_credentials failed.") sys.exit(1) - diff --git a/exasol_script_languages_container_ci_setup/cli/commands/generate_buildspec.py b/exasol_script_languages_container_ci_setup/cli/commands/generate_buildspec.py index e22e927..7a4180a 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/generate_buildspec.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/generate_buildspec.py @@ -1,33 +1,51 @@ from pathlib import Path -from typing import Tuple, Optional +from typing import ( + Optional, + Tuple, +) import click from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.logging import logging_options, set_log_level -from exasol_script_languages_container_ci_setup.lib.run_generate_buildspec import run_generate_buildspec +from exasol_script_languages_container_ci_setup.cli.options.logging import ( + logging_options, + set_log_level, +) +from exasol_script_languages_container_ci_setup.lib.run_generate_buildspec import ( + run_generate_buildspec, +) @cli.command() @add_options(logging_options) -@click.option('--flavor-root-path', required=True, multiple=True, - type=click.Path(file_okay=False, dir_okay=True, exists=True), - help="Path where script language container flavors are located.") -@click.option('--output-path', type=click.Path(file_okay=False, dir_okay=True, exists=True, writable=True), - default="./aws-code-build/ci", show_default=True, - help="Path where buildspec files will be deployed.") -@click.option('--config-file', type=click.Path(file_okay=True, dir_okay=False, exists=True), - help="Configuration file for build (project specific).") +@click.option( + "--flavor-root-path", + required=True, + multiple=True, + type=click.Path(file_okay=False, dir_okay=True, exists=True), + help="Path where script language container flavors are located.", +) +@click.option( + "--output-path", + type=click.Path(file_okay=False, dir_okay=True, exists=True, writable=True), + default="./aws-code-build/ci", + show_default=True, + help="Path where buildspec files will be deployed.", +) +@click.option( + "--config-file", + type=click.Path(file_okay=True, dir_okay=False, exists=True), + help="Configuration file for build (project specific).", +) def generate_buildspecs( - flavor_root_path: Tuple[str, ...], - log_level: str, - output_path: str, - config_file: Optional[str] - ): + flavor_root_path: Tuple[str, ...], + log_level: str, + output_path: str, + config_file: Optional[str], +): """ This command generates the buildspec file(s) for AWS CodeBuild based on the flavors located in path "flavor_root_path". """ set_log_level(log_level) run_generate_buildspec(flavor_root_path, output_path, config_file) - diff --git a/exasol_script_languages_container_ci_setup/cli/commands/generate_release_buildspec.py b/exasol_script_languages_container_ci_setup/cli/commands/generate_release_buildspec.py index 65212a6..cf106aa 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/generate_release_buildspec.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/generate_release_buildspec.py @@ -1,33 +1,51 @@ -from typing import Tuple, Optional +from typing import ( + Optional, + Tuple, +) import click from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.logging import logging_options, set_log_level -from exasol_script_languages_container_ci_setup.lib.run_generate_release_buildspec import run_generate_release_buildspec +from exasol_script_languages_container_ci_setup.cli.options.logging import ( + logging_options, + set_log_level, +) +from exasol_script_languages_container_ci_setup.lib.run_generate_release_buildspec import ( + run_generate_release_buildspec, +) @cli.command() @add_options(logging_options) -@click.option('--flavor-root-path', required=True, multiple=True, - type=click.Path(file_okay=False, dir_okay=True, exists=True), - help="Path where script language container flavors are located.") -@click.option('--output-path', type=click.Path(file_okay=False, dir_okay=True, exists=True, writable=True), - default="./aws-code-build/release", show_default=True, - help="Path where buildspec files will be deployed.") -@click.option('--config-file', type=click.Path(file_okay=True, dir_okay=False, exists=True), - help="Configuration file for build (project specific).") +@click.option( + "--flavor-root-path", + required=True, + multiple=True, + type=click.Path(file_okay=False, dir_okay=True, exists=True), + help="Path where script language container flavors are located.", +) +@click.option( + "--output-path", + type=click.Path(file_okay=False, dir_okay=True, exists=True, writable=True), + default="./aws-code-build/release", + show_default=True, + help="Path where buildspec files will be deployed.", +) +@click.option( + "--config-file", + type=click.Path(file_okay=True, dir_okay=False, exists=True), + help="Configuration file for build (project specific).", +) def generate_release_buildspecs( - flavor_root_path: Tuple[str, ...], - log_level: str, - output_path: str, - config_file: Optional[str] - ): + flavor_root_path: Tuple[str, ...], + log_level: str, + output_path: str, + config_file: Optional[str], +): """ This command generates the buildspec file(s) for the AWS CodeBuild Release build based on the flavors located in path "flavor_root_path". """ set_log_level(log_level) run_generate_release_buildspec(flavor_root_path, output_path, config_file) - diff --git a/exasol_script_languages_container_ci_setup/cli/commands/health.py b/exasol_script_languages_container_ci_setup/cli/commands/health.py index 51f0f82..145c9e9 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/health.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/health.py @@ -3,10 +3,10 @@ from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.aws_options import aws_options -from exasol_script_languages_container_ci_setup.health_check import ( - health_checkup, +from exasol_script_languages_container_ci_setup.cli.options.aws_options import ( + aws_options, ) +from exasol_script_languages_container_ci_setup.health_check import health_checkup @cli.command() @@ -34,11 +34,7 @@ def health(aws_profile: str): """ ).format( count=len(problems), - problems="\n".join( - ( - str(p) for p in problems - ) - ), + problems="\n".join(str(p) for p in problems), ) print(message) sys.exit(failure) diff --git a/exasol_script_languages_container_ci_setup/cli/commands/start_ci_build.py b/exasol_script_languages_container_ci_setup/cli/commands/start_ci_build.py index b6caed2..3c2cbdd 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/start_ci_build.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/start_ci_build.py @@ -4,33 +4,55 @@ from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.logging import logging_options, set_log_level +from exasol_script_languages_container_ci_setup.cli.options.aws_options import ( + aws_options, +) +from exasol_script_languages_container_ci_setup.cli.options.logging import ( + logging_options, + set_log_level, +) from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.cli.options.aws_options import aws_options -from exasol_script_languages_container_ci_setup.lib.run_start_build import run_start_ci_build +from exasol_script_languages_container_ci_setup.lib.run_start_build import ( + run_start_ci_build, +) @cli.command() @add_options(aws_options) @add_options(logging_options) -@click.option('--project', type=str, required=True, - help="""The project name. Must be same name as used for the AWS CodeBuild release stack creation.""") -@click.option('--branch', type=str, required=True, - help="""The branch of the repository which will be used(e.g. refs/heads/master).""") -@click.option('--timeout-in-seconds', type=int, required=False, default=180, - help="""Time we wait for the build to finish.""") +@click.option( + "--project", + type=str, + required=True, + help="""The project name. Must be same name as used for the AWS CodeBuild release stack creation.""", +) +@click.option( + "--branch", + type=str, + required=True, + help="""The branch of the repository which will be used(e.g. refs/heads/master).""", +) +@click.option( + "--timeout-in-seconds", + type=int, + required=False, + default=180, + help="""Time we wait for the build to finish.""", +) def start_ci_build( - aws_profile: Optional[str], - log_level: str, - project: str, - branch: str, - timeout_in_seconds: int + aws_profile: Optional[str], + log_level: str, + project: str, + branch: str, + timeout_in_seconds: int, ): """ This command can be used to trigger the AWS CI CodeBuild locally (not by Github Webhook). """ set_log_level(log_level) - run_start_ci_build(aws_access=AwsAccess(aws_profile), - project=project, - branch=branch, - timeout_in_seconds=timeout_in_seconds) + run_start_ci_build( + aws_access=AwsAccess(aws_profile), + project=project, + branch=branch, + timeout_in_seconds=timeout_in_seconds, + ) diff --git a/exasol_script_languages_container_ci_setup/cli/commands/start_release_build.py b/exasol_script_languages_container_ci_setup/cli/commands/start_release_build.py index e9a5eb2..9a2d9d8 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/start_release_build.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/start_release_build.py @@ -5,43 +5,72 @@ from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.aws_options import aws_options -from exasol_script_languages_container_ci_setup.cli.options.logging import logging_options, set_log_level +from exasol_script_languages_container_ci_setup.cli.options.aws_options import ( + aws_options, +) +from exasol_script_languages_container_ci_setup.cli.options.logging import ( + logging_options, + set_log_level, +) from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.run_start_build import run_start_release_build +from exasol_script_languages_container_ci_setup.lib.run_start_build import ( + run_start_release_build, +) @cli.command() @add_options(aws_options) @add_options(logging_options) -@click.option('--project', type=str, required=True, - help="""The project name. Must be same name as used for the AWS CodeBuild release stack creation.""") -@click.option('--upload-url', type=str, required=False, - help="""The URL of the Github release where artifacts will be stored.""") -@click.option('--branch', type=str, required=True, - help="""The branch of the repository which will be used.""") -@click.option('--timeout-in-seconds', type=int, required=False, - help="""Time to wait for the release, anymore.""") -@click.option('--config-file', type=click.Path(file_okay=True, dir_okay=False, exists=True), required=False, - help="Configuration file for build (project specific).") +@click.option( + "--project", + type=str, + required=True, + help="""The project name. Must be same name as used for the AWS CodeBuild release stack creation.""", +) +@click.option( + "--upload-url", + type=str, + required=False, + help="""The URL of the Github release where artifacts will be stored.""", +) +@click.option( + "--branch", + type=str, + required=True, + help="""The branch of the repository which will be used.""", +) +@click.option( + "--timeout-in-seconds", + type=int, + required=False, + help="""Time to wait for the release, anymore.""", +) +@click.option( + "--config-file", + type=click.Path(file_okay=True, dir_okay=False, exists=True), + required=False, + help="Configuration file for build (project specific).", +) def start_release_build( - aws_profile: Optional[str], - log_level: str, - project: str, - upload_url: str, - branch: str, - timeout_in_seconds: Optional[int], - config_file: Optional[str] + aws_profile: Optional[str], + log_level: str, + project: str, + upload_url: str, + branch: str, + timeout_in_seconds: Optional[int], + config_file: Optional[str], ): """ This command triggers the AWS release Codebuild to upload the release artifacts onto the given Github release, indicated by parameter 'upload_url'. """ set_log_level(log_level) - run_start_release_build(aws_access=AwsAccess(aws_profile), - project=project, - upload_url=upload_url, - branch=branch, - gh_token=os.getenv("GITHUB_TOKEN"), - timeout_in_seconds=timeout_in_seconds, - config_file_path=config_file) + run_start_release_build( + aws_access=AwsAccess(aws_profile), + project=project, + upload_url=upload_url, + branch=branch, + gh_token=os.getenv("GITHUB_TOKEN"), + timeout_in_seconds=timeout_in_seconds, + config_file_path=config_file, + ) diff --git a/exasol_script_languages_container_ci_setup/cli/commands/start_test_release_build.py b/exasol_script_languages_container_ci_setup/cli/commands/start_test_release_build.py index b16c8a7..14641bd 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/start_test_release_build.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/start_test_release_build.py @@ -5,38 +5,70 @@ from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.aws_options import aws_options -from exasol_script_languages_container_ci_setup.cli.options.logging import logging_options, set_log_level +from exasol_script_languages_container_ci_setup.cli.options.aws_options import ( + aws_options, +) +from exasol_script_languages_container_ci_setup.cli.options.logging import ( + logging_options, + set_log_level, +) from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.github_draft_release_creator import GithubDraftReleaseCreator -from exasol_script_languages_container_ci_setup.lib.run_start_build import run_start_test_release_build +from exasol_script_languages_container_ci_setup.lib.github_draft_release_creator import ( + GithubDraftReleaseCreator, +) +from exasol_script_languages_container_ci_setup.lib.run_start_build import ( + run_start_test_release_build, +) @cli.command() @add_options(aws_options) @add_options(logging_options) -@click.option('--project', type=str, required=True, - help="""The project name. Must be same name as used for the AWS CodeBuild release stack creation.""") -@click.option('--repo-name', type=str, required=True, - help="""The repository for which the test release should be created. - For example 'exasol/script-languages'.""", ) -@click.option('--branch', type=str, required=True, - help="""The branch for which the test release should be created.""") -@click.option('--release-title', type=str, required=True, - help="""The title of the Github draft release which will be created.""") -@click.option('--timeout-in-seconds', type=int, required=False, - help="""Time to wait for the release, anymore.""") -@click.option('--config-file', type=click.Path(file_okay=True, dir_okay=False, exists=True), - help="Configuration file for build (project specific).") +@click.option( + "--project", + type=str, + required=True, + help="""The project name. Must be same name as used for the AWS CodeBuild release stack creation.""", +) +@click.option( + "--repo-name", + type=str, + required=True, + help="""The repository for which the test release should be created. + For example 'exasol/script-languages'.""", +) +@click.option( + "--branch", + type=str, + required=True, + help="""The branch for which the test release should be created.""", +) +@click.option( + "--release-title", + type=str, + required=True, + help="""The title of the Github draft release which will be created.""", +) +@click.option( + "--timeout-in-seconds", + type=int, + required=False, + help="""Time to wait for the release, anymore.""", +) +@click.option( + "--config-file", + type=click.Path(file_okay=True, dir_okay=False, exists=True), + help="Configuration file for build (project specific).", +) def start_test_release_build( - aws_profile: Optional[str], - log_level: str, - repo_name: str, - project: str, - branch: str, - release_title: str, - timeout_in_seconds: Optional[str], - config_file: Optional[str] + aws_profile: Optional[str], + log_level: str, + repo_name: str, + project: str, + branch: str, + release_title: str, + timeout_in_seconds: Optional[str], + config_file: Optional[str], ): """ This command creates a release draft on Github and triggers the AWS release Codebuild to upload the @@ -52,5 +84,5 @@ def start_test_release_build( release_title=release_title, gh_token=os.getenv("GITHUB_TOKEN"), timeout_in_seconds=timeout_in_seconds, - config_file_path=config_file + config_file_path=config_file, ) diff --git a/exasol_script_languages_container_ci_setup/cli/commands/validate_ci_build.py b/exasol_script_languages_container_ci_setup/cli/commands/validate_ci_build.py index 3b2f17e..e958321 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/validate_ci_build.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/validate_ci_build.py @@ -4,23 +4,36 @@ from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.logging import logging_options, set_log_level +from exasol_script_languages_container_ci_setup.cli.options.aws_options import ( + aws_options, +) +from exasol_script_languages_container_ci_setup.cli.options.logging import ( + logging_options, + set_log_level, +) from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.ci_build import run_validate_ci_build -from exasol_script_languages_container_ci_setup.cli.options.aws_options import aws_options +from exasol_script_languages_container_ci_setup.lib.ci_build import ( + run_validate_ci_build, +) @cli.command() @add_options(aws_options) @add_options(logging_options) -@click.option('--project', type=str, required=True, - help="""The project for which the stack will be created.""") -@click.option('--project-url', type=str, required=True, - help="""The URL of the project on Github.""") +@click.option( + "--project", + type=str, + required=True, + help="""The project for which the stack will be created.""", +) +@click.option( + "--project-url", + type=str, + required=True, + help="""The URL of the project on Github.""", +) def validate_ci_build( - aws_profile: Optional[str], - log_level: str, - project: str, - project_url: str): + aws_profile: Optional[str], log_level: str, project: str, project_url: str +): set_log_level(log_level) run_validate_ci_build(AwsAccess(aws_profile), project, project_url) diff --git a/exasol_script_languages_container_ci_setup/cli/commands/validate_release_build.py b/exasol_script_languages_container_ci_setup/cli/commands/validate_release_build.py index f7320bf..8e4ad23 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/validate_release_build.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/validate_release_build.py @@ -4,23 +4,36 @@ from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.logging import logging_options, set_log_level +from exasol_script_languages_container_ci_setup.cli.options.aws_options import ( + aws_options, +) +from exasol_script_languages_container_ci_setup.cli.options.logging import ( + logging_options, + set_log_level, +) from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.cli.options.aws_options import aws_options -from exasol_script_languages_container_ci_setup.lib.release_build import run_validate_release_build +from exasol_script_languages_container_ci_setup.lib.release_build import ( + run_validate_release_build, +) @cli.command() @add_options(aws_options) @add_options(logging_options) -@click.option('--project', type=str, required=True, - help="""The project for which the stack will be created.""") -@click.option('--project-url', type=str, required=True, - help="""The URL of the project on Github.""") +@click.option( + "--project", + type=str, + required=True, + help="""The project for which the stack will be created.""", +) +@click.option( + "--project-url", + type=str, + required=True, + help="""The URL of the project on Github.""", +) def validate_release_build( - aws_profile: Optional[str], - log_level: str, - project: str, - project_url: str): + aws_profile: Optional[str], log_level: str, project: str, project_url: str +): set_log_level(log_level) run_validate_release_build(AwsAccess(aws_profile), project, project_url) diff --git a/exasol_script_languages_container_ci_setup/cli/commands/validate_source_credentials.py b/exasol_script_languages_container_ci_setup/cli/commands/validate_source_credentials.py index 95d8775..fdfc1b8 100644 --- a/exasol_script_languages_container_ci_setup/cli/commands/validate_source_credentials.py +++ b/exasol_script_languages_container_ci_setup/cli/commands/validate_source_credentials.py @@ -4,26 +4,48 @@ from exasol_script_languages_container_ci_setup.cli.cli import cli from exasol_script_languages_container_ci_setup.cli.common import add_options -from exasol_script_languages_container_ci_setup.cli.options.logging import logging_options, set_log_level +from exasol_script_languages_container_ci_setup.cli.options.aws_options import ( + aws_options, +) +from exasol_script_languages_container_ci_setup.cli.options.logging import ( + logging_options, + set_log_level, +) from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.source_credentials import run_validate_source_credentials -from exasol_script_languages_container_ci_setup.cli.options.aws_options import aws_options +from exasol_script_languages_container_ci_setup.lib.source_credentials import ( + run_validate_source_credentials, +) @cli.command() @add_options(aws_options) @add_options(logging_options) -@click.option('--secret-name', required=True, type=str, - help="Secret name for the Github user credentials stored in AWS Secret Manager.") -@click.option('--secret-user-key', required=True, type=str, - help="Github user key stored as secret in AWS Secret Manager under the respective secret name.") -@click.option('--secret-token-key', required=True, type=str, - help="Github user token key stored as secret in AWS Secret Manager under the respective secret name.") +@click.option( + "--secret-name", + required=True, + type=str, + help="Secret name for the Github user credentials stored in AWS Secret Manager.", +) +@click.option( + "--secret-user-key", + required=True, + type=str, + help="Github user key stored as secret in AWS Secret Manager under the respective secret name.", +) +@click.option( + "--secret-token-key", + required=True, + type=str, + help="Github user token key stored as secret in AWS Secret Manager under the respective secret name.", +) def validate_source_credentials( - aws_profile: Optional[str], - log_level: str, - secret_name: str, - secret_user_key: str, - secret_token_key: str): + aws_profile: Optional[str], + log_level: str, + secret_name: str, + secret_user_key: str, + secret_token_key: str, +): set_log_level(log_level) - run_validate_source_credentials(AwsAccess(aws_profile), secret_name, secret_user_key, secret_token_key) + run_validate_source_credentials( + AwsAccess(aws_profile), secret_name, secret_user_key, secret_token_key + ) diff --git a/exasol_script_languages_container_ci_setup/cli/common.py b/exasol_script_languages_container_ci_setup/cli/common.py index 28287d1..abbef7c 100644 --- a/exasol_script_languages_container_ci_setup/cli/common.py +++ b/exasol_script_languages_container_ci_setup/cli/common.py @@ -1,4 +1,3 @@ - def add_options(options): def _add_options(func): for option in reversed(options): diff --git a/exasol_script_languages_container_ci_setup/cli/options/aws_options.py b/exasol_script_languages_container_ci_setup/cli/options/aws_options.py index b760ea4..eb403fb 100644 --- a/exasol_script_languages_container_ci_setup/cli/options/aws_options.py +++ b/exasol_script_languages_container_ci_setup/cli/options/aws_options.py @@ -1,6 +1,7 @@ import click aws_options = [ - click.option('--aws-profile', required=False, type=str, - help="Id of the AWS profile to use."), + click.option( + "--aws-profile", required=False, type=str, help="Id of the AWS profile to use." + ), ] diff --git a/exasol_script_languages_container_ci_setup/cli/options/logging.py b/exasol_script_languages_container_ci_setup/cli/options/logging.py index 407e6cb..ffabfdc 100644 --- a/exasol_script_languages_container_ci_setup/cli/options/logging.py +++ b/exasol_script_languages_container_ci_setup/cli/options/logging.py @@ -2,14 +2,22 @@ import click -SUPPORTED_LOG_LEVELS = {"normal": logging.WARNING, "info": logging.INFO, "debug": logging.DEBUG} +SUPPORTED_LOG_LEVELS = { + "normal": logging.WARNING, + "info": logging.INFO, + "debug": logging.DEBUG, +} logging_options = [ - click.option('--log-level', type=click.Choice(list(SUPPORTED_LOG_LEVELS.keys())), default="normal", - show_default=True, - help="Level of information printed out. " - "'Normal' prints only necessary information. " - "'Info' prints also internal status info. 'Debug' prints detailed information."), + click.option( + "--log-level", + type=click.Choice(list(SUPPORTED_LOG_LEVELS.keys())), + default="normal", + show_default=True, + help="Level of information printed out. " + "'Normal' prints only necessary information. " + "'Info' prints also internal status info. 'Debug' prints detailed information.", + ), ] diff --git a/exasol_script_languages_container_ci_setup/health_check.py b/exasol_script_languages_container_ci_setup/health_check.py index f3d0740..909b982 100644 --- a/exasol_script_languages_container_ci_setup/health_check.py +++ b/exasol_script_languages_container_ci_setup/health_check.py @@ -2,10 +2,14 @@ The health check module provides functionality to check the health of the `slc-ci-setup` package and also provide help to find potential fixes. """ + import shlex import subprocess import sys -from typing import Iterator, Optional +from typing import ( + Iterator, + Optional, +) from exasol_error_reporting_python.error_message_builder import ErrorMessageBuilder from exasol_error_reporting_python.exa_error import ExaError @@ -15,7 +19,7 @@ def check_shell_cmd(cmd: str) -> bool: """ - Runs a shell command and returns True if exit code was 0, False otherwise + Runs a shell command and returns True if exit code was 0, False otherwise :param cmd: shell command to execute :return: returns True if exit code was 0, False otherwise """ @@ -28,37 +32,56 @@ def is_supported_platform(**kwargs) -> Optional[ErrorMessageBuilder]: Checks weather or not the current platform is supported. """ if sys.platform not in SUPPORTED_PLATFORMS: - return ExaError.message_builder('E-SLCCS-02') \ - .message("The platform you are running on is not supported.") \ - .mitigation("Make sure you are using one of the following platforms: {SUPPORTED_PLATFORMS}.") + return ( + ExaError.message_builder("E-SLCCS-02") + .message("The platform you are running on is not supported.") + .mitigation( + "Make sure you are using one of the following platforms: {SUPPORTED_PLATFORMS}." + ) + ) def aws_cli_available(**kwargs) -> Optional[ErrorMessageBuilder]: """Checks weather AWS cli is installed""" command = "aws --help" if not check_shell_cmd(command): - return ExaError.message_builder('E-SLCCS-03').message("AWS CLI not installed.") \ - .mitigation("Install AWS CLI. " - "Goto https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html") + return ( + ExaError.message_builder("E-SLCCS-03") + .message("AWS CLI not installed.") + .mitigation( + "Install AWS CLI. " + "Goto https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html" + ) + ) def aws_profile_valid(aws_profile: str) -> Optional[ErrorMessageBuilder]: """Checks weather the given AWS profile is configured properly.""" command = f"aws --profile {aws_profile} configure list" if not check_shell_cmd(command): - return ExaError.message_builder('E-SLCCS-04').message("AWS Profile invalid.") \ - .mitigation("Run 'aws configure --profile $your_profile' or " - "'aws configure' to configure the default profile.") + return ( + ExaError.message_builder("E-SLCCS-04") + .message("AWS Profile invalid.") + .mitigation( + "Run 'aws configure --profile $your_profile' or " + "'aws configure' to configure the default profile." + ) + ) def aws_access_key_valid(aws_profile: str) -> Optional[ErrorMessageBuilder]: """Checks weather AWS access key is configured for the given AWS profile.""" command = f"aws --profile {aws_profile} iam list-access-keys" if not check_shell_cmd(command): - return ExaError.message_builder('E-SLCCS-05').message("AWS Access Key invalid.") \ - .mitigation("Go to the AWS console and create an access key for your user. " - "Then register the access key with 'aws configure --profile $your_profile' or " - "'aws configure' for the default profile.") + return ( + ExaError.message_builder("E-SLCCS-05") + .message("AWS Access Key invalid.") + .mitigation( + "Go to the AWS console and create an access key for your user. " + "Then register the access key with 'aws configure --profile $your_profile' or " + "'aws configure' for the default profile." + ) + ) def health_checkup(**kwargs) -> Iterator[ErrorMessageBuilder]: diff --git a/exasol_script_languages_container_ci_setup/lib/aws/aws_access.py b/exasol_script_languages_container_ci_setup/lib/aws/aws_access.py index 3e160c1..72a3f38 100644 --- a/exasol_script_languages_container_ci_setup/lib/aws/aws_access.py +++ b/exasol_script_languages_container_ci_setup/lib/aws/aws_access.py @@ -1,22 +1,44 @@ import logging import time -from typing import Optional, List, Dict, Iterable, Callable +from typing import ( + Callable, + Dict, + Iterable, + List, + Optional, +) from botocore.exceptions import ClientError from exasol_script_languages_container_ci_setup.lib.aws.deployer import Deployer -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.aws_client import AwsClientFactory, AwsClient -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import StackResourceSummary -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.codebuild import BuildBatchStatus -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId - -BUILD_STATUS_FAILURES = [BuildBatchStatus.FAILED, BuildBatchStatus.FAULT, - BuildBatchStatus.STOPPED, BuildBatchStatus.TIMED_OUT] +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.aws_client import ( + AwsClient, + AwsClientFactory, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ( + StackResourceSummary, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.codebuild import ( + BuildBatchStatus, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) + +BUILD_STATUS_FAILURES = [ + BuildBatchStatus.FAILED, + BuildBatchStatus.FAULT, + BuildBatchStatus.STOPPED, + BuildBatchStatus.TIMED_OUT, +] class AwsAccess: - def __init__(self, aws_profile: Optional[str], - aws_client_factory: AwsClientFactory = AwsClientFactory()): + def __init__( + self, + aws_profile: Optional[str], + aws_client_factory: AwsClientFactory = AwsClientFactory(), + ): self._aws_client_factory = aws_client_factory self._aws_profile = aws_profile @@ -38,31 +60,48 @@ def upload_cloudformation_stack(self, yml: str, stack_name: str): """ Deploy the cloudformation stack. """ - logging.debug(f"Running upload_cloudformation_stack for aws profile {self.aws_profile_for_logging}") + logging.debug( + f"Running upload_cloudformation_stack for aws profile {self.aws_profile_for_logging}" + ) client = self._get_aws_client().create_cloudformation_service() try: cfn_deployer = Deployer(cloudformation_client=client.internal_aws_client) - result = cfn_deployer.create_and_wait_for_changeset(stack_name=stack_name, cfn_template=yml, - parameter_values=[], - capabilities=("CAPABILITY_IAM",), role_arn=None, - notification_arns=None, tags=tuple()) + result = cfn_deployer.create_and_wait_for_changeset( + stack_name=stack_name, + cfn_template=yml, + parameter_values=[], + capabilities=("CAPABILITY_IAM",), + role_arn=None, + notification_arns=None, + tags=tuple(), + ) except Exception as e: logging.error(f"Error creating changeset for cloud formation template: {e}") raise e try: - cfn_deployer.execute_changeset(changeset_id=result.changeset_id, stack_name=stack_name) - cfn_deployer.wait_for_execute(stack_name=stack_name, changeset_type=result.changeset_type) + cfn_deployer.execute_changeset( + changeset_id=result.changeset_id, stack_name=stack_name + ) + cfn_deployer.wait_for_execute( + stack_name=stack_name, changeset_type=result.changeset_type + ) except Exception as e: - logging.error(f"Error executing changeset for cloud formation template: {e}") - logging.error(f"Run 'aws cloudformation describe-stack-events --stack-name {stack_name}' to get details.") + logging.error( + f"Error executing changeset for cloud formation template: {e}" + ) + logging.error( + f"Run 'aws cloudformation describe-stack-events --stack-name {stack_name}' to get details." + ) raise e def read_secret_arn(self, secret_name: str): - """" + """ Uses Boto3 to retrieve the ARN of a secret. """ - logging.debug(f"Reading secret for getting ARN, secret name = {secret_name}, " - f"for aws profile {self.aws_profile_for_logging}") + logging.debug( + f"Reading secret for getting ARN, secret name = {secret_name}, " + f"for aws profile {self.aws_profile_for_logging}" + ) client = self._get_aws_client().create_secretsmanager_service() try: @@ -82,7 +121,9 @@ def validate_cloudformation_template(self, cloudformation_yml) -> None: Pitfall: Boto3 expects the YAML string as parameter, whereas the AWS CLI expects the file URL as parameter. It requires to have the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY env variables set correctly. """ - logging.debug(f"Running validate_cloudformation_template for aws profile {self.aws_profile_for_logging}") + logging.debug( + f"Running validate_cloudformation_template for aws profile {self.aws_profile_for_logging}" + ) client = self._get_aws_client().create_cloudformation_service() client.validate_template(template_body=cloudformation_yml) @@ -93,24 +134,30 @@ def get_all_stack_resources(self, stack_name: str) -> List[StackResourceSummary] The AWS API truncates at a size of 1MB, and in order to get all chunks the method must be called passing the previous retrieved token until no token is returned. """ - logging.debug(f"Running get_all_codebuild_projects for aws profile {self.aws_profile_for_logging}") + logging.debug( + f"Running get_all_codebuild_projects for aws profile {self.aws_profile_for_logging}" + ) client = self._get_aws_client().create_cloudformation_service() stack_name_id = PhysicalResourceId(stack_name) current_result = client.list_stack_resources(stack_name=stack_name_id) result = current_result.stack_resource_summaries while current_result.next_token is not None: - current_result = client.list_stack_resources(stack_name=stack_name_id, next_token=current_result.next_token) + current_result = client.list_stack_resources( + stack_name=stack_name_id, next_token=current_result.next_token + ) result.extend(current_result.stack_resource_summaries) return result - def start_codebuild(self, - project: PhysicalResourceId, - environment_variables_overrides: List[Dict[str, str]], - branch: str, - timeout_in_seconds: int, - poll_interval_seconds: int = 30, - sleep_function: Callable[[float], None] = time.sleep) -> None: + def start_codebuild( + self, + project: PhysicalResourceId, + environment_variables_overrides: List[Dict[str, str]], + branch: str, + timeout_in_seconds: int, + poll_interval_seconds: int = 30, + sleep_function: Callable[[float], None] = time.sleep, + ) -> None: """ This functions uses Boto3 to start a batch build. It forwards all variables from parameter env_variables as environment variables to the CodeBuild project. @@ -120,32 +167,45 @@ def start_codebuild(self, `RuntimeError` if build fails or AWS Batch build returns unknown status """ client = self._get_aws_client().create_codebuild_service() - logging.info(f"Trigger codebuild for project {project} with branch {branch} " - f"and env_variables ({environment_variables_overrides})") - build_batch = client.start_build_batch(project_name=project, - source_version=branch, - environment_variables_override=list( - environment_variables_overrides)) + logging.info( + f"Trigger codebuild for project {project} with branch {branch} " + f"and env_variables ({environment_variables_overrides})" + ) + build_batch = client.start_build_batch( + project_name=project, + source_version=branch, + environment_variables_override=list(environment_variables_overrides), + ) def wait_for(seconds: int, interval: int) -> Iterable[int]: for _ in range(int(seconds / interval)): yield interval build_id = build_batch.id - logging.debug(f"Codebuild for project {project} with branch {branch} triggered. Id is {build_id}.") - for seconds_to_wait in wait_for(seconds=timeout_in_seconds, interval=poll_interval_seconds): + logging.debug( + f"Codebuild for project {project} with branch {branch} triggered. Id is {build_id}." + ) + for seconds_to_wait in wait_for( + seconds=timeout_in_seconds, interval=poll_interval_seconds + ): sleep_function(seconds_to_wait) logging.debug(f"Checking status of codebuild id {build_id}.") build_batches = client.batch_get_build_batches(build_batch_ids=[build_id]) - logging.debug(f"Build response of codebuild id {build_id} is {build_batches}") + logging.debug( + f"Build response of codebuild id {build_id} is {build_batches}" + ) if len(build_batches) != 1: - logging.error(f"Unexpected return value from 'batch_get_build_batches': {build_batches}") + logging.error( + f"Unexpected return value from 'batch_get_build_batches': {build_batches}" + ) build_status = build_batches[0].build_batch_status logging.info(f"Build status of codebuild id {build_id} is {build_status}") if build_status == BuildBatchStatus.SUCCEEDED: break elif build_status in BUILD_STATUS_FAILURES: - raise RuntimeError(f"Build ({build_id}) failed with status: {build_status.name}") + raise RuntimeError( + f"Build ({build_id}) failed with status: {build_status.name}" + ) # if loop does not break early, build wasn't successful else: raise RuntimeError(f"Batch build {build_id} ran into timeout.") diff --git a/exasol_script_languages_container_ci_setup/lib/aws/deployer.py b/exasol_script_languages_container_ci_setup/lib/aws/deployer.py index 6c8c494..456d63b 100644 --- a/exasol_script_languages_container_ci_setup/lib/aws/deployer.py +++ b/exasol_script_languages_container_ci_setup/lib/aws/deployer.py @@ -11,27 +11,26 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. -#Source: https://github.com/aws/aws-cli/blob/e1f7196ad7859a8144f0313fa4b407da5ae8b101/awscli/customizations/cloudformation/deployer.py +# Source: https://github.com/aws/aws-cli/blob/e1f7196ad7859a8144f0313fa4b407da5ae8b101/awscli/customizations/cloudformation/deployer.py -import time -import logging -import botocore import collections - +import logging +import time from datetime import datetime +import botocore from botocore.exceptions import ValidationError LOG = logging.getLogger(__name__) ChangeSetResult = collections.namedtuple( - "ChangeSetResult", ["changeset_id", "changeset_type"]) + "ChangeSetResult", ["changeset_id", "changeset_type"] +) -class Deployer(object): +class Deployer: - def __init__(self, cloudformation_client, - changeset_prefix="slc-ci-setup-deploy-"): + def __init__(self, cloudformation_client, changeset_prefix="slc-ci-setup-deploy-"): self._client = cloudformation_client self.changeset_prefix = changeset_prefix @@ -62,18 +61,24 @@ def has_stack(self, stack_name): # the exception msg to understand the nature of this exception. msg = str(e) - if "Stack with id {0} does not exist".format(stack_name) in msg: - LOG.debug("Stack with id {0} does not exist".format( - stack_name)) + if f"Stack with id {stack_name} does not exist" in msg: + LOG.debug(f"Stack with id {stack_name} does not exist") return False else: # We don't know anything about this exception. Don't handle LOG.debug("Unable to get stack details.", exc_info=e) raise e - def create_changeset(self, stack_name, cfn_template, - parameter_values, capabilities, role_arn, - notification_arns, tags): + def create_changeset( + self, + stack_name, + cfn_template, + parameter_values, + capabilities, + role_arn, + notification_arns, + tags, + ): """ Call Cloudformation to create a changeset and wait for it to complete @@ -86,7 +91,7 @@ def create_changeset(self, stack_name, cfn_template, """ now = datetime.utcnow().isoformat() - description = "Created by AWS CLI at {0} UTC".format(now) + description = f"Created by AWS CLI at {now} UTC" # Each changeset will get a unique name based on time changeset_name = self.changeset_prefix + str(int(time.time())) @@ -96,34 +101,41 @@ def create_changeset(self, stack_name, cfn_template, # When creating a new stack, UsePreviousValue=True is invalid. # For such parameters, users should either override with new value, # or set a Default value in template to successfully create a stack. - parameter_values = [x for x in parameter_values - if not x.get("UsePreviousValue", False)] + parameter_values = [ + x for x in parameter_values if not x.get("UsePreviousValue", False) + ] else: changeset_type = "UPDATE" # UsePreviousValue not valid if parameter is new summary = self._client.get_template_summary(StackName=stack_name) - existing_parameters = [parameter['ParameterKey'] for parameter in - summary['Parameters']] - parameter_values = [x for x in parameter_values - if not (x.get("UsePreviousValue", False) and - x["ParameterKey"] not in existing_parameters)] + existing_parameters = [ + parameter["ParameterKey"] for parameter in summary["Parameters"] + ] + parameter_values = [ + x + for x in parameter_values + if not ( + x.get("UsePreviousValue", False) + and x["ParameterKey"] not in existing_parameters + ) + ] kwargs = { - 'ChangeSetName': changeset_name, - 'StackName': stack_name, - 'TemplateBody': cfn_template, - 'ChangeSetType': changeset_type, - 'Parameters': parameter_values, - 'Capabilities': capabilities, - 'Description': description, - 'Tags': tags, + "ChangeSetName": changeset_name, + "StackName": stack_name, + "TemplateBody": cfn_template, + "ChangeSetType": changeset_type, + "Parameters": parameter_values, + "Capabilities": capabilities, + "Description": description, + "Tags": tags, } # don't set these arguments if not specified to use existing values if role_arn is not None: - kwargs['RoleARN'] = role_arn + kwargs["RoleARN"] = role_arn if notification_arns is not None: - kwargs['NotificationARNs'] = notification_arns + kwargs["NotificationARNs"] = notification_arns try: resp = self._client.create_change_set(**kwargs) return ChangeSetResult(resp["Id"], changeset_type) @@ -144,10 +156,13 @@ def wait_for_changeset(self, changeset_id, stack_name): # Wait for changeset to be created waiter = self._client.get_waiter("change_set_create_complete") # Poll every 5 seconds. Changeset creation should be fast - waiter_config = {'Delay': 5} + waiter_config = {"Delay": 5} try: - waiter.wait(ChangeSetName=changeset_id, StackName=stack_name, - WaiterConfig=waiter_config) + waiter.wait( + ChangeSetName=changeset_id, + StackName=stack_name, + WaiterConfig=waiter_config, + ) except botocore.exceptions.WaiterError as ex: LOG.debug("Create changeset waiter exception", exc_info=ex) @@ -155,12 +170,12 @@ def wait_for_changeset(self, changeset_id, stack_name): status = resp["Status"] reason = resp["StatusReason"] - raise RuntimeError("Failed to create the changeset: {0} " - "Status: {1}. Reason: {2}" - .format(ex, status, reason)) from ex + raise RuntimeError( + "Failed to create the changeset: {} " + "Status: {}. Reason: {}".format(ex, status, reason) + ) from ex - def execute_changeset(self, changeset_id, stack_name, - disable_rollback=False): + def execute_changeset(self, changeset_id, stack_name, disable_rollback=False): """ Calls CloudFormation to execute changeset @@ -172,7 +187,8 @@ def execute_changeset(self, changeset_id, stack_name, return self._client.execute_change_set( ChangeSetName=changeset_id, StackName=stack_name, - DisableRollback=disable_rollback) + DisableRollback=disable_rollback, + ) def wait_for_execute(self, stack_name, changeset_type): @@ -184,14 +200,13 @@ def wait_for_execute(self, stack_name, changeset_type): elif changeset_type == "UPDATE": waiter = self._client.get_waiter("stack_update_complete") else: - raise RuntimeError("Invalid changeset type {0}" - .format(changeset_type)) + raise RuntimeError(f"Invalid changeset type {changeset_type}") # Poll every 30 seconds. Polling too frequently risks hitting rate limits # on CloudFormation's DescribeStacks API waiter_config = { - 'Delay': 30, - 'MaxAttempts': 120, + "Delay": 30, + "MaxAttempts": 120, } try: @@ -200,13 +215,26 @@ def wait_for_execute(self, stack_name, changeset_type): LOG.debug("Execute changeset waiter exception", exc_info=ex) raise RuntimeError("Execute changeset waiter exception", ex) - def create_and_wait_for_changeset(self, stack_name, cfn_template, - parameter_values, capabilities, role_arn, - notification_arns, tags): + def create_and_wait_for_changeset( + self, + stack_name, + cfn_template, + parameter_values, + capabilities, + role_arn, + notification_arns, + tags, + ): result = self.create_changeset( - stack_name, cfn_template, parameter_values, capabilities, - role_arn, notification_arns, tags) + stack_name, + cfn_template, + parameter_values, + capabilities, + role_arn, + notification_arns, + tags, + ) self.wait_for_changeset(result.changeset_id, stack_name) return result diff --git a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/aws_client.py b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/aws_client.py index 02784ce..7ef207b 100644 --- a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/aws_client.py +++ b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/aws_client.py @@ -1,33 +1,50 @@ import dataclasses from abc import abstractmethod -from typing import List, Dict, Optional, Any, Protocol +from typing import ( + Any, + Dict, + List, + Optional, + Protocol, +) import boto3 from boto3 import Session -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.cloudformation_service import CloudFormationService -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.codebuild_service import CodeBuildService -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.secretsmanager_service import SecretsManagerService +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.cloudformation_service import ( + CloudFormationService, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.codebuild_service import ( + CodeBuildService, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.secretsmanager_service import ( + SecretsManagerService, +) class BotoSessionFactory(Protocol): @abstractmethod - def __call__(self, profile_name: Optional[str] = None, region_name: Optional[str] = None) -> Session: - ... + def __call__( + self, profile_name: Optional[str] = None, region_name: Optional[str] = None + ) -> Session: ... class AwsClient: - def __init__(self, - profile: Optional[str] = None, - region: Optional[str] = None, - boto_session_factory: BotoSessionFactory = boto3.session.Session): + def __init__( + self, + profile: Optional[str] = None, + region: Optional[str] = None, + boto_session_factory: BotoSessionFactory = boto3.session.Session, + ): self._boto_session_factory = boto_session_factory self._region = region self._profile = profile def _create_aws_session(self) -> Session: - return self._boto_session_factory(profile_name=self._profile, region_name=self._region) + return self._boto_session_factory( + profile_name=self._profile, region_name=self._region + ) def create_codebuild_service(self) -> CodeBuildService: session = self._create_aws_session() @@ -46,5 +63,7 @@ def create_cloudformation_service(self) -> CloudFormationService: class AwsClientFactory: - def create(self, profile: Optional[str] = None, region: Optional[str] = None) -> AwsClient: + def create( + self, profile: Optional[str] = None, region: Optional[str] = None + ) -> AwsClient: return AwsClient(profile=profile, region=region) diff --git a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/cloudformation_service.py b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/cloudformation_service.py index b738510..9876114 100644 --- a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/cloudformation_service.py +++ b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/cloudformation_service.py @@ -1,8 +1,18 @@ -from typing import Any, Dict, Optional, Callable +from typing import ( + Any, + Callable, + Dict, + Optional, +) -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ValidationResult, \ - ListStackResourcesResult, NextToken -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ( + ListStackResourcesResult, + NextToken, + ValidationResult, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) class CloudFormationService: @@ -13,30 +23,40 @@ def __init__(self, internal_aws_client): def internal_aws_client(self) -> Any: return self._internal_aws_client - def validate_template(self, - template_body: str, - from_boto: Callable[[Dict[str, Any]], ValidationResult] = - ValidationResult.from_boto) \ - -> ValidationResult: - boto_validation_result = self._internal_aws_client.validate_template(TemplateBody=template_body) + def validate_template( + self, + template_body: str, + from_boto: Callable[ + [Dict[str, Any]], ValidationResult + ] = ValidationResult.from_boto, + ) -> ValidationResult: + boto_validation_result = self._internal_aws_client.validate_template( + TemplateBody=template_body + ) validation_result = from_boto(boto_validation_result) return validation_result - def list_stack_resources(self, - stack_name: PhysicalResourceId, - next_token: Optional[NextToken] = None, - from_boto: Callable[[Dict[str, Any]], ListStackResourcesResult] = - ListStackResourcesResult.from_boto) \ - -> ListStackResourcesResult: + def list_stack_resources( + self, + stack_name: PhysicalResourceId, + next_token: Optional[NextToken] = None, + from_boto: Callable[ + [Dict[str, Any]], ListStackResourcesResult + ] = ListStackResourcesResult.from_boto, + ) -> ListStackResourcesResult: if next_token is not None: - boto_list_stack_resources_result = \ + boto_list_stack_resources_result = ( self._internal_aws_client.list_stack_resources( StackName=stack_name.aws_physical_resource_id, - NextToken=next_token.aws_next_token) + NextToken=next_token.aws_next_token, + ) + ) else: - boto_list_stack_resources_result = \ + boto_list_stack_resources_result = ( self._internal_aws_client.list_stack_resources( - StackName=stack_name.aws_physical_resource_id) + StackName=stack_name.aws_physical_resource_id + ) + ) list_stack_resources_result = from_boto(boto_list_stack_resources_result) return list_stack_resources_result diff --git a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/codebuild_service.py b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/codebuild_service.py index fcf9bf1..cde7f2e 100644 --- a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/codebuild_service.py +++ b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/codebuild_service.py @@ -1,7 +1,16 @@ -from typing import Dict, Any, List, Callable +from typing import ( + Any, + Callable, + Dict, + List, +) -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.codebuild import BuildBatch -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.codebuild import ( + BuildBatch, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) class CodeBuildService: @@ -13,25 +22,35 @@ def internal_aws_client(self) -> Any: return self._internal_aws_client def start_build_batch( - self, - project_name: PhysicalResourceId, - source_version: str, - environment_variables_override: List[Dict[str, str]], - from_boto: Callable[[Dict[str, Any]], BuildBatch] = BuildBatch.from_boto) \ - -> BuildBatch: + self, + project_name: PhysicalResourceId, + source_version: str, + environment_variables_override: List[Dict[str, str]], + from_boto: Callable[[Dict[str, Any]], BuildBatch] = BuildBatch.from_boto, + ) -> BuildBatch: boto_build_batch = self._internal_aws_client.start_build_batch( projectName=project_name.aws_physical_resource_id, sourceVersion=source_version, - environmentVariablesOverride=environment_variables_override) - build_batch = from_boto(boto_build_batch['buildBatch']) + environmentVariablesOverride=environment_variables_override, + ) + build_batch = from_boto(boto_build_batch["buildBatch"]) return build_batch - def batch_get_build_batches(self, - build_batch_ids: List[PhysicalResourceId], - from_boto: Callable[[Dict[str, Any]], BuildBatch] = BuildBatch.from_boto) \ - -> List[BuildBatch]: - aws_ids = [build_batch_id.aws_physical_resource_id for build_batch_id in build_batch_ids] - boto_build_batches = self._internal_aws_client.batch_get_build_batches(ids=aws_ids) + def batch_get_build_batches( + self, + build_batch_ids: List[PhysicalResourceId], + from_boto: Callable[[Dict[str, Any]], BuildBatch] = BuildBatch.from_boto, + ) -> List[BuildBatch]: + aws_ids = [ + build_batch_id.aws_physical_resource_id + for build_batch_id in build_batch_ids + ] + boto_build_batches = self._internal_aws_client.batch_get_build_batches( + ids=aws_ids + ) print(boto_build_batches) - build_batches = [from_boto(boto_build_batch) for boto_build_batch in boto_build_batches['buildBatches']] + build_batches = [ + from_boto(boto_build_batch) + for boto_build_batch in boto_build_batches["buildBatches"] + ] return build_batches diff --git a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/cloudformation.py b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/cloudformation.py index 419a7d3..0aa7784 100644 --- a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/cloudformation.py +++ b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/cloudformation.py @@ -1,7 +1,14 @@ import dataclasses -from typing import Any, Optional, List, Dict +from typing import ( + Any, + Dict, + List, + Optional, +) -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) RESOURCE_TYPE = "ResourceType" @@ -23,25 +30,37 @@ class StackResourceSummary: resource_type: str @classmethod - def from_boto(cls, boto_stack_resource_summary: Dict[str, Any]) -> "StackResourceSummary": - physical_resource_id = cls._extract_physcial_resource_id(boto_stack_resource_summary) + def from_boto( + cls, boto_stack_resource_summary: Dict[str, Any] + ) -> "StackResourceSummary": + physical_resource_id = cls._extract_physcial_resource_id( + boto_stack_resource_summary + ) resource_type = boto_stack_resource_summary[RESOURCE_TYPE] - stack_resource_summary = StackResourceSummary(physical_resource_id=physical_resource_id, - resource_type=resource_type) + stack_resource_summary = StackResourceSummary( + physical_resource_id=physical_resource_id, resource_type=resource_type + ) return stack_resource_summary @classmethod - def _extract_physcial_resource_id(cls, boto_stack_resource_summary: Dict[str, Any]) -> PhysicalResourceId: + def _extract_physcial_resource_id( + cls, boto_stack_resource_summary: Dict[str, Any] + ) -> PhysicalResourceId: physical_resource_id = None if cls._has_physical_resource_id(boto_stack_resource_summary): physical_resource_id = PhysicalResourceId( - aws_physical_resource_id=boto_stack_resource_summary[PHYSICAL_RESOURCE_ID]) + aws_physical_resource_id=boto_stack_resource_summary[ + PHYSICAL_RESOURCE_ID + ] + ) return physical_resource_id @classmethod def _has_physical_resource_id(cls, boto_stack_resource_summary: Dict[str, Any]): - return PHYSICAL_RESOURCE_ID in boto_stack_resource_summary \ - and boto_stack_resource_summary[PHYSICAL_RESOURCE_ID] is not None + return ( + PHYSICAL_RESOURCE_ID in boto_stack_resource_summary + and boto_stack_resource_summary[PHYSICAL_RESOURCE_ID] is not None + ) @dataclasses.dataclass(frozen=True) @@ -50,19 +69,28 @@ class ListStackResourcesResult: stack_resource_summaries: List[StackResourceSummary] @classmethod - def from_boto(cls, boto_list_stack_resources_result: Dict[str, Any]) -> "ListStackResourcesResult": + def from_boto( + cls, boto_list_stack_resources_result: Dict[str, Any] + ) -> "ListStackResourcesResult": next_token = None if cls._has_next_token(boto_list_stack_resources_result): next_token = NextToken(boto_list_stack_resources_result[NEXT_TOKEN]) - stack_resource_summaries = [StackResourceSummary.from_boto(boto_stack_resource_summary) - for boto_stack_resource_summary - in boto_list_stack_resources_result[STACK_RESOURCE_SUMMARIES]] - return ListStackResourcesResult(next_token=next_token, stack_resource_summaries=stack_resource_summaries) + stack_resource_summaries = [ + StackResourceSummary.from_boto(boto_stack_resource_summary) + for boto_stack_resource_summary in boto_list_stack_resources_result[ + STACK_RESOURCE_SUMMARIES + ] + ] + return ListStackResourcesResult( + next_token=next_token, stack_resource_summaries=stack_resource_summaries + ) @classmethod def _has_next_token(cls, boto_list_stack_resources_result): - return NEXT_TOKEN in boto_list_stack_resources_result \ - and boto_list_stack_resources_result[NEXT_TOKEN] is not None + return ( + NEXT_TOKEN in boto_list_stack_resources_result + and boto_list_stack_resources_result[NEXT_TOKEN] is not None + ) @dataclasses.dataclass(frozen=True) diff --git a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/codebuild.py b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/codebuild.py index a5ef394..a80bb5c 100644 --- a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/codebuild.py +++ b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/codebuild.py @@ -1,8 +1,17 @@ import dataclasses -from enum import Enum, auto -from typing import Dict, Any, Optional +from enum import ( + Enum, + auto, +) +from typing import ( + Any, + Dict, + Optional, +) -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) BUILD_BATCH_STATUS = "buildBatchStatus" @@ -31,7 +40,9 @@ def from_boto(self, boto_buildbatch: Dict[str, Any]) -> "BuildBatch": return build_batch @classmethod - def _extract_build_id(cls, boto_buildbatch: Dict[str, Any]) -> Optional[PhysicalResourceId]: + def _extract_build_id( + cls, boto_buildbatch: Dict[str, Any] + ) -> Optional[PhysicalResourceId]: batch_id = None if BuildBatch._has_id(boto_buildbatch): batch_id = PhysicalResourceId(aws_physical_resource_id=boto_buildbatch[ID]) @@ -42,7 +53,9 @@ def _has_id(cls, boto_buildbatch: Dict[str, Any]) -> bool: return ID in boto_buildbatch and boto_buildbatch[ID] is not None @classmethod - def _extract_build_batch_status(cls, boto_buildbatch: Dict[str, Any]) -> Optional[BuildBatchStatus]: + def _extract_build_batch_status( + cls, boto_buildbatch: Dict[str, Any] + ) -> Optional[BuildBatchStatus]: build_batch_status = None if BuildBatch._has_build_status(boto_buildbatch): build_batch_status = BuildBatchStatus[boto_buildbatch[BUILD_BATCH_STATUS]] @@ -50,4 +63,7 @@ def _extract_build_batch_status(cls, boto_buildbatch: Dict[str, Any]) -> Optiona @classmethod def _has_build_status(cls, boto_buildbatch: Dict[str, Any]) -> bool: - return BUILD_BATCH_STATUS in boto_buildbatch and boto_buildbatch[BUILD_BATCH_STATUS] is not None + return ( + BUILD_BATCH_STATUS in boto_buildbatch + and boto_buildbatch[BUILD_BATCH_STATUS] is not None + ) diff --git a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/common.py b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/common.py index ad59767..43769c1 100644 --- a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/common.py +++ b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/common.py @@ -9,6 +9,7 @@ class ARN: We use a dataclass to encapsulate the original value of the ARN, to decouple our abstraction from AWS. This way we don't care when AWS should change its datatype. """ + aws_arn: Any @@ -19,4 +20,5 @@ class PhysicalResourceId: We use a dataclass to encapsulate the original value of the PhysicalResourceId, to decouple our abstraction from AWS. This way we don't care when AWS should change its datatype. """ + aws_physical_resource_id: Any diff --git a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/secretsmanager.py b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/secretsmanager.py index 8497b10..6c1afcb 100644 --- a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/secretsmanager.py +++ b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/datamodels/secretsmanager.py @@ -1,7 +1,12 @@ import dataclasses -from typing import Dict, Any +from typing import ( + Any, + Dict, +) -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ARN +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + ARN, +) ARN_KEY = "ARN" diff --git a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/secretsmanager_service.py b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/secretsmanager_service.py index 1be5818..0c2613c 100644 --- a/exasol_script_languages_container_ci_setup/lib/aws/wrapper/secretsmanager_service.py +++ b/exasol_script_languages_container_ci_setup/lib/aws/wrapper/secretsmanager_service.py @@ -1,8 +1,17 @@ import dataclasses -from typing import Any, Dict, Callable +from typing import ( + Any, + Callable, + Dict, +) -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ARN, PhysicalResourceId -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.secretsmanager import Secret +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + ARN, + PhysicalResourceId, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.secretsmanager import ( + Secret, +) class SecretsManagerService: @@ -13,10 +22,13 @@ def __init__(self, internal_aws_client): def internal_aws_client(self) -> Any: return self._internal_aws_client - def get_secret_value(self, - secret_id: PhysicalResourceId, - from_boto: Callable[[Dict[str, Any]], Secret] = Secret.from_boto) \ - -> Secret: - boto_secret = self._internal_aws_client.get_secret_value(SecretId=secret_id.aws_physical_resource_id) + def get_secret_value( + self, + secret_id: PhysicalResourceId, + from_boto: Callable[[Dict[str, Any]], Secret] = Secret.from_boto, + ) -> Secret: + boto_secret = self._internal_aws_client.get_secret_value( + SecretId=secret_id.aws_physical_resource_id + ) secret = from_boto(boto_secret) return secret diff --git a/exasol_script_languages_container_ci_setup/lib/ci_build.py b/exasol_script_languages_container_ci_setup/lib/ci_build.py index 76a9990..1e71fe3 100644 --- a/exasol_script_languages_container_ci_setup/lib/ci_build.py +++ b/exasol_script_languages_container_ci_setup/lib/ci_build.py @@ -1,14 +1,17 @@ import logging from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.render_template import render_template +from exasol_script_languages_container_ci_setup.lib.render_template import ( + render_template, +) CODE_BUILD_STACK_NAME = "CIBuild" CI_CODE_BUILD_TEMPLATE = "slc_code_build.yaml" -CI_BUILD_WEBHOOK_FILTER_PATTERN = \ - r"^refs/heads/(((main|master|develop)$)|" \ +CI_BUILD_WEBHOOK_FILTER_PATTERN = ( + r"^refs/heads/(((main|master|develop)$)|" r"((rebuild|feature|bug|enhancement|refactoring|ci|security|doc|documentation)/.*))" +) def ci_stack_name(project: str): @@ -21,11 +24,17 @@ def run_deploy_ci_build(aws_access: AwsAccess, project: str, github_url: str): 1. It get's the dockerhub secret ARN from AWS via Boto3 2. Then it renders the template and uploads the resulting cloudformation YAML file. """ - logging.info(f"run_deploy_ci_build for aws profile {aws_access.aws_profile} for project {project} at {github_url}") + logging.info( + f"run_deploy_ci_build for aws profile {aws_access.aws_profile} for project {project} at {github_url}" + ) dockerhub_secret_arn = aws_access.read_dockerhub_secret_arn() - yml = render_template(CI_CODE_BUILD_TEMPLATE, project=project, - dockerhub_secret_arn=dockerhub_secret_arn.aws_arn, github_url=github_url, - webhook_filter_pattern=CI_BUILD_WEBHOOK_FILTER_PATTERN) + yml = render_template( + CI_CODE_BUILD_TEMPLATE, + project=project, + dockerhub_secret_arn=dockerhub_secret_arn.aws_arn, + github_url=github_url, + webhook_filter_pattern=CI_BUILD_WEBHOOK_FILTER_PATTERN, + ) aws_access.upload_cloudformation_stack(yml, ci_stack_name(project)) @@ -33,10 +42,16 @@ def run_validate_ci_build(aws_access: AwsAccess, project: str, github_url: str): """ This command validates the ci build cloudformation stack """ - logging.info(f"run_validate_ci_build for aws profile {aws_access.aws_profile} " - f"for project {project} at {github_url}") + logging.info( + f"run_validate_ci_build for aws profile {aws_access.aws_profile} " + f"for project {project} at {github_url}" + ) dockerhub_secret_arn = "dummy_arn" - yml = render_template(CI_CODE_BUILD_TEMPLATE, project=project, - dockerhub_secret_arn=dockerhub_secret_arn, github_url=github_url, - webhook_filter_pattern=CI_BUILD_WEBHOOK_FILTER_PATTERN) + yml = render_template( + CI_CODE_BUILD_TEMPLATE, + project=project, + dockerhub_secret_arn=dockerhub_secret_arn, + github_url=github_url, + webhook_filter_pattern=CI_BUILD_WEBHOOK_FILTER_PATTERN, + ) aws_access.validate_cloudformation_template(yml) diff --git a/exasol_script_languages_container_ci_setup/lib/generate_buildspec_common.py b/exasol_script_languages_container_ci_setup/lib/generate_buildspec_common.py index 9fa1b07..4653ac6 100644 --- a/exasol_script_languages_container_ci_setup/lib/generate_buildspec_common.py +++ b/exasol_script_languages_container_ci_setup/lib/generate_buildspec_common.py @@ -1,19 +1,25 @@ - import logging from dataclasses import dataclass from pathlib import Path -from typing import Optional, Tuple, List +from typing import ( + List, + Optional, + Tuple, +) from exasol_script_languages_container_ci.lib.config.config_data_model import Config -from exasol_script_languages_container_ci_setup.lib.render_template import render_template +from exasol_script_languages_container_ci_setup.lib.render_template import ( + render_template, +) @dataclass(eq=True, frozen=True, order=True) -class Flavor(object): - """" +class Flavor: + """ Holds the name and the formatted name used for generating the buildspec. """ + flavor_original: str @property @@ -61,17 +67,24 @@ def _find_flavors(flavor_root_paths: Tuple[str, ...]) -> List[Flavor]: return return_value -def write_batch_build_spec(flavor_root_paths: Tuple[str, ...], output_pathname: str) -> None: +def write_batch_build_spec( + flavor_root_paths: Tuple[str, ...], output_pathname: str +) -> None: buildspec_body = [] flavors = _find_flavors(flavor_root_paths) for flavor in flavors: - buildspec_body.append(render_template("buildspec_batch_entry.yaml", - flavor_original=flavor.flavor_original, - flavor_formatted=flavor.flavor_formatted, - out_path=output_pathname)) - - result_yaml = render_template("buildspec_hull.yaml", - batch_entries="\n".join(buildspec_body)) + buildspec_body.append( + render_template( + "buildspec_batch_entry.yaml", + flavor_original=flavor.flavor_original, + flavor_formatted=flavor.flavor_formatted, + out_path=output_pathname, + ) + ) + + result_yaml = render_template( + "buildspec_hull.yaml", batch_entries="\n".join(buildspec_body) + ) with open(Path(output_pathname) / "buildspec.yaml", "w") as output_file: output_file.write(result_yaml) diff --git a/exasol_script_languages_container_ci_setup/lib/github_draft_release_creator.py b/exasol_script_languages_container_ci_setup/lib/github_draft_release_creator.py index 7c7db91..99bbe2f 100644 --- a/exasol_script_languages_container_ci_setup/lib/github_draft_release_creator.py +++ b/exasol_script_languages_container_ci_setup/lib/github_draft_release_creator.py @@ -1,7 +1,7 @@ from github import Github -class GithubDraftReleaseCreator(object): +class GithubDraftReleaseCreator: """ Implements creation of a Github Draft Release. See https://docs.github.com/en/rest/releases/releases for details. @@ -9,9 +9,17 @@ class GithubDraftReleaseCreator(object): Returns the internal ID of the new release. """ - def create_release(self, repo_name: str, branch: str, title: str, gh_token: str) -> int: + def create_release( + self, repo_name: str, branch: str, title: str, gh_token: str + ) -> int: gh = Github(gh_token) gh_repo = gh.get_repo(repo_name) - release = gh_repo.create_git_release(tag="", name=title, message="Test-Release", - draft=True, prerelease=True, target_commitish=branch) + release = gh_repo.create_git_release( + tag="", + name=title, + message="Test-Release", + draft=True, + prerelease=True, + target_commitish=branch, + ) return release.id diff --git a/exasol_script_languages_container_ci_setup/lib/release_build.py b/exasol_script_languages_container_ci_setup/lib/release_build.py index 721edcc..c97011f 100644 --- a/exasol_script_languages_container_ci_setup/lib/release_build.py +++ b/exasol_script_languages_container_ci_setup/lib/release_build.py @@ -1,7 +1,9 @@ import logging from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.render_template import render_template +from exasol_script_languages_container_ci_setup.lib.render_template import ( + render_template, +) CODE_BUILD_STACK_NAME = "ReleaseBuild" RELEASE_CODEBUILD_TEMPLATE = "slc_code_release_build.yaml" @@ -17,11 +19,17 @@ def run_deploy_release_build(aws_access: AwsAccess, project: str, github_url: st 1. It get's the dockerhub secret ARN from AWS via Boto3 2. Then it renders the template and uploads the resulting cloudformation YAML file. """ - logging.info(f"run_deploy_release_build for aws profile " - f"{aws_access.aws_profile} for project {project} at {github_url}") + logging.info( + f"run_deploy_release_build for aws profile " + f"{aws_access.aws_profile} for project {project} at {github_url}" + ) dockerhub_secret_arn = aws_access.read_dockerhub_secret_arn() - yml = render_template(RELEASE_CODEBUILD_TEMPLATE, project=project, - dockerhub_secret_arn=dockerhub_secret_arn, github_url=github_url) + yml = render_template( + RELEASE_CODEBUILD_TEMPLATE, + project=project, + dockerhub_secret_arn=dockerhub_secret_arn, + github_url=github_url, + ) aws_access.upload_cloudformation_stack(yml, release_stack_name(project)) @@ -29,9 +37,15 @@ def run_validate_release_build(aws_access: AwsAccess, project: str, github_url: """ This command validates the release build cloudformation stack """ - logging.info(f"run_validate_release_build for aws profile {aws_access.aws_profile} " - f"for project {project} at {github_url}") + logging.info( + f"run_validate_release_build for aws profile {aws_access.aws_profile} " + f"for project {project} at {github_url}" + ) dockerhub_secret_arn = "dummy_arn" - yml = render_template(RELEASE_CODEBUILD_TEMPLATE, project=project, - dockerhub_secret_arn=dockerhub_secret_arn, github_url=github_url) + yml = render_template( + RELEASE_CODEBUILD_TEMPLATE, + project=project, + dockerhub_secret_arn=dockerhub_secret_arn, + github_url=github_url, + ) aws_access.validate_cloudformation_template(yml) diff --git a/exasol_script_languages_container_ci_setup/lib/render_template.py b/exasol_script_languages_container_ci_setup/lib/render_template.py index 580c143..a96de7e 100644 --- a/exasol_script_languages_container_ci_setup/lib/render_template.py +++ b/exasol_script_languages_container_ci_setup/lib/render_template.py @@ -2,7 +2,10 @@ def render_template(template: str, **kwargs): - env = jinja2.Environment(loader=jinja2.PackageLoader("exasol_script_languages_container_ci_setup"), - autoescape=jinja2.select_autoescape(), keep_trailing_newline=True) + env = jinja2.Environment( + loader=jinja2.PackageLoader("exasol_script_languages_container_ci_setup"), + autoescape=jinja2.select_autoescape(), + keep_trailing_newline=True, + ) t = env.get_template(template) return t.render(**kwargs) diff --git a/exasol_script_languages_container_ci_setup/lib/run_generate_buildspec.py b/exasol_script_languages_container_ci_setup/lib/run_generate_buildspec.py index 7dd124b..617de56 100644 --- a/exasol_script_languages_container_ci_setup/lib/run_generate_buildspec.py +++ b/exasol_script_languages_container_ci_setup/lib/run_generate_buildspec.py @@ -1,25 +1,33 @@ import logging from pathlib import Path -from typing import Tuple, Optional +from typing import ( + Optional, + Tuple, +) -from exasol_script_languages_container_ci_setup.lib.generate_buildspec_common import validate_config_file, \ - get_config_file_parameter, write_batch_build_spec -from exasol_script_languages_container_ci_setup.lib.render_template import render_template +from exasol_script_languages_container_ci_setup.lib.generate_buildspec_common import ( + get_config_file_parameter, + validate_config_file, + write_batch_build_spec, +) +from exasol_script_languages_container_ci_setup.lib.render_template import ( + render_template, +) def run_generate_buildspec( - flavor_root_paths: Tuple[str, ...], - output_pathname: str, - config_file: Optional[str]): + flavor_root_paths: Tuple[str, ...], output_pathname: str, config_file: Optional[str] +): validate_config_file(config_file) logging.info(f"Run run_generate_buildspec for paths: {flavor_root_paths}") write_batch_build_spec(flavor_root_paths, output_pathname) - result_build_yaml = render_template("build_buildspec.yaml", - config_file_parameter=get_config_file_parameter(config_file)) + result_build_yaml = render_template( + "build_buildspec.yaml", + config_file_parameter=get_config_file_parameter(config_file), + ) with open(Path(output_pathname) / "build_buildspec.yaml", "w") as output_file: output_file.write(result_build_yaml) - diff --git a/exasol_script_languages_container_ci_setup/lib/run_generate_release_buildspec.py b/exasol_script_languages_container_ci_setup/lib/run_generate_release_buildspec.py index 4d92309..ed49915 100644 --- a/exasol_script_languages_container_ci_setup/lib/run_generate_release_buildspec.py +++ b/exasol_script_languages_container_ci_setup/lib/run_generate_release_buildspec.py @@ -1,22 +1,31 @@ import logging from pathlib import Path -from typing import Tuple, Optional +from typing import ( + Optional, + Tuple, +) -from exasol_script_languages_container_ci_setup.lib.generate_buildspec_common import validate_config_file, \ - get_config_file_parameter, write_batch_build_spec -from exasol_script_languages_container_ci_setup.lib.render_template import render_template +from exasol_script_languages_container_ci_setup.lib.generate_buildspec_common import ( + get_config_file_parameter, + validate_config_file, + write_batch_build_spec, +) +from exasol_script_languages_container_ci_setup.lib.render_template import ( + render_template, +) def run_generate_release_buildspec( - flavor_root_paths: Tuple[str, ...], - output_pathname: str, - config_file: Optional[str]): + flavor_root_paths: Tuple[str, ...], output_pathname: str, config_file: Optional[str] +): validate_config_file(config_file) logging.info(f"Run run_generate_release_buildspec for paths: {flavor_root_paths}") write_batch_build_spec(flavor_root_paths, output_pathname) - result_build_yaml = render_template("release_build_buildspec.yaml", - config_file_parameter=get_config_file_parameter(config_file)) + result_build_yaml = render_template( + "release_build_buildspec.yaml", + config_file_parameter=get_config_file_parameter(config_file), + ) with open(Path(output_pathname) / "build_buildspec.yaml", "w") as output_file: output_file.write(result_build_yaml) diff --git a/exasol_script_languages_container_ci_setup/lib/run_start_build.py b/exasol_script_languages_container_ci_setup/lib/run_start_build.py index 69bb554..52742ac 100644 --- a/exasol_script_languages_container_ci_setup/lib/run_start_build.py +++ b/exasol_script_languages_container_ci_setup/lib/run_start_build.py @@ -1,14 +1,25 @@ import logging import re -from typing import Tuple, Dict, List, Optional +from typing import ( + Dict, + List, + Optional, + Tuple, +) from exasol_script_languages_container_ci.lib.config.config_data_model import Config from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import StackResourceSummary +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ( + StackResourceSummary, +) from exasol_script_languages_container_ci_setup.lib.ci_build import ci_stack_name -from exasol_script_languages_container_ci_setup.lib.github_draft_release_creator import GithubDraftReleaseCreator -from exasol_script_languages_container_ci_setup.lib.release_build import release_stack_name +from exasol_script_languages_container_ci_setup.lib.github_draft_release_creator import ( + GithubDraftReleaseCreator, +) +from exasol_script_languages_container_ci_setup.lib.release_build import ( + release_stack_name, +) AWS_CODE_BUILD_PROJECT_RESOURCE_TYPE = "AWS::CodeBuild::Project" DEFAULT_TIMEOUT = 3 * 60 * 60 # 3 hours @@ -18,13 +29,22 @@ def get_environment_variable_override(env_variable: Tuple[str, str]) -> Dict[str return {"name": env_variable[0], "value": env_variable[1], "type": "PLAINTEXT"} -def get_aws_codebuild_project(resources: List[StackResourceSummary], project: str) -> StackResourceSummary: - matching_project = [resource for resource in resources - if resource.resource_type == AWS_CODE_BUILD_PROJECT_RESOURCE_TYPE] +def get_aws_codebuild_project( + resources: List[StackResourceSummary], project: str +) -> StackResourceSummary: + matching_project = [ + resource + for resource in resources + if resource.resource_type == AWS_CODE_BUILD_PROJECT_RESOURCE_TYPE + ] if len(matching_project) == 0: - raise ValueError(f"No project deployed for {project}. Found following resources: {resources}") + raise ValueError( + f"No project deployed for {project}. Found following resources: {resources}" + ) if len(matching_project) > 1: - raise RuntimeError(f"Multiple projects match {project}. Found following matches: {matching_project}") + raise RuntimeError( + f"Multiple projects match {project}. Found following matches: {matching_project}" + ) return matching_project[0] @@ -34,13 +54,18 @@ def _parse_upload_url(upload_url: str) -> int: where `exasol/script-languages-repo` is the repository for which the release will be created and 123 is the id of the release. This method return release id as integer. """ - res = re.search(r"^https://uploads.github.com/repos/([a-zA-Z0-9\-_/]+)/releases/([\d]+)/assets", upload_url) + res = re.search( + r"^https://uploads.github.com/repos/([a-zA-Z0-9\-_/]+)/releases/([\d]+)/assets", + upload_url, + ) if res is None: raise ValueError("Parameter upload_url is in unexpected format.") return int(res.groups()[1]) -def get_timeout_in_seconds(timeout_in_seconds: Optional[int], config_file: Optional[str]) -> int: +def get_timeout_in_seconds( + timeout_in_seconds: Optional[int], config_file: Optional[str] +) -> int: if timeout_in_seconds is not None: return timeout_in_seconds elif config_file is not None: @@ -51,14 +76,15 @@ def get_timeout_in_seconds(timeout_in_seconds: Optional[int], config_file: Optio def _execute_release_build( - aws_access: AwsAccess, - project: str, - branch: str, - release_id: int, - is_dry_run: bool, - gh_token: str, - timeout_in_seconds: Optional[int], - config_file_path: Optional[str]) -> None: + aws_access: AwsAccess, + project: str, + branch: str, + release_id: int, + is_dry_run: bool, + gh_token: str, + timeout_in_seconds: Optional[int], + config_file_path: Optional[str], +) -> None: """ This function: 1. Retrieve resources for the release codebuild stack for that given project @@ -81,28 +107,38 @@ def _execute_release_build( if gh_token is None: raise RuntimeError("Parameter gh_token must not be None.") - env_variables = [("RELEASE_ID", f"{release_id}"), - ("DRY_RUN", dry_run_value), - ("GITHUB_TOKEN", gh_token)] - environment_variables_overrides = list(map(get_environment_variable_override, env_variables)) + env_variables = [ + ("RELEASE_ID", f"{release_id}"), + ("DRY_RUN", dry_run_value), + ("GITHUB_TOKEN", gh_token), + ] + environment_variables_overrides = list( + map(get_environment_variable_override, env_variables) + ) timeout_in_seconds = get_timeout_in_seconds( + timeout_in_seconds=timeout_in_seconds, config_file=config_file_path + ) + aws_access.start_codebuild( + matching_project.physical_resource_id, + environment_variables_overrides=environment_variables_overrides, + branch=branch, timeout_in_seconds=timeout_in_seconds, - config_file=config_file_path) - aws_access.start_codebuild(matching_project.physical_resource_id, - environment_variables_overrides=environment_variables_overrides, - branch=branch, timeout_in_seconds=timeout_in_seconds) + ) def run_start_release_build( - aws_access: AwsAccess, - project: str, - upload_url: str, - branch: str, - gh_token: str, - timeout_in_seconds: Optional[int], - config_file_path: Optional[str]) -> None: - logging.info(f"run_start_release_build for aws profile {aws_access.aws_profile_for_logging} for project {project} " - f"with upload url: {upload_url}") + aws_access: AwsAccess, + project: str, + upload_url: str, + branch: str, + gh_token: str, + timeout_in_seconds: Optional[int], + config_file_path: Optional[str], +) -> None: + logging.info( + f"run_start_release_build for aws profile {aws_access.aws_profile_for_logging} for project {project} " + f"with upload url: {upload_url}" + ) _execute_release_build( aws_access=aws_access, project=project, @@ -111,23 +147,28 @@ def run_start_release_build( is_dry_run=False, gh_token=gh_token, timeout_in_seconds=timeout_in_seconds, - config_file_path=config_file_path + config_file_path=config_file_path, ) def run_start_test_release_build( - aws_access: AwsAccess, - gh_release_creator: GithubDraftReleaseCreator, repo_name: str, - project: str, - branch: str, - release_title: str, - gh_token: str, - timeout_in_seconds: Optional[int], - config_file_path: Optional[str] + aws_access: AwsAccess, + gh_release_creator: GithubDraftReleaseCreator, + repo_name: str, + project: str, + branch: str, + release_title: str, + gh_token: str, + timeout_in_seconds: Optional[int], + config_file_path: Optional[str], ) -> None: - logging.info(f"run_start_test_release_build for aws profile {aws_access.aws_profile_for_logging} " - f"for project {project} for branch: {branch} with title: {release_title}") - release_id = gh_release_creator.create_release(repo_name, branch, release_title, gh_token) + logging.info( + f"run_start_test_release_build for aws profile {aws_access.aws_profile_for_logging} " + f"for project {project} for branch: {branch} with title: {release_title}" + ) + release_id = gh_release_creator.create_release( + repo_name, branch, release_title, gh_token + ) _execute_release_build( aws_access=aws_access, project=project, @@ -136,13 +177,17 @@ def run_start_test_release_build( is_dry_run=True, gh_token=gh_token, timeout_in_seconds=timeout_in_seconds, - config_file_path=config_file_path + config_file_path=config_file_path, ) -def run_start_ci_build(aws_access: AwsAccess, project: str, branch: str, timeout_in_seconds: int) -> None: - logging.info(f"run_start_ci_build for aws profile {aws_access.aws_profile_for_logging} for project {project} " - f"on branch {branch}") +def run_start_ci_build( + aws_access: AwsAccess, project: str, branch: str, timeout_in_seconds: int +) -> None: + logging.info( + f"run_start_ci_build for aws profile {aws_access.aws_profile_for_logging} for project {project} " + f"on branch {branch}" + ) """ This function: 1. Retrieve resources for the release codebuild stack for that given project @@ -163,8 +208,12 @@ def run_start_ci_build(aws_access: AwsAccess, project: str, branch: str, timeout # be used in the build_buildspec.yaml to forward the branch name to exasol_script_languages_container_ci.run_ci() # (which itself uses the parameter to evaluate build strategies) env_variables = [("CUSTOM_BRANCH", branch)] - environment_variables_overrides = list(map(get_environment_variable_override, env_variables)) - aws_access.start_codebuild(matching_project.physical_resource_id, - environment_variables_overrides=environment_variables_overrides, - branch=branch, - timeout_in_seconds=timeout_in_seconds) + environment_variables_overrides = list( + map(get_environment_variable_override, env_variables) + ) + aws_access.start_codebuild( + matching_project.physical_resource_id, + environment_variables_overrides=environment_variables_overrides, + branch=branch, + timeout_in_seconds=timeout_in_seconds, + ) diff --git a/exasol_script_languages_container_ci_setup/lib/source_credentials.py b/exasol_script_languages_container_ci_setup/lib/source_credentials.py index b5e2c9d..873b037 100644 --- a/exasol_script_languages_container_ci_setup/lib/source_credentials.py +++ b/exasol_script_languages_container_ci_setup/lib/source_credentials.py @@ -1,37 +1,44 @@ import logging from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.render_template import render_template +from exasol_script_languages_container_ci_setup.lib.render_template import ( + render_template, +) SOURCE_CREDENTIALS_STACK_NAME = "SLCSourceCredentials" def run_deploy_source_credentials( - aws_access: AwsAccess, - secret_name: str, - secret_user_key: str, - secret_token_key: str): + aws_access: AwsAccess, secret_name: str, secret_user_key: str, secret_token_key: str +): """ This command deploys the source credential as cloudformation stack. """ - logging.info(f"run_deploy_source_credentials for aws profile {aws_access.aws_profile}") - yml = render_template("slc_source_credential.yaml", - secret_name=secret_name, - secret_user_key=secret_user_key, - secret_token_key=secret_token_key) + logging.info( + f"run_deploy_source_credentials for aws profile {aws_access.aws_profile}" + ) + yml = render_template( + "slc_source_credential.yaml", + secret_name=secret_name, + secret_user_key=secret_user_key, + secret_token_key=secret_token_key, + ) aws_access.upload_cloudformation_stack(yml, SOURCE_CREDENTIALS_STACK_NAME) -def run_validate_source_credentials(aws_access: AwsAccess, - secret_name: str, - secret_user_key: str, - secret_token_key: str): +def run_validate_source_credentials( + aws_access: AwsAccess, secret_name: str, secret_user_key: str, secret_token_key: str +): """ This command deploys the source credential as cloudformation stack. """ - logging.info(f"run_validate_source_credentials for aws profile {aws_access.aws_profile}") - yml = render_template("slc_source_credential.yaml", - secret_name=secret_name, - secret_user_key=secret_user_key, - secret_token_key=secret_token_key) + logging.info( + f"run_validate_source_credentials for aws profile {aws_access.aws_profile}" + ) + yml = render_template( + "slc_source_credential.yaml", + secret_name=secret_name, + secret_user_key=secret_user_key, + secret_token_key=secret_token_key, + ) aws_access.validate_cloudformation_template(yml) diff --git a/exasol_script_languages_container_ci_setup/main.py b/exasol_script_languages_container_ci_setup/main.py index 7b8cb72..3e50198 100755 --- a/exasol_script_languages_container_ci_setup/main.py +++ b/exasol_script_languages_container_ci_setup/main.py @@ -2,5 +2,5 @@ # from exasol_script_languages_container_ci_setup.cli.cli import cli -if __name__ == '__main__': +if __name__ == "__main__": cli() diff --git a/exasol_script_languages_container_ci_setup/version.py b/exasol_script_languages_container_ci_setup/version.py new file mode 100644 index 0000000..5517912 --- /dev/null +++ b/exasol_script_languages_container_ci_setup/version.py @@ -0,0 +1,10 @@ +# ATTENTION: +# This file is generated by exasol/toolbox/pre_commit_hooks/package_version.py when using: +# * either "poetry run nox -s project:fix" +# * or "poetry run version-check --fix" +# Do not edit this file manually! +# If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`. +MAJOR = 1 +MINOR = 6 +PATCH = 0 +VERSION = f"{MAJOR}.{MINOR}.{PATCH}" diff --git a/noxconfig.py b/noxconfig.py new file mode 100644 index 0000000..62776e7 --- /dev/null +++ b/noxconfig.py @@ -0,0 +1,26 @@ +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path +from typing import Iterable + + +@dataclass(frozen=True) +class Config: + root: Path = Path(__file__).parent + doc: Path = Path(__file__).parent / "doc" + version_file: Path = ( + Path(__file__).parent + / "exasol_script_languages_container_ci_setup" + / "version.py" + ) + path_filters: Iterable[str] = ( + "dist", + ".eggs", + "venv", + ) + + plugins = [] + + +PROJECT_CONFIG = Config() diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 0000000..176dbf9 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,7 @@ +import nox + +# imports all nox task provided by the toolbox +from exasol.toolbox.nox.tasks import * + +# default actions to be run if nothing is explicitly specified with the -s option +nox.options.sessions = ["project:fix"] diff --git a/poetry.lock b/poetry.lock index 485e3de..7a8ca0a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,15 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 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" +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 = "annotated-types" @@ -13,13 +24,13 @@ files = [ [[package]] name = "anyio" -version = "4.4.0" +version = "4.6.2.post1" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, - {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, + {file = "anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d"}, + {file = "anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c"}, ] [package.dependencies] @@ -29,24 +40,38 @@ sniffio = ">=1.1" typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.23)"] +doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21.0b1)"] +trio = ["trio (>=0.26.1)"] [[package]] name = "argcomplete" -version = "3.5.0" +version = "3.5.1" description = "Bash tab completion for argparse" optional = false python-versions = ">=3.8" files = [ - {file = "argcomplete-3.5.0-py3-none-any.whl", hash = "sha256:d4bcf3ff544f51e16e54228a7ac7f486ed70ebf2ecfe49a63a91171c76bf029b"}, - {file = "argcomplete-3.5.0.tar.gz", hash = "sha256:4349400469dccfb7950bb60334a680c58d88699bff6159df61251878dc6bf74b"}, + {file = "argcomplete-3.5.1-py3-none-any.whl", hash = "sha256:1a1d148bdaa3e3b93454900163403df41448a248af01b6e849edc5ac08e6c363"}, + {file = "argcomplete-3.5.1.tar.gz", hash = "sha256:eb1ee355aa2557bd3d0145de7b06b2a45b0ce461e1e7813f5d066039ab4177b4"}, ] [package.extras] test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] +[[package]] +name = "astroid" +version = "3.3.5" +description = "An abstract syntax tree for Python with inference support." +optional = false +python-versions = ">=3.9.0" +files = [ + {file = "astroid-3.3.5-py3-none-any.whl", hash = "sha256:a9d1c946ada25098d790e079ba2a1b112157278f3fb7e718ae6a9252f5835dc8"}, + {file = "astroid-3.3.5.tar.gz", hash = "sha256:5cfc40ae9f68311075d27ef68a4841bdc5cc7f6cf86671b49f00607d30188e2d"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} + [[package]] name = "attrs" version = "24.2.0" @@ -68,13 +93,13 @@ tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "aws-sam-translator" -version = "1.91.0" +version = "1.94.0" description = "AWS SAM Translator is a library that transform SAM templates into AWS CloudFormation templates" optional = false python-versions = "!=4.0,<=4.0,>=3.8" files = [ - {file = "aws_sam_translator-1.91.0-py3-none-any.whl", hash = "sha256:9ebf4b53c226338e6b89d14d8583bc4559b87f0be52ed8d577c5a1dc2db14962"}, - {file = "aws_sam_translator-1.91.0.tar.gz", hash = "sha256:0cdfbc598f384c430c3ec064f6008d80c5a0d58f1dc45ca4e331ae5c43cb4697"}, + {file = "aws_sam_translator-1.94.0-py3-none-any.whl", hash = "sha256:100e33eeffcfa81f7c45cadeb0ee29596ce829f6b4d2745140f04fa19a41f539"}, + {file = "aws_sam_translator-1.94.0.tar.gz", hash = "sha256:8ec258d9f7ece72ef91c81f4edb45a2db064c16844b6afac90c575893beaa391"}, ] [package.dependencies] @@ -86,75 +111,133 @@ typing-extensions = ">=4.4" [package.extras] dev = ["black (==24.3.0)", "boto3 (>=1.23,<2)", "boto3-stubs[appconfig,serverlessrepo] (>=1.19.5,<2.dev0)", "coverage (>=5.3,<8)", "dateparser (>=1.1,<2.0)", "mypy (>=1.3.0,<1.4.0)", "parameterized (>=0.7,<1.0)", "pytest (>=6.2,<8)", "pytest-cov (>=2.10,<5)", "pytest-env (>=0.6,<1)", "pytest-rerunfailures (>=9.1,<12)", "pytest-xdist (>=2.5,<4)", "pyyaml (>=6.0,<7.0)", "requests (>=2.28,<3.0)", "ruamel.yaml (==0.17.21)", "ruff (>=0.4.5,<0.5.0)", "tenacity (>=8.0,<9.0)", "types-PyYAML (>=6.0,<7.0)", "types-jsonschema (>=3.2,<4.0)"] +[[package]] +name = "babel" +version = "2.16.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.8" +files = [ + {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, + {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, +] + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + +[[package]] +name = "bandit" +version = "1.8.0" +description = "Security oriented static analyser for python code." +optional = false +python-versions = ">=3.9" +files = [ + {file = "bandit-1.8.0-py3-none-any.whl", hash = "sha256:b1a61d829c0968aed625381e426aa378904b996529d048f8d908fa28f6b13e38"}, + {file = "bandit-1.8.0.tar.gz", hash = "sha256:b5bfe55a095abd9fe20099178a7c6c060f844bfd4fe4c76d28e35e4c52b9d31e"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} +PyYAML = ">=5.3.1" +rich = "*" +stevedore = ">=1.20.0" +tomli = {version = ">=1.1.0", optional = true, markers = "python_version < \"3.11\" and extra == \"toml\""} + +[package.extras] +baseline = ["GitPython (>=3.1.30)"] +sarif = ["jschema-to-python (>=1.2.3)", "sarif-om (>=1.0.4)"] +test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)"] +toml = ["tomli (>=1.1.0)"] +yaml = ["PyYAML"] + [[package]] name = "bcrypt" -version = "4.2.0" +version = "4.2.1" description = "Modern password hashing for your software and your servers" optional = false python-versions = ">=3.7" files = [ - {file = "bcrypt-4.2.0-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:096a15d26ed6ce37a14c1ac1e48119660f21b24cba457f160a4b830f3fe6b5cb"}, - {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c02d944ca89d9b1922ceb8a46460dd17df1ba37ab66feac4870f6862a1533c00"}, - {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d84cf6d877918620b687b8fd1bf7781d11e8a0998f576c7aa939776b512b98d"}, - {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:1bb429fedbe0249465cdd85a58e8376f31bb315e484f16e68ca4c786dcc04291"}, - {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:655ea221910bcac76ea08aaa76df427ef8625f92e55a8ee44fbf7753dbabb328"}, - {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:1ee38e858bf5d0287c39b7a1fc59eec64bbf880c7d504d3a06a96c16e14058e7"}, - {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0da52759f7f30e83f1e30a888d9163a81353ef224d82dc58eb5bb52efcabc399"}, - {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3698393a1b1f1fd5714524193849d0c6d524d33523acca37cd28f02899285060"}, - {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:762a2c5fb35f89606a9fde5e51392dad0cd1ab7ae64149a8b935fe8d79dd5ed7"}, - {file = "bcrypt-4.2.0-cp37-abi3-win32.whl", hash = "sha256:5a1e8aa9b28ae28020a3ac4b053117fb51c57a010b9f969603ed885f23841458"}, - {file = "bcrypt-4.2.0-cp37-abi3-win_amd64.whl", hash = "sha256:8f6ede91359e5df88d1f5c1ef47428a4420136f3ce97763e31b86dd8280fbdf5"}, - {file = "bcrypt-4.2.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:c52aac18ea1f4a4f65963ea4f9530c306b56ccd0c6f8c8da0c06976e34a6e841"}, - {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3bbbfb2734f0e4f37c5136130405332640a1e46e6b23e000eeff2ba8d005da68"}, - {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3413bd60460f76097ee2e0a493ccebe4a7601918219c02f503984f0a7ee0aebe"}, - {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8d7bb9c42801035e61c109c345a28ed7e84426ae4865511eb82e913df18f58c2"}, - {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d3a6d28cb2305b43feac298774b997e372e56c7c7afd90a12b3dc49b189151c"}, - {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:9c1c4ad86351339c5f320ca372dfba6cb6beb25e8efc659bedd918d921956bae"}, - {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:27fe0f57bb5573104b5a6de5e4153c60814c711b29364c10a75a54bb6d7ff48d"}, - {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8ac68872c82f1add6a20bd489870c71b00ebacd2e9134a8aa3f98a0052ab4b0e"}, - {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cb2a8ec2bc07d3553ccebf0746bbf3d19426d1c6d1adbd4fa48925f66af7b9e8"}, - {file = "bcrypt-4.2.0-cp39-abi3-win32.whl", hash = "sha256:77800b7147c9dc905db1cba26abe31e504d8247ac73580b4aa179f98e6608f34"}, - {file = "bcrypt-4.2.0-cp39-abi3-win_amd64.whl", hash = "sha256:61ed14326ee023917ecd093ee6ef422a72f3aec6f07e21ea5f10622b735538a9"}, - {file = "bcrypt-4.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:39e1d30c7233cfc54f5c3f2c825156fe044efdd3e0b9d309512cc514a263ec2a"}, - {file = "bcrypt-4.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f4f4acf526fcd1c34e7ce851147deedd4e26e6402369304220250598b26448db"}, - {file = "bcrypt-4.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:1ff39b78a52cf03fdf902635e4c81e544714861ba3f0efc56558979dd4f09170"}, - {file = "bcrypt-4.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:373db9abe198e8e2c70d12b479464e0d5092cc122b20ec504097b5f2297ed184"}, - {file = "bcrypt-4.2.0.tar.gz", hash = "sha256:cf69eaf5185fd58f268f805b505ce31f9b9fc2d64b376642164e9244540c1221"}, + {file = "bcrypt-4.2.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:1340411a0894b7d3ef562fb233e4b6ed58add185228650942bdc885362f32c17"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ee315739bc8387aa36ff127afc99120ee452924e0df517a8f3e4c0187a0f5f"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dbd0747208912b1e4ce730c6725cb56c07ac734b3629b60d4398f082ea718ad"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:aaa2e285be097050dba798d537b6efd9b698aa88eef52ec98d23dcd6d7cf6fea"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:76d3e352b32f4eeb34703370e370997065d28a561e4a18afe4fef07249cb4396"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:b7703ede632dc945ed1172d6f24e9f30f27b1b1a067f32f68bf169c5f08d0425"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:89df2aea2c43be1e1fa066df5f86c8ce822ab70a30e4c210968669565c0f4685"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:04e56e3fe8308a88b77e0afd20bec516f74aecf391cdd6e374f15cbed32783d6"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cfdf3d7530c790432046c40cda41dfee8c83e29482e6a604f8930b9930e94139"}, + {file = "bcrypt-4.2.1-cp37-abi3-win32.whl", hash = "sha256:adadd36274510a01f33e6dc08f5824b97c9580583bd4487c564fc4617b328005"}, + {file = "bcrypt-4.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:8c458cd103e6c5d1d85cf600e546a639f234964d0228909d8f8dbeebff82d526"}, + {file = "bcrypt-4.2.1-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:8ad2f4528cbf0febe80e5a3a57d7a74e6635e41af1ea5675282a33d769fba413"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:909faa1027900f2252a9ca5dfebd25fc0ef1417943824783d1c8418dd7d6df4a"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cde78d385d5e93ece5479a0a87f73cd6fa26b171c786a884f955e165032b262c"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:533e7f3bcf2f07caee7ad98124fab7499cb3333ba2274f7a36cf1daee7409d99"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:687cf30e6681eeda39548a93ce9bfbb300e48b4d445a43db4298d2474d2a1e54"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:041fa0155c9004eb98a232d54da05c0b41d4b8e66b6fc3cb71b4b3f6144ba837"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f85b1ffa09240c89aa2e1ae9f3b1c687104f7b2b9d2098da4e923f1b7082d331"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c6f5fa3775966cca251848d4d5393ab016b3afed251163c1436fefdec3b02c84"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:807261df60a8b1ccd13e6599c779014a362ae4e795f5c59747f60208daddd96d"}, + {file = "bcrypt-4.2.1-cp39-abi3-win32.whl", hash = "sha256:b588af02b89d9fad33e5f98f7838bf590d6d692df7153647724a7f20c186f6bf"}, + {file = "bcrypt-4.2.1-cp39-abi3-win_amd64.whl", hash = "sha256:e84e0e6f8e40a242b11bce56c313edc2be121cec3e0ec2d76fce01f6af33c07c"}, + {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76132c176a6d9953cdc83c296aeaed65e1a708485fd55abf163e0d9f8f16ce0e"}, + {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e158009a54c4c8bc91d5e0da80920d048f918c61a581f0a63e4e93bb556d362f"}, + {file = "bcrypt-4.2.1.tar.gz", hash = "sha256:6765386e3ab87f569b276988742039baab087b2cdb01e809d74e74503c2faafe"}, ] [package.extras] tests = ["pytest (>=3.2.1,!=3.3.0)"] typecheck = ["mypy"] +[[package]] +name = "beautifulsoup4" +version = "4.12.3" +description = "Screen-scraping library" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, +] + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + [[package]] name = "black" -version = "24.8.0" +version = "24.10.0" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.8" -files = [ - {file = "black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6"}, - {file = "black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb"}, - {file = "black-24.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42"}, - {file = "black-24.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a"}, - {file = "black-24.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1"}, - {file = "black-24.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af"}, - {file = "black-24.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4"}, - {file = "black-24.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af"}, - {file = "black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368"}, - {file = "black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed"}, - {file = "black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018"}, - {file = "black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2"}, - {file = "black-24.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd"}, - {file = "black-24.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2"}, - {file = "black-24.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e"}, - {file = "black-24.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920"}, - {file = "black-24.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c"}, - {file = "black-24.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e"}, - {file = "black-24.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47"}, - {file = "black-24.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb"}, - {file = "black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed"}, - {file = "black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f"}, +python-versions = ">=3.9" +files = [ + {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, + {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, + {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"}, + {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"}, + {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"}, + {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"}, + {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"}, + {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"}, + {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"}, + {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"}, + {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"}, + {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"}, + {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"}, + {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"}, + {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"}, + {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"}, + {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"}, + {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"}, + {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"}, + {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"}, + {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"}, + {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"}, ] [package.dependencies] @@ -168,7 +251,7 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +d = ["aiohttp (>=3.10)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -223,83 +306,94 @@ files = [ [[package]] name = "cffi" -version = "1.17.0" +version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, - {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, - {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, - {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, - {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, - {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, - {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, - {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, - {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, - {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, - {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, - {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, - {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, - {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, - {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, - {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, + {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"}, ] [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" +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 = "cfn-lint" version = "0.75.1" @@ -323,101 +417,116 @@ sarif-om = ">=1.0.4,<1.1.0" [[package]] name = "charset-normalizer" -version = "3.3.2" +version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] [[package]] @@ -445,64 +554,157 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "colorlog" +version = "6.9.0" +description = "Add colours to the output of Python's logging module." +optional = false +python-versions = ">=3.6" +files = [ + {file = "colorlog-6.9.0-py3-none-any.whl", hash = "sha256:5906e71acd67cb07a71e779c47c4bcb45fb8c2993eebe9e5adcd6a6f1b283eff"}, + {file = "colorlog-6.9.0.tar.gz", hash = "sha256:bfba54a1b93b94f54e1f4fe48395725a3d92fd2a4af702f6bd70946bdc0c6ac2"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +development = ["black", "flake8", "mypy", "pytest", "types-colorama"] + +[[package]] +name = "coverage" +version = "7.6.8" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "coverage-7.6.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b39e6011cd06822eb964d038d5dff5da5d98652b81f5ecd439277b32361a3a50"}, + {file = "coverage-7.6.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:63c19702db10ad79151a059d2d6336fe0c470f2e18d0d4d1a57f7f9713875dcf"}, + {file = "coverage-7.6.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3985b9be361d8fb6b2d1adc9924d01dec575a1d7453a14cccd73225cb79243ee"}, + {file = "coverage-7.6.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:644ec81edec0f4ad17d51c838a7d01e42811054543b76d4ba2c5d6af741ce2a6"}, + {file = "coverage-7.6.8-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f188a2402f8359cf0c4b1fe89eea40dc13b52e7b4fd4812450da9fcd210181d"}, + {file = "coverage-7.6.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e19122296822deafce89a0c5e8685704c067ae65d45e79718c92df7b3ec3d331"}, + {file = "coverage-7.6.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:13618bed0c38acc418896005732e565b317aa9e98d855a0e9f211a7ffc2d6638"}, + {file = "coverage-7.6.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:193e3bffca48ad74b8c764fb4492dd875038a2f9925530cb094db92bb5e47bed"}, + {file = "coverage-7.6.8-cp310-cp310-win32.whl", hash = "sha256:3988665ee376abce49613701336544041f2117de7b7fbfe91b93d8ff8b151c8e"}, + {file = "coverage-7.6.8-cp310-cp310-win_amd64.whl", hash = "sha256:f56f49b2553d7dd85fd86e029515a221e5c1f8cb3d9c38b470bc38bde7b8445a"}, + {file = "coverage-7.6.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:86cffe9c6dfcfe22e28027069725c7f57f4b868a3f86e81d1c62462764dc46d4"}, + {file = "coverage-7.6.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d82ab6816c3277dc962cfcdc85b1efa0e5f50fb2c449432deaf2398a2928ab94"}, + {file = "coverage-7.6.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13690e923a3932e4fad4c0ebfb9cb5988e03d9dcb4c5150b5fcbf58fd8bddfc4"}, + {file = "coverage-7.6.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4be32da0c3827ac9132bb488d331cb32e8d9638dd41a0557c5569d57cf22c9c1"}, + {file = "coverage-7.6.8-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44e6c85bbdc809383b509d732b06419fb4544dca29ebe18480379633623baafb"}, + {file = "coverage-7.6.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:768939f7c4353c0fac2f7c37897e10b1414b571fd85dd9fc49e6a87e37a2e0d8"}, + {file = "coverage-7.6.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e44961e36cb13c495806d4cac67640ac2866cb99044e210895b506c26ee63d3a"}, + {file = "coverage-7.6.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3ea8bb1ab9558374c0ab591783808511d135a833c3ca64a18ec927f20c4030f0"}, + {file = "coverage-7.6.8-cp311-cp311-win32.whl", hash = "sha256:629a1ba2115dce8bf75a5cce9f2486ae483cb89c0145795603d6554bdc83e801"}, + {file = "coverage-7.6.8-cp311-cp311-win_amd64.whl", hash = "sha256:fb9fc32399dca861584d96eccd6c980b69bbcd7c228d06fb74fe53e007aa8ef9"}, + {file = "coverage-7.6.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e683e6ecc587643f8cde8f5da6768e9d165cd31edf39ee90ed7034f9ca0eefee"}, + {file = "coverage-7.6.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1defe91d41ce1bd44b40fabf071e6a01a5aa14de4a31b986aa9dfd1b3e3e414a"}, + {file = "coverage-7.6.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7ad66e8e50225ebf4236368cc43c37f59d5e6728f15f6e258c8639fa0dd8e6d"}, + {file = "coverage-7.6.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fe47da3e4fda5f1abb5709c156eca207eacf8007304ce3019eb001e7a7204cb"}, + {file = "coverage-7.6.8-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:202a2d645c5a46b84992f55b0a3affe4f0ba6b4c611abec32ee88358db4bb649"}, + {file = "coverage-7.6.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4674f0daa1823c295845b6a740d98a840d7a1c11df00d1fd62614545c1583787"}, + {file = "coverage-7.6.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:74610105ebd6f33d7c10f8907afed696e79c59e3043c5f20eaa3a46fddf33b4c"}, + {file = "coverage-7.6.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37cda8712145917105e07aab96388ae76e787270ec04bcb9d5cc786d7cbb8443"}, + {file = "coverage-7.6.8-cp312-cp312-win32.whl", hash = "sha256:9e89d5c8509fbd6c03d0dd1972925b22f50db0792ce06324ba069f10787429ad"}, + {file = "coverage-7.6.8-cp312-cp312-win_amd64.whl", hash = "sha256:379c111d3558272a2cae3d8e57e6b6e6f4fe652905692d54bad5ea0ca37c5ad4"}, + {file = "coverage-7.6.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0b0c69f4f724c64dfbfe79f5dfb503b42fe6127b8d479b2677f2b227478db2eb"}, + {file = "coverage-7.6.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c15b32a7aca8038ed7644f854bf17b663bc38e1671b5d6f43f9a2b2bd0c46f63"}, + {file = "coverage-7.6.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63068a11171e4276f6ece913bde059e77c713b48c3a848814a6537f35afb8365"}, + {file = "coverage-7.6.8-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f4548c5ead23ad13fb7a2c8ea541357474ec13c2b736feb02e19a3085fac002"}, + {file = "coverage-7.6.8-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b4b4299dd0d2c67caaaf286d58aef5e75b125b95615dda4542561a5a566a1e3"}, + {file = "coverage-7.6.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c9ebfb2507751f7196995142f057d1324afdab56db1d9743aab7f50289abd022"}, + {file = "coverage-7.6.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c1b4474beee02ede1eef86c25ad4600a424fe36cff01a6103cb4533c6bf0169e"}, + {file = "coverage-7.6.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d9fd2547e6decdbf985d579cf3fc78e4c1d662b9b0ff7cc7862baaab71c9cc5b"}, + {file = "coverage-7.6.8-cp313-cp313-win32.whl", hash = "sha256:8aae5aea53cbfe024919715eca696b1a3201886ce83790537d1c3668459c7146"}, + {file = "coverage-7.6.8-cp313-cp313-win_amd64.whl", hash = "sha256:ae270e79f7e169ccfe23284ff5ea2d52a6f401dc01b337efb54b3783e2ce3f28"}, + {file = "coverage-7.6.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:de38add67a0af869b0d79c525d3e4588ac1ffa92f39116dbe0ed9753f26eba7d"}, + {file = "coverage-7.6.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b07c25d52b1c16ce5de088046cd2432b30f9ad5e224ff17c8f496d9cb7d1d451"}, + {file = "coverage-7.6.8-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62a66ff235e4c2e37ed3b6104d8b478d767ff73838d1222132a7a026aa548764"}, + {file = "coverage-7.6.8-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09b9f848b28081e7b975a3626e9081574a7b9196cde26604540582da60235fdf"}, + {file = "coverage-7.6.8-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:093896e530c38c8e9c996901858ac63f3d4171268db2c9c8b373a228f459bbc5"}, + {file = "coverage-7.6.8-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a7b8ac36fd688c8361cbc7bf1cb5866977ece6e0b17c34aa0df58bda4fa18a4"}, + {file = "coverage-7.6.8-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:38c51297b35b3ed91670e1e4efb702b790002e3245a28c76e627478aa3c10d83"}, + {file = "coverage-7.6.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2e4e0f60cb4bd7396108823548e82fdab72d4d8a65e58e2c19bbbc2f1e2bfa4b"}, + {file = "coverage-7.6.8-cp313-cp313t-win32.whl", hash = "sha256:6535d996f6537ecb298b4e287a855f37deaf64ff007162ec0afb9ab8ba3b8b71"}, + {file = "coverage-7.6.8-cp313-cp313t-win_amd64.whl", hash = "sha256:c79c0685f142ca53256722a384540832420dff4ab15fec1863d7e5bc8691bdcc"}, + {file = "coverage-7.6.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3ac47fa29d8d41059ea3df65bd3ade92f97ee4910ed638e87075b8e8ce69599e"}, + {file = "coverage-7.6.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:24eda3a24a38157eee639ca9afe45eefa8d2420d49468819ac5f88b10de84f4c"}, + {file = "coverage-7.6.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4c81ed2820b9023a9a90717020315e63b17b18c274a332e3b6437d7ff70abe0"}, + {file = "coverage-7.6.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd55f8fc8fa494958772a2a7302b0354ab16e0b9272b3c3d83cdb5bec5bd1779"}, + {file = "coverage-7.6.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f39e2f3530ed1626c66e7493be7a8423b023ca852aacdc91fb30162c350d2a92"}, + {file = "coverage-7.6.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:716a78a342679cd1177bc8c2fe957e0ab91405bd43a17094324845200b2fddf4"}, + {file = "coverage-7.6.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:177f01eeaa3aee4a5ffb0d1439c5952b53d5010f86e9d2667963e632e30082cc"}, + {file = "coverage-7.6.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:912e95017ff51dc3d7b6e2be158dedc889d9a5cc3382445589ce554f1a34c0ea"}, + {file = "coverage-7.6.8-cp39-cp39-win32.whl", hash = "sha256:4db3ed6a907b555e57cc2e6f14dc3a4c2458cdad8919e40b5357ab9b6db6c43e"}, + {file = "coverage-7.6.8-cp39-cp39-win_amd64.whl", hash = "sha256:428ac484592f780e8cd7b6b14eb568f7c85460c92e2a37cb0c0e5186e1a0d076"}, + {file = "coverage-7.6.8-pp39.pp310-none-any.whl", hash = "sha256:5c52a036535d12590c32c49209e79cabaad9f9ad8aa4cbd875b68c4d67a9cbce"}, + {file = "coverage-7.6.8.tar.gz", hash = "sha256:8b2b8503edb06822c86d82fa64a4a5cb0760bb8f31f26e138ec743f422f37cfc"}, +] + +[package.extras] +toml = ["tomli"] + [[package]] name = "cryptography" -version = "43.0.1" +version = "44.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false -python-versions = ">=3.7" -files = [ - {file = "cryptography-43.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a"}, - {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042"}, - {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494"}, - {file = "cryptography-43.0.1-cp37-abi3-win32.whl", hash = "sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2"}, - {file = "cryptography-43.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d"}, - {file = "cryptography-43.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1"}, - {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa"}, - {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4"}, - {file = "cryptography-43.0.1-cp39-abi3-win32.whl", hash = "sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47"}, - {file = "cryptography-43.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ea25acb556320250756e53f9e20a4177515f012c9eaea17eb7587a8c4d8ae034"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c1332724be35d23a854994ff0b66530119500b6053d0bd3363265f7e5e77288d"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1007b3ef89946dbbb515aeeb41e30203b004f0b4b00e5e16078b518563289"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5b43d1ea6b378b54a1dc99dd8a2b5be47658fe9a7ce0a58ff0b55f4b43ef2b84"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:88cce104c36870d70c49c7c8fd22885875d950d9ee6ab54df2745f83ba0dc365"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d3cdb25fa98afdd3d0892d132b8d7139e2c087da1712041f6b762e4f807cc96"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e710bf40870f4db63c3d7d929aa9e09e4e7ee219e703f949ec4073b4294f6172"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7c05650fe8023c5ed0d46793d4b7d7e6cd9c04e68eabe5b0aeea836e37bdcec2"}, - {file = "cryptography-43.0.1.tar.gz", hash = "sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d"}, +python-versions = "!=3.9.0,!=3.9.1,>=3.7" +files = [ + {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, + {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, + {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, + {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, + {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, + {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, + {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, ] [package.dependencies] cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] -nox = ["nox"] -pep8test = ["check-sdist", "click", "mypy", "ruff"] -sdist = ["build"] +docs = ["sphinx (>=5.3.0)", "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)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "cryptography-vectors (==43.0.1)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "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 = "datamodel-code-generator" -version = "0.26.0" +version = "0.26.3" description = "Datamodel Code Generator" optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "datamodel_code_generator-0.26.0-py3-none-any.whl", hash = "sha256:29af7c1991d6b346d4f6cdf2f11b74c09d84c73b1ed7229adc4f64316dfbb48d"}, - {file = "datamodel_code_generator-0.26.0.tar.gz", hash = "sha256:5d1db3dd4d31ee8bb70426d8705f5b059bea15e0dd79e015a28373b5da98ff00"}, + {file = "datamodel_code_generator-0.26.3-py3-none-any.whl", hash = "sha256:f1f8f1cef14f138fa239f987d4640837bb68d53c5f08d8673a7bde275b929fd8"}, + {file = "datamodel_code_generator-0.26.3.tar.gz", hash = "sha256:b58e0800eb6448e1d1df02f4586207c1e3631c4a188531d154b00b3cf2f95fd8"}, ] [package.dependencies] @@ -540,38 +742,64 @@ files = [ [[package]] name = "deprecated" -version = "1.2.14" +version = "1.2.15" description = "Python @deprecated decorator to deprecate old python classes, functions or methods." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" files = [ - {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, - {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, + {file = "Deprecated-1.2.15-py2.py3-none-any.whl", hash = "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320"}, + {file = "deprecated-1.2.15.tar.gz", hash = "sha256:683e561a90de76239796e6b6feac66b99030d2dd3fcf61ef996330f14bbb9b0d"}, ] [package.dependencies] wrapt = ">=1.10,<2" [package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "jinja2 (>=3.0.3,<3.1.0)", "setuptools", "sphinx (<2)", "tox"] + +[[package]] +name = "dill" +version = "0.3.9" +description = "serialize all of Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a"}, + {file = "dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] + +[[package]] +name = "distlib" +version = "0.3.9" +description = "Distribution utilities" +optional = false +python-versions = "*" +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 = "dnspython" -version = "2.6.1" +version = "2.7.0" description = "DNS toolkit" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, - {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, + {file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"}, + {file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"}, ] [package.extras] -dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] -dnssec = ["cryptography (>=41)"] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "hypercorn (>=0.16.0)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "quart-trio (>=0.11.0)", "sphinx (>=7.2.0)", "sphinx-rtd-theme (>=2.0.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] +dnssec = ["cryptography (>=43)"] doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] -doq = ["aioquic (>=0.9.25)"] -idna = ["idna (>=3.6)"] +doq = ["aioquic (>=1.0.0)"] +idna = ["idna (>=3.7)"] trio = ["trio (>=0.23)"] wmi = ["wmi (>=1.5.1)"] @@ -665,13 +893,13 @@ files = [ [[package]] name = "exasol-integration-test-docker-environment" -version = "3.1.0" +version = "3.2.0" description = "Integration Test Docker Environment for Exasol" optional = false python-versions = "<4,>=3.8" files = [ - {file = "exasol_integration_test_docker_environment-3.1.0-py3-none-any.whl", hash = "sha256:ce3cf917bd660ef5e1c59281ba0c1ea7c7dc3c43c9454040a6e1a3d90124a1e4"}, - {file = "exasol_integration_test_docker_environment-3.1.0.tar.gz", hash = "sha256:dbcbb967bb3458f74c8764a1cfc4f62ab215b79ee754bb4d17d4ef54c74f7f0a"}, + {file = "exasol_integration_test_docker_environment-3.2.0-py3-none-any.whl", hash = "sha256:b0fc41a70b73ec5ad43171e2c8fcf76a54a1eb31befa09e6a3214af55f1c93fc"}, + {file = "exasol_integration_test_docker_environment-3.2.0.tar.gz", hash = "sha256:47b11dde66be0149d54cfa6d7eebc4665bd996fccb22f64ce6489a07cec7b331"}, ] [package.dependencies] @@ -697,13 +925,13 @@ simplejson = ">=3.16.0" [[package]] name = "exasol-saas-api" -version = "0.9.0" +version = "0.10.0" description = "API enabling Python applications connecting to Exasol database SaaS instances and using their SaaS services" optional = false python-versions = "<4.0.0,>=3.10.0" files = [ - {file = "exasol_saas_api-0.9.0-py3-none-any.whl", hash = "sha256:86b350ebc7257cf0e2f532e0fa0683ed53347ec7a96f7410a952d49ccc038aa0"}, - {file = "exasol_saas_api-0.9.0.tar.gz", hash = "sha256:0a6f051dd508b41eec66cefcf57369ccace04a8bc2e546a588202fa3a50dfee8"}, + {file = "exasol_saas_api-0.10.0-py3-none-any.whl", hash = "sha256:13ad9f62e37e95e0359da875d44369c38c511b72b374cdc46bfffe0de2d3f730"}, + {file = "exasol_saas_api-0.10.0.tar.gz", hash = "sha256:8e7febf0c1eb777c38f5631cfb8d45c82a63b463a1e43134117c7fde508a8504"}, ] [package.dependencies] @@ -753,6 +981,42 @@ importlib_metadata = ">=4.6.0" importlib-resources = ">=6.4.0" networkx = ">=3.3.0,<4.0.0" +[[package]] +name = "exasol-toolbox" +version = "0.18.0" +description = "Your one-stop solution for managing all standard tasks and core workflows of your Python project." +optional = false +python-versions = "<4.0,>=3.9" +files = [ + {file = "exasol_toolbox-0.18.0-py3-none-any.whl", hash = "sha256:db6a5f421b710ce4bbef7c8bb9a3e671c7d5d3400f6f95e8fa80e06344244e87"}, + {file = "exasol_toolbox-0.18.0.tar.gz", hash = "sha256:93986545bf9e077114f61627bca741bac778a02f9420d4612fe1bcca109afd51"}, +] + +[package.dependencies] +bandit = {version = ">=1.7.9,<2.0.0", extras = ["toml"]} +black = ">=24.1.0" +coverage = ">=6.4.4,<8.0.0" +furo = ">=2022.9.15" +import-linter = ">=2.0,<3.0" +importlib-resources = ">=5.12.0" +isort = ">=5.12.0,<6.0.0" +jinja2 = ">=3.1.4,<4.0.0" +mypy = ">=0.971" +myst-parser = ">=2.0.0,<4" +nox = ">=2022.8.7" +pluggy = ">=1.5.0,<2.0.0" +pre-commit = ">=3.1.1,<4" +prysk = {version = ">0.17.0,<1", extras = ["pytest-plugin"]} +pylint = ">=2.15.4" +pytest = ">=7.2.2,<9" +pyupgrade = ">=2.38.2,<4.0.0" +shibuya = ">=2024.5.14" +sphinx = ">=5.3,<8" +sphinx-copybutton = ">=0.5.0,<0.6.0" +sphinx-design = ">=0.5.0,<1" +sphinx-inline-tabs = ">=2023.4.21,<2024.0.0" +typer = {version = ">=0.7.0", extras = ["all"]} + [[package]] name = "exceptiongroup" version = "1.2.2" @@ -787,6 +1051,39 @@ paramiko = ">=2.4" [package.extras] pytest = ["pytest (>=7)"] +[[package]] +name = "filelock" +version = "3.16.1" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, + {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] +typing = ["typing-extensions (>=4.12.2)"] + +[[package]] +name = "furo" +version = "2024.8.6" +description = "A clean customisable Sphinx documentation theme." +optional = false +python-versions = ">=3.8" +files = [ + {file = "furo-2024.8.6-py3-none-any.whl", hash = "sha256:6cd97c58b47813d3619e63e9081169880fbe331f0ca883c871ff1f3f11814f5c"}, + {file = "furo-2024.8.6.tar.gz", hash = "sha256:b63e4cee8abfc3136d3bc03a3d45a76a850bada4d6374d24c1716b0e01394a01"}, +] + +[package.dependencies] +beautifulsoup4 = "*" +pygments = ">=2.7" +sphinx = ">=6.0,<9.0" +sphinx-basic-ng = ">=1.0.0.beta2" + [[package]] name = "genson" version = "1.3.0" @@ -830,6 +1127,109 @@ gitdb = ">=4.0.1,<5" doc = ["sphinx (==4.3.2)", "sphinx-autodoc-typehints", "sphinx-rtd-theme", "sphinxcontrib-applehelp (>=1.0.2,<=1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (>=2.0.0,<=2.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)"] test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions"] +[[package]] +name = "grimp" +version = "3.5" +description = "Builds a queryable graph of the imports within one or more Python packages." +optional = false +python-versions = ">=3.9" +files = [ + {file = "grimp-3.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:73538d288752ea7b10fdfd05406a1c1507531b5763ad97994cd1646283112d93"}, + {file = "grimp-3.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c2f4a16626b6de9f5ea6e87e685e5810be7712461ef29260c67b5b868f64ae5"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5d495c9d527535872d78dfbc0f74f2650ad6b13e12f7d8b11da9d91ebaf2bda"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b2ea1402221bf00dee7ae5357ef549151b1ad213a892cfe734b7156413d99a38"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a71a6c4e411adfeb6b8ba0fc5eff60505bf758aea9e4c7169a6fce5a57833cf"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60e92da02c72eebb9f1aaecd48c3b9fd234de6a6427da6b2232918cb88b409c0"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5f9db004a253329f480a3ec0b0929558a6427f2db0610900b57fded591f6e3be"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fa6188b077339f030973b6cb3e1947175c45f6f9a472162435a5f80afd21805"}, + {file = "grimp-3.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3140ec48aaa43e124a735878fdf527cad7fa65230c2b69abc8124a22afb755bc"}, + {file = "grimp-3.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:7e6f9af573b59bb0dd07e182482277922889329672cb418a0e8617de3aaf4922"}, + {file = "grimp-3.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:374ad436ffdd29ffd6ae4b2a345783aad08f0d674b1ee01b55b824420b6f8e85"}, + {file = "grimp-3.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b10e7d4f67bae4326275b63aa1987652f6d673264fd8e2eb6804d64e0bfc4fa2"}, + {file = "grimp-3.5-cp310-none-win32.whl", hash = "sha256:077a0e5fe97a95183e9302615dd10b69f4b378efb9158504a57b7e71871259a3"}, + {file = "grimp-3.5-cp310-none-win_amd64.whl", hash = "sha256:80a04c1559bfe45a8cb49caf160391e180cf24db9af443f34ed01e5ededba025"}, + {file = "grimp-3.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3d2130cbdbcd01ae65ebe39520f8a38e5f4ed445a4989eb1c8c0796759ddc5c6"}, + {file = "grimp-3.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b2f9fdafc36dcf3ae80f7da2696bc7cbd1ef73ddd0f043446d63facc474cb2ab"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2320207ad620ed383533f3178783b5d82a9f100dbc9d7fc1c50e40275dc9a002"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24b83512a3195c4f927e3968b0c61db9c6d5758f748bf6d3fec197f0b61309e8"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6abffdfe3b70723fe6a61f3c3e2c5c415a18d06387929bf4b223aa050c618d3"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ba4988e1c96415d02f49b4677e1a219c048c2cbb358c812c99b303310f4adaa"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d3d11d7ed0b0313cb378a5d138f4644189ffc77fb358d60d21d54c3d32f0a5a5"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b175fb636e7d2d1e6feb79ad09794740b03458eb838c341e51112beee8ae5f6e"}, + {file = "grimp-3.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a93990401856d4ba7620faa123d1949059b2b5c169b6ef1bdf4d1f8df316c0a1"}, + {file = "grimp-3.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f8676bc2e0ecdc61376aba038b8ebd3380630a78f1c44426b393dd616eb3899b"}, + {file = "grimp-3.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e270c5342302aabf97ad4e810101fcfc38c5f9360cbdd5b6f653ce43f29bf1bf"}, + {file = "grimp-3.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e6682704bd7c3a2f9098747b524038f15df4d1456aded3265596fb2360fca872"}, + {file = "grimp-3.5-cp311-none-win32.whl", hash = "sha256:7aa32379f91494d1f1779a3e469ebf5d3e515c8c978bb5d585f6a87c297f45a1"}, + {file = "grimp-3.5-cp311-none-win_amd64.whl", hash = "sha256:bbcd2468a2609a8c662429ed34357ff50efb194c00c1c88a6336c92d662439ad"}, + {file = "grimp-3.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e09db10a7395b3930ebe95eee2ac440c5ee24ce77b6171e807a8aacb4625cca2"}, + {file = "grimp-3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:977c6b220671d7332657be13c51e4f6f38c76d911680f844806a5346142910fc"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f4e2159c3c75b62f9ea59a539ac93f89b9ced38811b453d3b78be62c8395b01"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8d7bb3f2178b3a8115eca5f6ea5f766a283b8a7ede84fbbdda2a40b7d28624cb"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e023c883a83fa8ca1a613b1e8b39834545818971a8d94977bcd4b491537cde"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce7440c8498fa5b47acfffce7fe42d6c63be94dbe2fff7f524522fa7e422e0eb"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0724f60d7cccf2c94616f0282ba8eec85a1956b59b8d22274409a60539fc462"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a486e985fa4d4fb9dc6ebb094ed17a293809ff5cf6532bba26a5ae064d350539"}, + {file = "grimp-3.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a98f06d58b0cb7b8bfe5846d8ab07adb36c313dd3c7298836ddd3df98a8344a"}, + {file = "grimp-3.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:13924943d6e5a0f0150c8f2a05d87042f03510b633b198ac3dd5c4274d36f28c"}, + {file = "grimp-3.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8194ac4c54fac7641bfcef332aaec1af590e97b2aa8993e47a7c51ff84220f44"}, + {file = "grimp-3.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3f83b85aad278dfcaf2bf27b9cfa6dd6533dd96ecc510ba3bc0141344686857f"}, + {file = "grimp-3.5-cp312-none-win32.whl", hash = "sha256:f88307f0e50883ab73cc59164a5a9396e8e1c8b68b8e2edef68d478b91d81000"}, + {file = "grimp-3.5-cp312-none-win_amd64.whl", hash = "sha256:6fa422c150597f8e6ad51c4fe2b271747057abe638acca5eebb2162e536065ed"}, + {file = "grimp-3.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:448dba63f938d0e13e6121559749816e3b2644202c912cc308e7608c6034737a"}, + {file = "grimp-3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:17113aba41269d0ee91512c96eeb850c7c668440c6a8e0bfc94d17762184b293"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6a55614945c319d1dc692c3e43f3a02b80c116a1298e593f5f887b97e6c983a"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aba7ce7839b72efb4c6d06404d2b2a3026e28dd89816f4e546b3cd6626cbeeb1"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eaedfba320a70d87b14acb25a685c8629586b943129c71ffd02b47d9531c11ce"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60a9afd3dd00ad1d301a07f97e26bc9ecdc3d2db39ab6ac46c315a7dea0a96cb"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:11c66039c0475e5c9fc6a086264f11870181ae79f603caa5dffa1411ddad636b"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bff39a0061790f074f86a7841cd8e6064aa7b2208cb1ee5c3f2e685dead2b66e"}, + {file = "grimp-3.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cf7f5367c4a87b8e9f08c09e7401d2d73f21cb65d6142445819f9df0d6ab3f6b"}, + {file = "grimp-3.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:edee4b087f007dab8b65461caf6a1b67b2f9480cceb5f6aceea87008d8f283c4"}, + {file = "grimp-3.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6af125013ad2a56c18f2f53a3fcabbfbe96c70374abecd6f14b82dc444726ebe"}, + {file = "grimp-3.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:24aabae0183ca5fd5a710257ff37120b55d8e6d6d4cbb2c08481552832e5c901"}, + {file = "grimp-3.5-cp313-none-win32.whl", hash = "sha256:506091bfd600dd7ad427586998ef5e54a2098485148a1499bd9af5943d2fb0b7"}, + {file = "grimp-3.5-cp313-none-win_amd64.whl", hash = "sha256:099388df82d922ddc589f362f1a523ab053c8dee5d29a6b622b2cddf481c6a2f"}, + {file = "grimp-3.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:4bec3fbe008c8f8c546a640e6e74a519c9d33720c315c72013f1b6455543d1a9"}, + {file = "grimp-3.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea11cf5a0e1cd8fb1a119304128c85162bb2e4ad49c7583ab7835c783fc45457"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a63b444410c78763b506c9f31cd813b5c3ff3ed14100d102f1a705201f70f2f"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fffb6e7b066636e69f1b70ed617891d04efc14c8d740015026c6c01ede03196f"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:057a4afece42540d51817f8acca889bde87d78720ff7bf51833b27a83ea0a74b"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7a59650956cd1e29810a5611395560c33a27cf3acddd587437745c8b136a820"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57d35306da73b62d3d29fc482e8add9e6781fc004ca080c1b74b0d21d62e1613"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb3a24b5f4c1b19a19712855dbb82a7d82d8dc565e99464c3fb15fefd5ae81ae"}, + {file = "grimp-3.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bb3adae6cc3938aa487fc206c4a44af026907ec98322c738e5f2f3435e34e7cd"}, + {file = "grimp-3.5-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:b14b00f15bf1e5901ec50fad0b4238522aef7b37b0cce770c100e387e278cd6e"}, + {file = "grimp-3.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:40c6473a12ac8f71f66d3215269011fd8e480b99947f1dbb12e1d83b3fc3df74"}, + {file = "grimp-3.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2967cef66f123f9c90281ad2525995302dea3d52416e5177b3eb9cd7eea0f617"}, + {file = "grimp-3.5-cp39-none-win32.whl", hash = "sha256:d1aeb5ffb188d10a28a4508cc33e5f06f03a032c484a8b2d5bd0a2fad115d3c2"}, + {file = "grimp-3.5-cp39-none-win_amd64.whl", hash = "sha256:98d6be78ffabc28016d313847ff990f2625b6d2c7015edd34f0bad4be97bb648"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:952c0ea0c652c3aea99411921e1a43b015c4ef96466a8b0d78b8d15c820228ca"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:33da59560da889ad41018f0c93f58833018922a1fff7ae44bcf20a0644bda9fc"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f8ee28ff91df8e6c8ce2ea4334bb487ebd7adeef94f6d0170314cb3e0179e272"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4dca05a5beb2346630968127612ebd7771084890297d4de25cde24ac937dc11b"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bb6feb9667349fba87d85d210a85480e43dc96a65b6229baf3a0439ebf44613f"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b35460a314a720d1a332222621dc9a8b412d9c56bc19866019d6c6451cc09dc"}, + {file = "grimp-3.5-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:03350ec0378d984d6d8ff09fa607ecdeca59d8ee4636a029f1a7475e8a9cd74a"}, + {file = "grimp-3.5-pp310-pypy310_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:d9ef6c6c8d1d64eabb555a7ecf4ec3dce91d0ade54b3724a03169a298a65f2f7"}, + {file = "grimp-3.5-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:813ec51de74800043c543ab2979dd7b383aeb6b5cd52adf092ef7fa69c6c2b2f"}, + {file = "grimp-3.5-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1966b0059b38b5aeca9da3fb3c036590d783d7330eb9e1300b2779f7e6d41650"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca26b2e1acd3ecfba14a9987dc2cf81b44cd05be755e7a112e05ae8c54626548"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d2257a4abfe40578e546e2f74b698b58645aeb3137fd7c3c95ac49a84ebe3009"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c07bab1917ae798381a63f065e804fb1b5797bb727bb17671453bb6c02639944"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74b035af58fa6171f07972bac3cb970ac409c10c222515c913b468c7e067f23a"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ba0066ab7d081c1637947a82c744081654150e9dcb6967ae9bdad3a69a55224c"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e6f7d75e9f32022b57ca9d83239a0325a495cb6dc3ddb629654aa3d30f0a88"}, + {file = "grimp-3.5-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:697ec33b8ed0803b5c7ca68d297d90cfc36940b2a4fc64651bf29953f126ada3"}, + {file = "grimp-3.5-pp39-pypy39_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:1f3b3a8f309c9a9026324745f744ffc60cd54d1a07bc1ddbb1ba73e7bacb2a78"}, + {file = "grimp-3.5-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:320bcca184841f7935df8c50636607e452ebea1891e9985a6fe9b82b96a3cd6c"}, + {file = "grimp-3.5-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed910d51b1105799882beb3936d5dcb7617ae17494864bbef01617e52c9866f4"}, + {file = "grimp-3.5.tar.gz", hash = "sha256:dc9560aed1d82222b361fe5f312a775b15a96b9237670f3a9fb20f44d30d5762"}, +] + +[package.dependencies] +typing-extensions = ">=3.10.0.0" + [[package]] name = "h11" version = "0.14.0" @@ -843,13 +1243,13 @@ files = [ [[package]] name = "httpcore" -version = "1.0.5" +version = "1.0.7" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, - {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, + {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, + {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, ] [package.dependencies] @@ -860,7 +1260,7 @@ h11 = ">=0.13,<0.15" asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.26.0)"] +trio = ["trio (>=0.22.0,<1.0)"] [[package]] name = "httpx" @@ -901,17 +1301,34 @@ files = [ [package.dependencies] pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""} +[[package]] +name = "identify" +version = "2.6.3" +description = "File identification library for Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "identify-2.6.3-py2.py3-none-any.whl", hash = "sha256:9edba65473324c2ea9684b1f944fe3191db3345e50b6d04571d10ed164f8d7bd"}, + {file = "identify-2.6.3.tar.gz", hash = "sha256:62f5dae9b5fef52c84cc188514e9ea4f3f636b1d8799ab5ebc475471f9e47a02"}, +] + +[package.extras] +license = ["ukkonen"] + [[package]] name = "idna" -version = "3.8" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" files = [ - {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, - {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, + {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 = "ifaddr" version = "0.2.0" @@ -923,34 +1340,66 @@ files = [ {file = "ifaddr-0.2.0.tar.gz", hash = "sha256:cc0cbfcaabf765d44595825fb96a99bb12c79716b73b44330ea38ee2b0c4aed4"}, ] +[[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.*" +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 = "import-linter" +version = "2.1" +description = "Enforces rules for the imports within and between Python packages." +optional = false +python-versions = ">=3.9" +files = [ + {file = "import_linter-2.1-py3-none-any.whl", hash = "sha256:324d65035f0252a8e432f60256b0d0d32d8d5d6e4f8fd29716688b09d7a2217a"}, + {file = "import_linter-2.1.tar.gz", hash = "sha256:393fadb2e91304c22c5ceab575213ed2b6a794abc7bd05ab345f2430930b2eae"}, +] + +[package.dependencies] +click = ">=6" +grimp = ">=3.2" +tomli = {version = ">=1.2.1", markers = "python_version < \"3.11\""} +typing-extensions = ">=3.10.0.0" + [[package]] name = "importlib-metadata" -version = "8.4.0" +version = "8.5.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1"}, - {file = "importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"}, + {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, + {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, ] [package.dependencies] -zipp = ">=0.5" +zipp = ">=3.20" [package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +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)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +type = ["pytest-mypy"] [[package]] name = "importlib-resources" -version = "6.4.4" +version = "6.4.5" description = "Read resources from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_resources-6.4.4-py3-none-any.whl", hash = "sha256:dda242603d1c9cd836c3368b1174ed74cb4049ecd209e7a1a0104620c18c5c11"}, - {file = "importlib_resources-6.4.4.tar.gz", hash = "sha256:20600c8b7361938dc0bb2d5ec0297802e575df486f5a544fa414da65e13721f7"}, + {file = "importlib_resources-6.4.5-py3-none-any.whl", hash = "sha256:ac29d5f956f01d5e4bb63102a5a19957f1b9175e45649977264a1416783bb717"}, + {file = "importlib_resources-6.4.5.tar.gz", hash = "sha256:980862a1d16c9e147a59603677fa2aa5fd82b87f223b6cb870695bcfce830065"}, ] [package.extras] @@ -1083,19 +1532,21 @@ jsonpointer = ">=1.9" [[package]] name = "jsonpickle" -version = "3.3.0" -description = "Python library for serializing arbitrary object graphs into JSON" +version = "4.0.0" +description = "jsonpickle encodes/decodes any Python object to/from JSON" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "jsonpickle-3.3.0-py3-none-any.whl", hash = "sha256:287c12143f35571ab00e224fa323aa4b090d5a7f086f5f494d7ee9c7eb1a380a"}, - {file = "jsonpickle-3.3.0.tar.gz", hash = "sha256:ab467e601e5b1a1cd76f1819d014795165da071744ef30bf3786e9bc549de25a"}, + {file = "jsonpickle-4.0.0-py3-none-any.whl", hash = "sha256:53730b9e094bc41f540bfdd25eaf6e6cf43811590e9e1477abcec44b866ddcd9"}, + {file = "jsonpickle-4.0.0.tar.gz", hash = "sha256:fc670852b204d77601b08f8f9333149ac37ab6d3fe4e6ed3b578427291f63736"}, ] [package.extras] -docs = ["furo", "rst.linker (>=1.9)", "sphinx"] -packaging = ["build", "twine"] -testing = ["bson", "ecdsa", "feedparser", "gmpy2", "numpy", "pandas", "pymongo", "pytest (>=3.5,!=3.7.3)", "pytest-benchmark", "pytest-benchmark[histogram]", "pytest-checkdocs (>=1.2.3)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-ruff (>=0.2.1)", "scikit-learn", "scipy", "scipy (>=1.9.3)", "simplejson", "sqlalchemy", "ujson"] +cov = ["pytest-cov"] +dev = ["black", "pyupgrade"] +docs = ["furo", "rst.linker (>=1.9)", "sphinx (>=3.5)"] +packaging = ["build", "setuptools (>=61.2)", "setuptools-scm[toml] (>=6.0)", "twine"] +testing = ["PyYAML", "atheris (>=2.3.0,<2.4.0)", "bson", "ecdsa", "feedparser", "gmpy2", "numpy", "pandas", "pymongo", "pytest (>=6.0,!=8.1.*)", "pytest-benchmark", "pytest-benchmark[histogram]", "pytest-checkdocs (>=1.2.3)", "pytest-enabler (>=1.0.1)", "pytest-ruff (>=0.2.1)", "scikit-learn", "scipy", "scipy (>=1.9.3)", "simplejson", "sqlalchemy", "ujson"] [[package]] name = "jsonpointer" @@ -1131,13 +1582,13 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- [[package]] name = "jsonschema-specifications" -version = "2023.12.1" +version = "2024.10.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, - {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, + {file = "jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf"}, + {file = "jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272"}, ] [package.dependencies] @@ -1189,75 +1640,194 @@ jsonschema = ["jsonschema"] prometheus = ["prometheus-client (>=0.5,<0.15)"] toml = ["toml (<2.0.0)"] +[[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" +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] +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 = "2.1.5" +version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false +python-versions = ">=3.9" +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 = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mdit-py-plugins" +version = "0.4.2" +description = "Collection of plugins for markdown-it-py" +optional = false +python-versions = ">=3.8" +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" files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] +[[package]] +name = "mypy" +version = "1.13.0" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"}, + {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"}, + {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"}, + {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"}, + {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"}, + {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"}, + {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"}, + {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"}, + {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"}, + {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"}, + {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"}, + {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"}, + {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"}, + {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"}, + {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"}, + {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"}, + {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"}, + {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"}, + {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"}, + {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"}, + {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"}, + {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.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.0.0" @@ -1269,6 +1839,32 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "myst-parser" +version = "3.0.1" +description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," +optional = false +python-versions = ">=3.8" +files = [ + {file = "myst_parser-3.0.1-py3-none-any.whl", hash = "sha256:6457aaa33a5d474aca678b8ead9b3dc298e89c68e67012e73146ea6fd54babf1"}, + {file = "myst_parser-3.0.1.tar.gz", hash = "sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87"}, +] + +[package.dependencies] +docutils = ">=0.18,<0.22" +jinja2 = "*" +markdown-it-py = ">=3.0,<4.0" +mdit-py-plugins = ">=0.4,<1.0" +pyyaml = "*" +sphinx = ">=6,<8" + +[package.extras] +code-style = ["pre-commit (>=3.0,<4.0)"] +linkify = ["linkify-it-py (>=2.0,<3.0)"] +rtd = ["ipython", "sphinx (>=7)", "sphinx-autodoc2 (>=0.5.0,<0.6.0)", "sphinx-book-theme (>=1.1,<2.0)", "sphinx-copybutton", "sphinx-design", "sphinx-pyscript", "sphinx-tippy (>=0.4.3)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.9.0,<0.10.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] +testing = ["beautifulsoup4", "coverage[toml]", "defusedxml", "pytest (>=8,<9)", "pytest-cov", "pytest-param-files (>=0.6.0,<0.7.0)", "pytest-regressions", "sphinx-pytest"] +testing-docutils = ["pygments", "pytest (>=8,<9)", "pytest-param-files (>=0.6.0,<0.7.0)"] + [[package]] name = "netaddr" version = "1.3.0" @@ -1285,42 +1881,76 @@ nicer-shell = ["ipython"] [[package]] name = "networkx" -version = "3.3" +version = "3.4.2" description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = ">=3.10" files = [ - {file = "networkx-3.3-py3-none-any.whl", hash = "sha256:28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2"}, - {file = "networkx-3.3.tar.gz", hash = "sha256:0c127d8b2f4865f59ae9cb8aafcd60b5c70f3241ebd66f7defad7c4ab90126c9"}, + {file = "networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"}, + {file = "networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1"}, ] [package.extras] -default = ["matplotlib (>=3.6)", "numpy (>=1.23)", "pandas (>=1.4)", "scipy (>=1.9,!=1.11.0,!=1.11.1)"] +default = ["matplotlib (>=3.7)", "numpy (>=1.24)", "pandas (>=2.0)", "scipy (>=1.10,!=1.11.0,!=1.11.1)"] developer = ["changelist (==0.5)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"] -doc = ["myst-nb (>=1.0)", "numpydoc (>=1.7)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.14)", "sphinx (>=7)", "sphinx-gallery (>=0.14)", "texext (>=0.6.7)"] -extra = ["lxml (>=4.6)", "pydot (>=2.0)", "pygraphviz (>=1.12)", "sympy (>=1.10)"] +doc = ["intersphinx-registry", "myst-nb (>=1.1)", "numpydoc (>=1.8.0)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.15)", "sphinx (>=7.3)", "sphinx-gallery (>=0.16)", "texext (>=0.6.7)"] +example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "momepy (>=0.7.2)", "osmnx (>=1.9)", "scikit-learn (>=1.5)", "seaborn (>=0.13)"] +extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"] test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] +[[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" +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 = "nox" +version = "2024.10.9" +description = "Flexible test automation." +optional = false +python-versions = ">=3.8" +files = [ + {file = "nox-2024.10.9-py3-none-any.whl", hash = "sha256:1d36f309a0a2a853e9bccb76bbef6bb118ba92fa92674d15604ca99adeb29eab"}, + {file = "nox-2024.10.9.tar.gz", hash = "sha256:7aa9dc8d1c27e9f45ab046ffd1c3b2c4f7c91755304769df231308849ebded95"}, +] + +[package.dependencies] +argcomplete = ">=1.9.4,<4" +colorlog = ">=2.6.1,<7" +packaging = ">=20.9" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} +virtualenv = ">=20.14.1" + +[package.extras] +tox-to-nox = ["jinja2", "tox"] +uv = ["uv (>=0.1.6)"] + [[package]] name = "packaging" -version = "24.1" +version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] [[package]] name = "paramiko" -version = "3.4.1" +version = "3.5.0" description = "SSH2 protocol library" optional = false python-versions = ">=3.6" files = [ - {file = "paramiko-3.4.1-py3-none-any.whl", hash = "sha256:8e49fd2f82f84acf7ffd57c64311aa2b30e575370dc23bdb375b10262f7eac32"}, - {file = "paramiko-3.4.1.tar.gz", hash = "sha256:8b15302870af7f6652f2e038975c1d2973f06046cb5d7d65355668b3ecbece0c"}, + {file = "paramiko-3.5.0-py3-none-any.whl", hash = "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9"}, + {file = "paramiko-3.5.0.tar.gz", hash = "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124"}, ] [package.dependencies] @@ -1357,19 +1987,19 @@ files = [ [[package]] name = "platformdirs" -version = "4.2.2" +version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] [[package]] name = "pluggy" @@ -1405,6 +2035,42 @@ docs = ["sphinx (>=1.7.1)"] redis = ["redis"] tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "pytest-timeout (>=2.1.0)", "redis", "sphinx (>=6.0.0)", "types-redis"] +[[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" +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 = "prysk" +version = "0.20.0" +description = "Functional tests for command line applications" +optional = false +python-versions = "<4.0.0,>=3.8" +files = [ + {file = "prysk-0.20.0-py3-none-any.whl", hash = "sha256:3758f59febe1ff27710c8ba69a8edad42286050d041ed8df519fc4bbeea41133"}, + {file = "prysk-0.20.0.tar.gz", hash = "sha256:3499d24c9c8d534754d3915218cb2ab59cf59a8d6f37acfb68dc582650e67e33"}, +] + +[package.dependencies] +pytest-prysk = {version = ">=0.2.0,<0.3.0", optional = true, markers = "extra == \"pytest-plugin\""} +rich = ">=13.3.1,<14.0.0" + +[package.extras] +pytest-plugin = ["pytest-prysk (>=0.2.0,<0.3.0)"] + [[package]] name = "pycparser" version = "2.22" @@ -1418,123 +2084,132 @@ files = [ [[package]] name = "pydantic" -version = "2.8.2" +version = "2.10.2" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, - {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, + {file = "pydantic-2.10.2-py3-none-any.whl", hash = "sha256:cfb96e45951117c3024e6b67b25cdc33a3cb7b2fa62e239f7af1378358a1d99e"}, + {file = "pydantic-2.10.2.tar.gz", hash = "sha256:2bc2d7f17232e0841cbba4641e65ba1eb6fafb3a08de3a091ff3ce14a197c4fa"}, ] [package.dependencies] -annotated-types = ">=0.4.0" +annotated-types = ">=0.6.0" email-validator = {version = ">=2.0.0", optional = true, markers = "extra == \"email\""} -pydantic-core = "2.20.1" -typing-extensions = [ - {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, - {version = ">=4.6.1", markers = "python_version < \"3.13\""}, -] +pydantic-core = "2.27.1" +typing-extensions = ">=4.12.2" [package.extras] email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata"] [[package]] name = "pydantic-core" -version = "2.20.1" +version = "2.27.1" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, - {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, - {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, - {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, - {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, - {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, - {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, - {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, - {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, - {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, - {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, - {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, - {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, - {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, + {file = "pydantic_core-2.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:71a5e35c75c021aaf400ac048dacc855f000bdfed91614b4a726f7432f1f3d6a"}, + {file = "pydantic_core-2.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f82d068a2d6ecfc6e054726080af69a6764a10015467d7d7b9f66d6ed5afa23b"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:121ceb0e822f79163dd4699e4c54f5ad38b157084d97b34de8b232bcaad70278"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4603137322c18eaf2e06a4495f426aa8d8388940f3c457e7548145011bb68e05"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a33cd6ad9017bbeaa9ed78a2e0752c5e250eafb9534f308e7a5f7849b0b1bfb4"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15cc53a3179ba0fcefe1e3ae50beb2784dede4003ad2dfd24f81bba4b23a454f"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45d9c5eb9273aa50999ad6adc6be5e0ecea7e09dbd0d31bd0c65a55a2592ca08"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8bf7b66ce12a2ac52d16f776b31d16d91033150266eb796967a7e4621707e4f6"}, + {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:655d7dd86f26cb15ce8a431036f66ce0318648f8853d709b4167786ec2fa4807"}, + {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:5556470f1a2157031e676f776c2bc20acd34c1990ca5f7e56f1ebf938b9ab57c"}, + {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f69ed81ab24d5a3bd93861c8c4436f54afdf8e8cc421562b0c7504cf3be58206"}, + {file = "pydantic_core-2.27.1-cp310-none-win32.whl", hash = "sha256:f5a823165e6d04ccea61a9f0576f345f8ce40ed533013580e087bd4d7442b52c"}, + {file = "pydantic_core-2.27.1-cp310-none-win_amd64.whl", hash = "sha256:57866a76e0b3823e0b56692d1a0bf722bffb324839bb5b7226a7dbd6c9a40b17"}, + {file = "pydantic_core-2.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac3b20653bdbe160febbea8aa6c079d3df19310d50ac314911ed8cc4eb7f8cb8"}, + {file = "pydantic_core-2.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a5a8e19d7c707c4cadb8c18f5f60c843052ae83c20fa7d44f41594c644a1d330"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f7059ca8d64fea7f238994c97d91f75965216bcbe5f695bb44f354893f11d52"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bed0f8a0eeea9fb72937ba118f9db0cb7e90773462af7962d382445f3005e5a4"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3cb37038123447cf0f3ea4c74751f6a9d7afef0eb71aa07bf5f652b5e6a132c"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84286494f6c5d05243456e04223d5a9417d7f443c3b76065e75001beb26f88de"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acc07b2cfc5b835444b44a9956846b578d27beeacd4b52e45489e93276241025"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4fefee876e07a6e9aad7a8c8c9f85b0cdbe7df52b8a9552307b09050f7512c7e"}, + {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:258c57abf1188926c774a4c94dd29237e77eda19462e5bb901d88adcab6af919"}, + {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:35c14ac45fcfdf7167ca76cc80b2001205a8d5d16d80524e13508371fb8cdd9c"}, + {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d1b26e1dff225c31897696cab7d4f0a315d4c0d9e8666dbffdb28216f3b17fdc"}, + {file = "pydantic_core-2.27.1-cp311-none-win32.whl", hash = "sha256:2cdf7d86886bc6982354862204ae3b2f7f96f21a3eb0ba5ca0ac42c7b38598b9"}, + {file = "pydantic_core-2.27.1-cp311-none-win_amd64.whl", hash = "sha256:3af385b0cee8df3746c3f406f38bcbfdc9041b5c2d5ce3e5fc6637256e60bbc5"}, + {file = "pydantic_core-2.27.1-cp311-none-win_arm64.whl", hash = "sha256:81f2ec23ddc1b476ff96563f2e8d723830b06dceae348ce02914a37cb4e74b89"}, + {file = "pydantic_core-2.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9cbd94fc661d2bab2bc702cddd2d3370bbdcc4cd0f8f57488a81bcce90c7a54f"}, + {file = "pydantic_core-2.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f8c4718cd44ec1580e180cb739713ecda2bdee1341084c1467802a417fe0f02"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15aae984e46de8d376df515f00450d1522077254ef6b7ce189b38ecee7c9677c"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ba5e3963344ff25fc8c40da90f44b0afca8cfd89d12964feb79ac1411a260ac"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:992cea5f4f3b29d6b4f7f1726ed8ee46c8331c6b4eed6db5b40134c6fe1768bb"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0325336f348dbee6550d129b1627cb8f5351a9dc91aad141ffb96d4937bd9529"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7597c07fbd11515f654d6ece3d0e4e5093edc30a436c63142d9a4b8e22f19c35"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3bbd5d8cc692616d5ef6fbbbd50dbec142c7e6ad9beb66b78a96e9c16729b089"}, + {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:dc61505e73298a84a2f317255fcc72b710b72980f3a1f670447a21efc88f8381"}, + {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:e1f735dc43da318cad19b4173dd1ffce1d84aafd6c9b782b3abc04a0d5a6f5bb"}, + {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f4e5658dbffe8843a0f12366a4c2d1c316dbe09bb4dfbdc9d2d9cd6031de8aae"}, + {file = "pydantic_core-2.27.1-cp312-none-win32.whl", hash = "sha256:672ebbe820bb37988c4d136eca2652ee114992d5d41c7e4858cdd90ea94ffe5c"}, + {file = "pydantic_core-2.27.1-cp312-none-win_amd64.whl", hash = "sha256:66ff044fd0bb1768688aecbe28b6190f6e799349221fb0de0e6f4048eca14c16"}, + {file = "pydantic_core-2.27.1-cp312-none-win_arm64.whl", hash = "sha256:9a3b0793b1bbfd4146304e23d90045f2a9b5fd5823aa682665fbdaf2a6c28f3e"}, + {file = "pydantic_core-2.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f216dbce0e60e4d03e0c4353c7023b202d95cbaeff12e5fd2e82ea0a66905073"}, + {file = "pydantic_core-2.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a2e02889071850bbfd36b56fd6bc98945e23670773bc7a76657e90e6b6603c08"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b0e23f119b2b456d07ca91b307ae167cc3f6c846a7b169fca5326e32fdc6cf"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:764be71193f87d460a03f1f7385a82e226639732214b402f9aa61f0d025f0737"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c00666a3bd2f84920a4e94434f5974d7bbc57e461318d6bb34ce9cdbbc1f6b2"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ccaa88b24eebc0f849ce0a4d09e8a408ec5a94afff395eb69baf868f5183107"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c65af9088ac534313e1963443d0ec360bb2b9cba6c2909478d22c2e363d98a51"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:206b5cf6f0c513baffaeae7bd817717140770c74528f3e4c3e1cec7871ddd61a"}, + {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:062f60e512fc7fff8b8a9d680ff0ddaaef0193dba9fa83e679c0c5f5fbd018bc"}, + {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:a0697803ed7d4af5e4c1adf1670af078f8fcab7a86350e969f454daf598c4960"}, + {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:58ca98a950171f3151c603aeea9303ef6c235f692fe555e883591103da709b23"}, + {file = "pydantic_core-2.27.1-cp313-none-win32.whl", hash = "sha256:8065914ff79f7eab1599bd80406681f0ad08f8e47c880f17b416c9f8f7a26d05"}, + {file = "pydantic_core-2.27.1-cp313-none-win_amd64.whl", hash = "sha256:ba630d5e3db74c79300d9a5bdaaf6200172b107f263c98a0539eeecb857b2337"}, + {file = "pydantic_core-2.27.1-cp313-none-win_arm64.whl", hash = "sha256:45cf8588c066860b623cd11c4ba687f8d7175d5f7ef65f7129df8a394c502de5"}, + {file = "pydantic_core-2.27.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:5897bec80a09b4084aee23f9b73a9477a46c3304ad1d2d07acca19723fb1de62"}, + {file = "pydantic_core-2.27.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d0165ab2914379bd56908c02294ed8405c252250668ebcb438a55494c69f44ab"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b9af86e1d8e4cfc82c2022bfaa6f459381a50b94a29e95dcdda8442d6d83864"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f6c8a66741c5f5447e047ab0ba7a1c61d1e95580d64bce852e3df1f895c4067"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a42d6a8156ff78981f8aa56eb6394114e0dedb217cf8b729f438f643608cbcd"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64c65f40b4cd8b0e049a8edde07e38b476da7e3aaebe63287c899d2cff253fa5"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdcf339322a3fae5cbd504edcefddd5a50d9ee00d968696846f089b4432cf78"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf99c8404f008750c846cb4ac4667b798a9f7de673ff719d705d9b2d6de49c5f"}, + {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8f1edcea27918d748c7e5e4d917297b2a0ab80cad10f86631e488b7cddf76a36"}, + {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:159cac0a3d096f79ab6a44d77a961917219707e2a130739c64d4dd46281f5c2a"}, + {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:029d9757eb621cc6e1848fa0b0310310de7301057f623985698ed7ebb014391b"}, + {file = "pydantic_core-2.27.1-cp38-none-win32.whl", hash = "sha256:a28af0695a45f7060e6f9b7092558a928a28553366519f64083c63a44f70e618"}, + {file = "pydantic_core-2.27.1-cp38-none-win_amd64.whl", hash = "sha256:2d4567c850905d5eaaed2f7a404e61012a51caf288292e016360aa2b96ff38d4"}, + {file = "pydantic_core-2.27.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e9386266798d64eeb19dd3677051f5705bf873e98e15897ddb7d76f477131967"}, + {file = "pydantic_core-2.27.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4228b5b646caa73f119b1ae756216b59cc6e2267201c27d3912b592c5e323b60"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3dfe500de26c52abe0477dde16192ac39c98f05bf2d80e76102d394bd13854"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aee66be87825cdf72ac64cb03ad4c15ffef4143dbf5c113f64a5ff4f81477bf9"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b748c44bb9f53031c8cbc99a8a061bc181c1000c60a30f55393b6e9c45cc5bd"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ca038c7f6a0afd0b2448941b6ef9d5e1949e999f9e5517692eb6da58e9d44be"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e0bd57539da59a3e4671b90a502da9a28c72322a4f17866ba3ac63a82c4498e"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ac6c2c45c847bbf8f91930d88716a0fb924b51e0c6dad329b793d670ec5db792"}, + {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b94d4ba43739bbe8b0ce4262bcc3b7b9f31459ad120fb595627eaeb7f9b9ca01"}, + {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:00e6424f4b26fe82d44577b4c842d7df97c20be6439e8e685d0d715feceb9fb9"}, + {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:38de0a70160dd97540335b7ad3a74571b24f1dc3ed33f815f0880682e6880131"}, + {file = "pydantic_core-2.27.1-cp39-none-win32.whl", hash = "sha256:7ccebf51efc61634f6c2344da73e366c75e735960b5654b63d7e6f69a5885fa3"}, + {file = "pydantic_core-2.27.1-cp39-none-win_amd64.whl", hash = "sha256:a57847b090d7892f123726202b7daa20df6694cbd583b67a592e856bff603d6c"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3fa80ac2bd5856580e242dbc202db873c60a01b20309c8319b5c5986fbe53ce6"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d950caa237bb1954f1b8c9227b5065ba6875ac9771bb8ec790d956a699b78676"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e4216e64d203e39c62df627aa882f02a2438d18a5f21d7f721621f7a5d3611d"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02a3d637bd387c41d46b002f0e49c52642281edacd2740e5a42f7017feea3f2c"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:161c27ccce13b6b0c8689418da3885d3220ed2eae2ea5e9b2f7f3d48f1d52c27"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:19910754e4cc9c63bc1c7f6d73aa1cfee82f42007e407c0f413695c2f7ed777f"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:e173486019cc283dc9778315fa29a363579372fe67045e971e89b6365cc035ed"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:af52d26579b308921b73b956153066481f064875140ccd1dfd4e77db89dbb12f"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:981fb88516bd1ae8b0cbbd2034678a39dedc98752f264ac9bc5839d3923fa04c"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5fde892e6c697ce3e30c61b239330fc5d569a71fefd4eb6512fc6caec9dd9e2f"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:816f5aa087094099fff7edabb5e01cc370eb21aa1a1d44fe2d2aefdfb5599b31"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c10c309e18e443ddb108f0ef64e8729363adbfd92d6d57beec680f6261556f3"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98476c98b02c8e9b2eec76ac4156fd006628b1b2d0ef27e548ffa978393fd154"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c3027001c28434e7ca5a6e1e527487051136aa81803ac812be51802150d880dd"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7699b1df36a48169cdebda7ab5a2bac265204003f153b4bd17276153d997670a"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1c39b07d90be6b48968ddc8c19e7585052088fd7ec8d568bb31ff64c70ae3c97"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:46ccfe3032b3915586e469d4972973f893c0a2bb65669194a5bdea9bacc088c2"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:62ba45e21cf6571d7f716d903b5b7b6d2617e2d5d67c0923dc47b9d41369f840"}, + {file = "pydantic_core-2.27.1.tar.gz", hash = "sha256:62a763352879b84aa31058fc931884055fd75089cccbd9d58bb6afd01141b235"}, ] [package.dependencies] @@ -1542,13 +2217,13 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pydot" -version = "3.0.1" +version = "3.0.2" description = "Python interface to Graphviz's Dot" optional = false python-versions = ">=3.8" files = [ - {file = "pydot-3.0.1-py3-none-any.whl", hash = "sha256:43f1e878dc1ff7c1c2e3470a6999d4e9e97771c5c862440c2f0af0ba844c231f"}, - {file = "pydot-3.0.1.tar.gz", hash = "sha256:e18cf7f287c497d77b536a3d20a46284568fea390776dface6eabbdf1b1b5efc"}, + {file = "pydot-3.0.2-py3-none-any.whl", hash = "sha256:99cedaa55d04abb0b2bc56d9981a6da781053dd5ac75c428e8dd53db53f90b14"}, + {file = "pydot-3.0.2.tar.gz", hash = "sha256:9180da540b51b3aa09fbf81140b3edfbe2315d778e8589a7d0a4a69c41332bae"}, ] [package.dependencies] @@ -1557,17 +2232,17 @@ pyparsing = ">=3.0.9" [package.extras] dev = ["chardet", "parameterized", "ruff"] release = ["zest.releaser[recommended]"] -tests = ["chardet", "parameterized", "ruff", "tox", "unittest-parallel"] +tests = ["chardet", "parameterized", "pytest", "pytest-cov", "pytest-xdist[psutil]", "ruff", "tox"] [[package]] name = "pygithub" -version = "2.4.0" +version = "2.5.0" description = "Use the full Github API v3" optional = false python-versions = ">=3.8" files = [ - {file = "PyGithub-2.4.0-py3-none-any.whl", hash = "sha256:81935aa4bdc939fba98fee1cb47422c09157c56a27966476ff92775602b9ee24"}, - {file = "pygithub-2.4.0.tar.gz", hash = "sha256:6601e22627e87bac192f1e2e39c6e6f69a43152cfb8f307cee575879320b3051"}, + {file = "PyGithub-2.5.0-py3-none-any.whl", hash = "sha256:b0b635999a658ab8e08720bdd3318893ff20e2275f6446fcf35bf3f44f2c0fd2"}, + {file = "pygithub-2.5.0.tar.gz", hash = "sha256:e1613ac508a9be710920d26eb18b1905ebd9926aa49398e88151c1b526aad3cf"}, ] [package.dependencies] @@ -1578,15 +2253,29 @@ requests = ">=2.14.0" typing-extensions = ">=4.0.0" urllib3 = ">=1.26.0" +[[package]] +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + [[package]] name = "pyjwt" -version = "2.9.0" +version = "2.10.1" description = "JSON Web Token implementation in Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, - {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, + {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, + {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, ] [package.dependencies] @@ -1598,6 +2287,35 @@ dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pyte docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] +[[package]] +name = "pylint" +version = "3.3.1" +description = "python code static checker" +optional = false +python-versions = ">=3.9.0" +files = [ + {file = "pylint-3.3.1-py3-none-any.whl", hash = "sha256:2f846a466dd023513240bc140ad2dd73bfc080a5d85a710afdb728c420a5a2b9"}, + {file = "pylint-3.3.1.tar.gz", hash = "sha256:9f3dcc87b1203e612b78d91a896407787e708b3f189b5fa0b307712d49ff0c6e"}, +] + +[package.dependencies] +astroid = ">=3.3.4,<=3.4.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = [ + {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, + {version = ">=0.2", markers = "python_version < \"3.11\""}, +] +isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + [[package]] name = "pynacl" version = "1.5.0" @@ -1626,13 +2344,13 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] [[package]] name = "pyparsing" -version = "3.1.4" +version = "3.2.0" description = "pyparsing module - Classes and methods to define and execute parsing grammars" optional = false -python-versions = ">=3.6.8" +python-versions = ">=3.9" files = [ - {file = "pyparsing-3.1.4-py3-none-any.whl", hash = "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c"}, - {file = "pyparsing-3.1.4.tar.gz", hash = "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032"}, + {file = "pyparsing-3.2.0-py3-none-any.whl", hash = "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84"}, + {file = "pyparsing-3.2.0.tar.gz", hash = "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c"}, ] [package.extras] @@ -1640,15 +2358,18 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pyreadline3" -version = "3.4.1" +version = "3.5.4" description = "A python implementation of GNU readline." optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb"}, - {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"}, + {file = "pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6"}, + {file = "pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7"}, ] +[package.extras] +dev = ["build", "flake8", "mypy", "pytest", "twine"] + [[package]] name = "pytest" version = "7.4.4" @@ -1688,25 +2409,43 @@ pytest = ">=6.2.5" [package.extras] dev = ["pre-commit", "pytest-asyncio", "tox"] +[[package]] +name = "pytest-prysk" +version = "0.2.0" +description = "Pytest plugin for prysk" +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "pytest_prysk-0.2.0-py3-none-any.whl", hash = "sha256:3180a9d3a6634e6e70107b2eed2a6a7420630b14ba2036598ef690f9b71be79f"}, + {file = "pytest_prysk-0.2.0.tar.gz", hash = "sha256:488d1f77e35beec9cad13e11368dcc5d09555ec31a4d6a3f9d901e78bbeeb2d1"}, +] + +[package.dependencies] +prysk = ">=0.15.0" +pytest = ">=7.3.2,<8.0.0" + [[package]] name = "python-daemon" -version = "3.0.1" +version = "3.1.0" description = "Library to implement a well-behaved Unix daemon process." optional = false -python-versions = ">=3" +python-versions = ">=3.7" files = [ - {file = "python-daemon-3.0.1.tar.gz", hash = "sha256:6c57452372f7eaff40934a1c03ad1826bf5e793558e87fef49131e6464b4dae5"}, - {file = "python_daemon-3.0.1-py3-none-any.whl", hash = "sha256:42bb848a3260a027fa71ad47ecd959e471327cb34da5965962edd5926229f341"}, + {file = "python_daemon-3.1.0-py3-none-any.whl", hash = "sha256:a66b5896f0aed5807a25c6128268eb496488b1f9c6927c487710049ba16be32a"}, + {file = "python_daemon-3.1.0.tar.gz", hash = "sha256:fdb621d7e5f46e74b4de1ad6b0fff6e69cd91b4f219de1476190ebdd0f4781df"}, ] [package.dependencies] -docutils = "*" lockfile = ">=0.10" setuptools = ">=62.4.0" [package.extras] -devel = ["coverage", "docutils", "isort", "testscenarios (>=0.4)", "testtools", "twine"] -test = ["coverage", "docutils", "testscenarios (>=0.4)", "testtools"] +build = ["build", "changelog-chug", "docutils", "python-daemon[doc]", "wheel"] +devel = ["python-daemon[dist,test]"] +dist = ["python-daemon[build]", "twine"] +doc = ["Sphinx (>=4.4,<5.0)"] +static-analysis = ["isort (>=5.13,<6.0)", "pip-check", "pycodestyle (>=2.12,<3.0)", "pydocstyle (>=6.3,<7.0)", "pyupgrade (>=3.17,<4.0)"] +test = ["coverage", "python-daemon[build,static-analysis]", "testscenarios (>=0.4)", "testtools"] [[package]] name = "python-dateutil" @@ -1722,27 +2461,45 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "pyupgrade" +version = "3.19.0" +description = "A tool to automatically upgrade syntax for newer versions." +optional = false +python-versions = ">=3.9" +files = [ + {file = "pyupgrade-3.19.0-py2.py3-none-any.whl", hash = "sha256:1364fcae4436a6a236a85960587390ec8a939ad0f65f429346f70a5f201c1489"}, + {file = "pyupgrade-3.19.0.tar.gz", hash = "sha256:7ed4b7d972ed2788c43994f4a24f949d5bf044342992f3b48e1bed0092ddaa01"}, +] + +[package.dependencies] +tokenize-rt = ">=6.1.0" + [[package]] name = "pywin32" -version = "306" +version = "308" description = "Python for Window Extensions" optional = false python-versions = "*" files = [ - {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, - {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, - {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, - {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, - {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, - {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, - {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, - {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, - {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, - {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, - {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, - {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, - {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, - {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, + {file = "pywin32-308-cp310-cp310-win32.whl", hash = "sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e"}, + {file = "pywin32-308-cp310-cp310-win_amd64.whl", hash = "sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e"}, + {file = "pywin32-308-cp310-cp310-win_arm64.whl", hash = "sha256:a5ab5381813b40f264fa3495b98af850098f814a25a63589a8e9eb12560f450c"}, + {file = "pywin32-308-cp311-cp311-win32.whl", hash = "sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a"}, + {file = "pywin32-308-cp311-cp311-win_amd64.whl", hash = "sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b"}, + {file = "pywin32-308-cp311-cp311-win_arm64.whl", hash = "sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6"}, + {file = "pywin32-308-cp312-cp312-win32.whl", hash = "sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897"}, + {file = "pywin32-308-cp312-cp312-win_amd64.whl", hash = "sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47"}, + {file = "pywin32-308-cp312-cp312-win_arm64.whl", hash = "sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091"}, + {file = "pywin32-308-cp313-cp313-win32.whl", hash = "sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed"}, + {file = "pywin32-308-cp313-cp313-win_amd64.whl", hash = "sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4"}, + {file = "pywin32-308-cp313-cp313-win_arm64.whl", hash = "sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd"}, + {file = "pywin32-308-cp37-cp37m-win32.whl", hash = "sha256:1f696ab352a2ddd63bd07430080dd598e6369152ea13a25ebcdd2f503a38f1ff"}, + {file = "pywin32-308-cp37-cp37m-win_amd64.whl", hash = "sha256:13dcb914ed4347019fbec6697a01a0aec61019c1046c2b905410d197856326a6"}, + {file = "pywin32-308-cp38-cp38-win32.whl", hash = "sha256:5794e764ebcabf4ff08c555b31bd348c9025929371763b2183172ff4708152f0"}, + {file = "pywin32-308-cp38-cp38-win_amd64.whl", hash = "sha256:3b92622e29d651c6b783e368ba7d6722b1634b8e70bd376fd7610fe1992e19de"}, + {file = "pywin32-308-cp39-cp39-win32.whl", hash = "sha256:7873ca4dc60ab3287919881a7d4f88baee4a6e639aa6962de25a98ba6b193341"}, + {file = "pywin32-308-cp39-cp39-win_amd64.whl", hash = "sha256:71b3322d949b4cc20776436a9c9ba0eeedcbc9c650daa536df63f0ff111bb920"}, ] [[package]] @@ -1843,127 +2600,133 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "rich" +version = "13.9.4" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, + {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, +] + +[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 = "rpds-py" -version = "0.20.0" +version = "0.21.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false -python-versions = ">=3.8" -files = [ - {file = "rpds_py-0.20.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2"}, - {file = "rpds_py-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf"}, - {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140"}, - {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f"}, - {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce"}, - {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94"}, - {file = "rpds_py-0.20.0-cp310-none-win32.whl", hash = "sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee"}, - {file = "rpds_py-0.20.0-cp310-none-win_amd64.whl", hash = "sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399"}, - {file = "rpds_py-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489"}, - {file = "rpds_py-0.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209"}, - {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3"}, - {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272"}, - {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad"}, - {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58"}, - {file = "rpds_py-0.20.0-cp311-none-win32.whl", hash = "sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0"}, - {file = "rpds_py-0.20.0-cp311-none-win_amd64.whl", hash = "sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c"}, - {file = "rpds_py-0.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6"}, - {file = "rpds_py-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4"}, - {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef"}, - {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821"}, - {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940"}, - {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174"}, - {file = "rpds_py-0.20.0-cp312-none-win32.whl", hash = "sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139"}, - {file = "rpds_py-0.20.0-cp312-none-win_amd64.whl", hash = "sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585"}, - {file = "rpds_py-0.20.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29"}, - {file = "rpds_py-0.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879"}, - {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f"}, - {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c"}, - {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2"}, - {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57"}, - {file = "rpds_py-0.20.0-cp313-none-win32.whl", hash = "sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a"}, - {file = "rpds_py-0.20.0-cp313-none-win_amd64.whl", hash = "sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2"}, - {file = "rpds_py-0.20.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24"}, - {file = "rpds_py-0.20.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751"}, - {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8"}, - {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e"}, - {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253"}, - {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a"}, - {file = "rpds_py-0.20.0-cp38-none-win32.whl", hash = "sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5"}, - {file = "rpds_py-0.20.0-cp38-none-win_amd64.whl", hash = "sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232"}, - {file = "rpds_py-0.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22"}, - {file = "rpds_py-0.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda"}, - {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580"}, - {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b"}, - {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420"}, - {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b"}, - {file = "rpds_py-0.20.0-cp39-none-win32.whl", hash = "sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7"}, - {file = "rpds_py-0.20.0-cp39-none-win_amd64.whl", hash = "sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344"}, - {file = "rpds_py-0.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec"}, - {file = "rpds_py-0.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8"}, - {file = "rpds_py-0.20.0.tar.gz", hash = "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121"}, +python-versions = ">=3.9" +files = [ + {file = "rpds_py-0.21.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a017f813f24b9df929674d0332a374d40d7f0162b326562daae8066b502d0590"}, + {file = "rpds_py-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:20cc1ed0bcc86d8e1a7e968cce15be45178fd16e2ff656a243145e0b439bd250"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad116dda078d0bc4886cb7840e19811562acdc7a8e296ea6ec37e70326c1b41c"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:808f1ac7cf3b44f81c9475475ceb221f982ef548e44e024ad5f9e7060649540e"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de552f4a1916e520f2703ec474d2b4d3f86d41f353e7680b597512ffe7eac5d0"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:efec946f331349dfc4ae9d0e034c263ddde19414fe5128580f512619abed05f1"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b80b4690bbff51a034bfde9c9f6bf9357f0a8c61f548942b80f7b66356508bf5"}, + {file = "rpds_py-0.21.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:085ed25baac88953d4283e5b5bd094b155075bb40d07c29c4f073e10623f9f2e"}, + {file = "rpds_py-0.21.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:daa8efac2a1273eed2354397a51216ae1e198ecbce9036fba4e7610b308b6153"}, + {file = "rpds_py-0.21.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:95a5bad1ac8a5c77b4e658671642e4af3707f095d2b78a1fdd08af0dfb647624"}, + {file = "rpds_py-0.21.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3e53861b29a13d5b70116ea4230b5f0f3547b2c222c5daa090eb7c9c82d7f664"}, + {file = "rpds_py-0.21.0-cp310-none-win32.whl", hash = "sha256:ea3a6ac4d74820c98fcc9da4a57847ad2cc36475a8bd9683f32ab6d47a2bd682"}, + {file = "rpds_py-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:b8f107395f2f1d151181880b69a2869c69e87ec079c49c0016ab96860b6acbe5"}, + {file = "rpds_py-0.21.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5555db3e618a77034954b9dc547eae94166391a98eb867905ec8fcbce1308d95"}, + {file = "rpds_py-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:97ef67d9bbc3e15584c2f3c74bcf064af36336c10d2e21a2131e123ce0f924c9"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ab2c2a26d2f69cdf833174f4d9d86118edc781ad9a8fa13970b527bf8236027"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4e8921a259f54bfbc755c5bbd60c82bb2339ae0324163f32868f63f0ebb873d9"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a7ff941004d74d55a47f916afc38494bd1cfd4b53c482b77c03147c91ac0ac3"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5145282a7cd2ac16ea0dc46b82167754d5e103a05614b724457cffe614f25bd8"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de609a6f1b682f70bb7163da745ee815d8f230d97276db049ab447767466a09d"}, + {file = "rpds_py-0.21.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:40c91c6e34cf016fa8e6b59d75e3dbe354830777fcfd74c58b279dceb7975b75"}, + {file = "rpds_py-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d2132377f9deef0c4db89e65e8bb28644ff75a18df5293e132a8d67748397b9f"}, + {file = "rpds_py-0.21.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0a9e0759e7be10109645a9fddaaad0619d58c9bf30a3f248a2ea57a7c417173a"}, + {file = "rpds_py-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e20da3957bdf7824afdd4b6eeb29510e83e026473e04952dca565170cd1ecc8"}, + {file = "rpds_py-0.21.0-cp311-none-win32.whl", hash = "sha256:f71009b0d5e94c0e86533c0b27ed7cacc1239cb51c178fd239c3cfefefb0400a"}, + {file = "rpds_py-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:e168afe6bf6ab7ab46c8c375606298784ecbe3ba31c0980b7dcbb9631dcba97e"}, + {file = "rpds_py-0.21.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:30b912c965b2aa76ba5168fd610087bad7fcde47f0a8367ee8f1876086ee6d1d"}, + {file = "rpds_py-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ca9989d5d9b1b300bc18e1801c67b9f6d2c66b8fd9621b36072ed1df2c977f72"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f54e7106f0001244a5f4cf810ba8d3f9c542e2730821b16e969d6887b664266"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fed5dfefdf384d6fe975cc026886aece4f292feaf69d0eeb716cfd3c5a4dd8be"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:590ef88db231c9c1eece44dcfefd7515d8bf0d986d64d0caf06a81998a9e8cab"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f983e4c2f603c95dde63df633eec42955508eefd8d0f0e6d236d31a044c882d7"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b229ce052ddf1a01c67d68166c19cb004fb3612424921b81c46e7ea7ccf7c3bf"}, + {file = "rpds_py-0.21.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ebf64e281a06c904a7636781d2e973d1f0926a5b8b480ac658dc0f556e7779f4"}, + {file = "rpds_py-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:998a8080c4495e4f72132f3d66ff91f5997d799e86cec6ee05342f8f3cda7dca"}, + {file = "rpds_py-0.21.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:98486337f7b4f3c324ab402e83453e25bb844f44418c066623db88e4c56b7c7b"}, + {file = "rpds_py-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a78d8b634c9df7f8d175451cfeac3810a702ccb85f98ec95797fa98b942cea11"}, + {file = "rpds_py-0.21.0-cp312-none-win32.whl", hash = "sha256:a58ce66847711c4aa2ecfcfaff04cb0327f907fead8945ffc47d9407f41ff952"}, + {file = "rpds_py-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:e860f065cc4ea6f256d6f411aba4b1251255366e48e972f8a347cf88077b24fd"}, + {file = "rpds_py-0.21.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ee4eafd77cc98d355a0d02f263efc0d3ae3ce4a7c24740010a8b4012bbb24937"}, + {file = "rpds_py-0.21.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:688c93b77e468d72579351a84b95f976bd7b3e84aa6686be6497045ba84be560"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c38dbf31c57032667dd5a2f0568ccde66e868e8f78d5a0d27dcc56d70f3fcd3b"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2d6129137f43f7fa02d41542ffff4871d4aefa724a5fe38e2c31a4e0fd343fb0"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520ed8b99b0bf86a176271f6fe23024323862ac674b1ce5b02a72bfeff3fff44"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaeb25ccfb9b9014a10eaf70904ebf3f79faaa8e60e99e19eef9f478651b9b74"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af04ac89c738e0f0f1b913918024c3eab6e3ace989518ea838807177d38a2e94"}, + {file = "rpds_py-0.21.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9b76e2afd585803c53c5b29e992ecd183f68285b62fe2668383a18e74abe7a3"}, + {file = "rpds_py-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5afb5efde74c54724e1a01118c6e5c15e54e642c42a1ba588ab1f03544ac8c7a"}, + {file = "rpds_py-0.21.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:52c041802a6efa625ea18027a0723676a778869481d16803481ef6cc02ea8cb3"}, + {file = "rpds_py-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee1e4fc267b437bb89990b2f2abf6c25765b89b72dd4a11e21934df449e0c976"}, + {file = "rpds_py-0.21.0-cp313-none-win32.whl", hash = "sha256:0c025820b78817db6a76413fff6866790786c38f95ea3f3d3c93dbb73b632202"}, + {file = "rpds_py-0.21.0-cp313-none-win_amd64.whl", hash = "sha256:320c808df533695326610a1b6a0a6e98f033e49de55d7dc36a13c8a30cfa756e"}, + {file = "rpds_py-0.21.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2c51d99c30091f72a3c5d126fad26236c3f75716b8b5e5cf8effb18889ced928"}, + {file = "rpds_py-0.21.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cbd7504a10b0955ea287114f003b7ad62330c9e65ba012c6223dba646f6ffd05"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dcc4949be728ede49e6244eabd04064336012b37f5c2200e8ec8eb2988b209c"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f414da5c51bf350e4b7960644617c130140423882305f7574b6cf65a3081cecb"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9afe42102b40007f588666bc7de82451e10c6788f6f70984629db193849dced1"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b929c2bb6e29ab31f12a1117c39f7e6d6450419ab7464a4ea9b0b417174f044"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8404b3717da03cbf773a1d275d01fec84ea007754ed380f63dfc24fb76ce4592"}, + {file = "rpds_py-0.21.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e12bb09678f38b7597b8346983d2323a6482dcd59e423d9448108c1be37cac9d"}, + {file = "rpds_py-0.21.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:58a0e345be4b18e6b8501d3b0aa540dad90caeed814c515e5206bb2ec26736fd"}, + {file = "rpds_py-0.21.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c3761f62fcfccf0864cc4665b6e7c3f0c626f0380b41b8bd1ce322103fa3ef87"}, + {file = "rpds_py-0.21.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c2b2f71c6ad6c2e4fc9ed9401080badd1469fa9889657ec3abea42a3d6b2e1ed"}, + {file = "rpds_py-0.21.0-cp39-none-win32.whl", hash = "sha256:b21747f79f360e790525e6f6438c7569ddbfb1b3197b9e65043f25c3c9b489d8"}, + {file = "rpds_py-0.21.0-cp39-none-win_amd64.whl", hash = "sha256:0626238a43152918f9e72ede9a3b6ccc9e299adc8ade0d67c5e142d564c9a83d"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6b4ef7725386dc0762857097f6b7266a6cdd62bfd209664da6712cb26acef035"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:6bc0e697d4d79ab1aacbf20ee5f0df80359ecf55db33ff41481cf3e24f206919"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da52d62a96e61c1c444f3998c434e8b263c384f6d68aca8274d2e08d1906325c"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:98e4fe5db40db87ce1c65031463a760ec7906ab230ad2249b4572c2fc3ef1f9f"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30bdc973f10d28e0337f71d202ff29345320f8bc49a31c90e6c257e1ccef4333"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:faa5e8496c530f9c71f2b4e1c49758b06e5f4055e17144906245c99fa6d45356"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32eb88c30b6a4f0605508023b7141d043a79b14acb3b969aa0b4f99b25bc7d4a"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a89a8ce9e4e75aeb7fa5d8ad0f3fecdee813802592f4f46a15754dcb2fd6b061"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:241e6c125568493f553c3d0fdbb38c74babf54b45cef86439d4cd97ff8feb34d"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:3b766a9f57663396e4f34f5140b3595b233a7b146e94777b97a8413a1da1be18"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:af4a644bf890f56e41e74be7d34e9511e4954894d544ec6b8efe1e21a1a8da6c"}, + {file = "rpds_py-0.21.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3e30a69a706e8ea20444b98a49f386c17b26f860aa9245329bab0851ed100677"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:031819f906bb146561af051c7cef4ba2003d28cff07efacef59da973ff7969ba"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b876f2bc27ab5954e2fd88890c071bd0ed18b9c50f6ec3de3c50a5ece612f7a6"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc5695c321e518d9f03b7ea6abb5ea3af4567766f9852ad1560f501b17588c7b"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b4de1da871b5c0fd5537b26a6fc6814c3cc05cabe0c941db6e9044ffbb12f04a"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:878f6fea96621fda5303a2867887686d7a198d9e0f8a40be100a63f5d60c88c9"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8eeec67590e94189f434c6d11c426892e396ae59e4801d17a93ac96b8c02a6c"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ff2eba7f6c0cb523d7e9cff0903f2fe1feff8f0b2ceb6bd71c0e20a4dcee271"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a429b99337062877d7875e4ff1a51fe788424d522bd64a8c0a20ef3021fdb6ed"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d167e4dbbdac48bd58893c7e446684ad5d425b407f9336e04ab52e8b9194e2ed"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:4eb2de8a147ffe0626bfdc275fc6563aa7bf4b6db59cf0d44f0ccd6ca625a24e"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e78868e98f34f34a88e23ee9ccaeeec460e4eaf6db16d51d7a9b883e5e785a5e"}, + {file = "rpds_py-0.21.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4991ca61656e3160cdaca4851151fd3f4a92e9eba5c7a530ab030d6aee96ec89"}, + {file = "rpds_py-0.21.0.tar.gz", hash = "sha256:ed6378c9d66d0de903763e7706383d60c33829581f0adff47b6535f1802fa6db"}, ] [[package]] name = "s3transfer" -version = "0.10.2" +version = "0.10.4" description = "An Amazon S3 Transfer Manager" optional = false python-versions = ">=3.8" files = [ - {file = "s3transfer-0.10.2-py3-none-any.whl", hash = "sha256:eca1c20de70a39daee580aef4986996620f365c4e0fda6a86100231d62f1bf69"}, - {file = "s3transfer-0.10.2.tar.gz", hash = "sha256:0711534e9356d3cc692fdde846b4a1e4b0cb6519971860796e6bc4c7aea00ef6"}, + {file = "s3transfer-0.10.4-py3-none-any.whl", hash = "sha256:244a76a24355363a68164241438de1b72f8781664920260c48465896b712a41e"}, + {file = "s3transfer-0.10.4.tar.gz", hash = "sha256:29edc09801743c21eb5ecbc617a152df41d3c287f67b615f73e5f750583666a7"}, ] [package.dependencies] @@ -2003,6 +2766,31 @@ core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.te 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)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +[[package]] +name = "shellingham" +version = "1.5.4" +description = "Tool to Detect Surrounding Shell" +optional = false +python-versions = ">=3.7" +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 = "shibuya" +version = "2024.10.15" +description = "A clean, responsive, and customizable Sphinx documentation theme with light/dark mode." +optional = false +python-versions = ">=3.7" +files = [ + {file = "shibuya-2024.10.15-py3-none-any.whl", hash = "sha256:46d32c4dc7f244bfe130e710f477f4bda64706e5610916089371509992cae5e6"}, + {file = "shibuya-2024.10.15.tar.gz", hash = "sha256:fc057a32a2dcdca9f0f85616f9fff5b3007500bf42ff4eeb1d68fae124b1a51d"}, +] + +[package.dependencies] +Sphinx = "*" + [[package]] name = "simplejson" version = "3.19.3" @@ -2155,6 +2943,249 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + +[[package]] +name = "soupsieve" +version = "2.6" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +files = [ + {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, + {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, +] + +[[package]] +name = "sphinx" +version = "7.4.7" +description = "Python documentation generator" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239"}, + {file = "sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe"}, +] + +[package.dependencies] +alabaster = ">=0.7.14,<0.8.0" +babel = ">=2.13" +colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} +docutils = ">=0.20,<0.22" +imagesize = ">=1.3" +Jinja2 = ">=3.1" +packaging = ">=23.0" +Pygments = ">=2.17" +requests = ">=2.30.0" +snowballstemmer = ">=2.2" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.9" +tomli = {version = ">=2", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["flake8 (>=6.0)", "importlib-metadata (>=6.0)", "mypy (==1.10.1)", "pytest (>=6.0)", "ruff (==0.5.2)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-docutils (==0.21.0.20240711)", "types-requests (>=2.30.0)"] +test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"] + +[[package]] +name = "sphinx-basic-ng" +version = "1.0.0b2" +description = "A modern skeleton for Sphinx themes." +optional = false +python-versions = ">=3.7" +files = [ + {file = "sphinx_basic_ng-1.0.0b2-py3-none-any.whl", hash = "sha256:eb09aedbabfb650607e9b4b68c9d240b90b1e1be221d6ad71d61c52e29f7932b"}, + {file = "sphinx_basic_ng-1.0.0b2.tar.gz", hash = "sha256:9ec55a47c90c8c002b5960c57492ec3021f5193cb26cebc2dc4ea226848651c9"}, +] + +[package.dependencies] +sphinx = ">=4.0" + +[package.extras] +docs = ["furo", "ipython", "myst-parser", "sphinx-copybutton", "sphinx-inline-tabs"] + +[[package]] +name = "sphinx-copybutton" +version = "0.5.2" +description = "Add a copy button to each of your code cells." +optional = false +python-versions = ">=3.7" +files = [ + {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"}, + {file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"}, +] + +[package.dependencies] +sphinx = ">=1.8" + +[package.extras] +code-style = ["pre-commit (==2.12.1)"] +rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] + +[[package]] +name = "sphinx-design" +version = "0.6.1" +description = "A sphinx extension for designing beautiful, view size responsive web components." +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinx_design-0.6.1-py3-none-any.whl", hash = "sha256:b11f37db1a802a183d61b159d9a202314d4d2fe29c163437001324fe2f19549c"}, + {file = "sphinx_design-0.6.1.tar.gz", hash = "sha256:b44eea3719386d04d765c1a8257caca2b3e6f8421d7b3a5e742c0fd45f84e632"}, +] + +[package.dependencies] +sphinx = ">=6,<9" + +[package.extras] +code-style = ["pre-commit (>=3,<4)"] +rtd = ["myst-parser (>=2,<4)"] +testing = ["defusedxml", "myst-parser (>=2,<4)", "pytest (>=8.3,<9.0)", "pytest-cov", "pytest-regressions"] +testing-no-myst = ["defusedxml", "pytest (>=8.3,<9.0)", "pytest-cov", "pytest-regressions"] +theme-furo = ["furo (>=2024.7.18,<2024.8.0)"] +theme-im = ["sphinx-immaterial (>=0.12.2,<0.13.0)"] +theme-pydata = ["pydata-sphinx-theme (>=0.15.2,<0.16.0)"] +theme-rtd = ["sphinx-rtd-theme (>=2.0,<3.0)"] +theme-sbt = ["sphinx-book-theme (>=1.1,<2.0)"] + +[[package]] +name = "sphinx-inline-tabs" +version = "2023.4.21" +description = "Add inline tabbed content to your Sphinx documentation." +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinx_inline_tabs-2023.4.21-py3-none-any.whl", hash = "sha256:06809ac613f7c48ddd6e2fa588413e3fe92cff2397b56e2ccf0b0218f9ef6a78"}, + {file = "sphinx_inline_tabs-2023.4.21.tar.gz", hash = "sha256:5df2f13f602c158f3f5f6c509e008aeada199a8c76d97ba3aa2822206683bebc"}, +] + +[package.dependencies] +sphinx = ">=3" + +[package.extras] +doc = ["furo", "myst-parser"] +test = ["pytest", "pytest-cov", "pytest-xdist"] + +[[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" +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" +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" +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" +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" +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" +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 = "stevedore" +version = "5.4.0" +description = "Manage dynamic plugins for Python applications" +optional = false +python-versions = ">=3.9" +files = [ + {file = "stevedore-5.4.0-py3-none-any.whl", hash = "sha256:b0be3c4748b3ea7b854b265dcb4caa891015e442416422be16f8b31756107857"}, + {file = "stevedore-5.4.0.tar.gz", hash = "sha256:79e92235ecb828fe952b6b8b0c6c87863248631922c8e8e0fa5b17b232c4514d"}, +] + +[package.dependencies] +pbr = ">=2.0.0" + [[package]] name = "stopwatch-py" version = "2.0.1" @@ -2181,6 +3212,17 @@ files = [ doc = ["reno", "sphinx"] test = ["pytest", "tornado (>=4.5)", "typeguard"] +[[package]] +name = "tokenize-rt" +version = "6.1.0" +description = "A wrapper around the stdlib `tokenize` which roundtrips." +optional = false +python-versions = ">=3.9" +files = [ + {file = "tokenize_rt-6.1.0-py2.py3-none-any.whl", hash = "sha256:d706141cdec4aa5f358945abe36b911b8cbdc844545da99e811250c0cee9b6fc"}, + {file = "tokenize_rt-6.1.0.tar.gz", hash = "sha256:e8ee836616c0877ab7c7b54776d2fefcc3bde714449a206762425ae114b53c86"}, +] + [[package]] name = "toml" version = "0.10.2" @@ -2194,44 +3236,85 @@ files = [ [[package]] name = "tomli" -version = "2.0.1" +version = "2.2.1" description = "A lil' TOML parser" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {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"}, +] + +[[package]] +name = "tomlkit" +version = "0.13.2" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.8" +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 = "tornado" -version = "6.4.1" +version = "6.4.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">=3.8" files = [ - {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8"}, - {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14"}, - {file = "tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4"}, - {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842"}, - {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3"}, - {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f"}, - {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4"}, - {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698"}, - {file = "tornado-6.4.1-cp38-abi3-win32.whl", hash = "sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d"}, - {file = "tornado-6.4.1-cp38-abi3-win_amd64.whl", hash = "sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7"}, - {file = "tornado-6.4.1.tar.gz", hash = "sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9"}, + {file = "tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1"}, + {file = "tornado-6.4.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803"}, + {file = "tornado-6.4.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec"}, + {file = "tornado-6.4.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946"}, + {file = "tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf"}, + {file = "tornado-6.4.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634"}, + {file = "tornado-6.4.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73"}, + {file = "tornado-6.4.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c"}, + {file = "tornado-6.4.2-cp38-abi3-win32.whl", hash = "sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482"}, + {file = "tornado-6.4.2-cp38-abi3-win_amd64.whl", hash = "sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38"}, + {file = "tornado-6.4.2.tar.gz", hash = "sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b"}, ] [[package]] name = "typeguard" -version = "4.3.0" +version = "4.4.1" description = "Run-time type checker for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "typeguard-4.3.0-py3-none-any.whl", hash = "sha256:4d24c5b39a117f8a895b9da7a9b3114f04eb63bade45a4492de49b175b6f7dfa"}, - {file = "typeguard-4.3.0.tar.gz", hash = "sha256:92ee6a0aec9135181eae6067ebd617fd9de8d75d714fb548728a4933b1dea651"}, + {file = "typeguard-4.4.1-py3-none-any.whl", hash = "sha256:9324ec07a27ec67fc54a9c063020ca4c0ae6abad5e9f0f9804ca59aee68c6e21"}, + {file = "typeguard-4.4.1.tar.gz", hash = "sha256:0d22a89d00b453b47c49875f42b6601b961757541a2e1e0ef517b6e24213c21b"}, ] [package.dependencies] @@ -2241,15 +3324,32 @@ typing-extensions = ">=4.10.0" doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.3.0)"] test = ["coverage[toml] (>=7)", "mypy (>=1.2.0)", "pytest (>=7)"] +[[package]] +name = "typer" +version = "0.13.1" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.7" +files = [ + {file = "typer-0.13.1-py3-none-any.whl", hash = "sha256:5b59580fd925e89463a29d363e0a43245ec02765bde9fb77d39e5d0f29dd7157"}, + {file = "typer-0.13.1.tar.gz", hash = "sha256:9d444cb96cc268ce6f8b94e13b4335084cef4c079998a9f4851a90229a3bd25c"}, +] + +[package.dependencies] +click = ">=8.0.0" +rich = ">=10.11.0" +shellingham = ">=1.3.0" +typing-extensions = ">=3.7.4.3" + [[package]] name = "types-requests" -version = "2.32.0.20240712" +version = "2.32.0.20241016" description = "Typing stubs for requests" optional = false python-versions = ">=3.8" files = [ - {file = "types-requests-2.32.0.20240712.tar.gz", hash = "sha256:90c079ff05e549f6bf50e02e910210b98b8ff1ebdd18e19c873cd237737c1358"}, - {file = "types_requests-2.32.0.20240712-py3-none-any.whl", hash = "sha256:f754283e152c752e46e70942fa2a146b5bc70393522257bb85bd1ef7e019dcc3"}, + {file = "types-requests-2.32.0.20241016.tar.gz", hash = "sha256:0d9cad2f27515d0e3e3da7134a1b6f28fb97129d86b867f24d9c726452634d95"}, + {file = "types_requests-2.32.0.20241016-py3-none-any.whl", hash = "sha256:4195d62d6d3e043a4eaaf08ff8a62184584d2e8684e9d2aa178c7915a7da3747"}, ] [package.dependencies] @@ -2268,13 +3368,13 @@ files = [ [[package]] name = "urllib3" -version = "2.2.2" +version = "2.2.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, - {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, ] [package.extras] @@ -2283,94 +3383,109 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "virtualenv" +version = "20.28.0" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.8" +files = [ + {file = "virtualenv-20.28.0-py3-none-any.whl", hash = "sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0"}, + {file = "virtualenv-20.28.0.tar.gz", hash = "sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa"}, +] + +[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)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + [[package]] name = "wrapt" -version = "1.16.0" +version = "1.17.0" description = "Module for decorators, wrappers and monkey patching." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, - {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, - {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, - {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, - {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, - {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, - {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, - {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, - {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, - {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, - {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, - {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, - {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, - {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, - {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, - {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, - {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, - {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, + {file = "wrapt-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a0c23b8319848426f305f9cb0c98a6e32ee68a36264f45948ccf8e7d2b941f8"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ca5f060e205f72bec57faae5bd817a1560fcfc4af03f414b08fa29106b7e2d"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e185ec6060e301a7e5f8461c86fb3640a7beb1a0f0208ffde7a65ec4074931df"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb90765dd91aed05b53cd7a87bd7f5c188fcd95960914bae0d32c5e7f899719d"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:879591c2b5ab0a7184258274c42a126b74a2c3d5a329df16d69f9cee07bba6ea"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fce6fee67c318fdfb7f285c29a82d84782ae2579c0e1b385b7f36c6e8074fffb"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0698d3a86f68abc894d537887b9bbf84d29bcfbc759e23f4644be27acf6da301"}, + {file = "wrapt-1.17.0-cp310-cp310-win32.whl", hash = "sha256:69d093792dc34a9c4c8a70e4973a3361c7a7578e9cd86961b2bbf38ca71e4e22"}, + {file = "wrapt-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:f28b29dc158ca5d6ac396c8e0a2ef45c4e97bb7e65522bfc04c989e6fe814575"}, + {file = "wrapt-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:74bf625b1b4caaa7bad51d9003f8b07a468a704e0644a700e936c357c17dd45a"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f2a28eb35cf99d5f5bd12f5dd44a0f41d206db226535b37b0c60e9da162c3ed"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81b1289e99cf4bad07c23393ab447e5e96db0ab50974a280f7954b071d41b489"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2939cd4a2a52ca32bc0b359015718472d7f6de870760342e7ba295be9ebaf9"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a9653131bda68a1f029c52157fd81e11f07d485df55410401f745007bd6d339"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4e4b4385363de9052dac1a67bfb535c376f3d19c238b5f36bddc95efae15e12d"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bdf62d25234290db1837875d4dceb2151e4ea7f9fff2ed41c0fde23ed542eb5b"}, + {file = "wrapt-1.17.0-cp311-cp311-win32.whl", hash = "sha256:5d8fd17635b262448ab8f99230fe4dac991af1dabdbb92f7a70a6afac8a7e346"}, + {file = "wrapt-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:92a3d214d5e53cb1db8b015f30d544bc9d3f7179a05feb8f16df713cecc2620a"}, + {file = "wrapt-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:89fc28495896097622c3fc238915c79365dd0ede02f9a82ce436b13bd0ab7569"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875d240fdbdbe9e11f9831901fb8719da0bd4e6131f83aa9f69b96d18fae7504"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ed16d95fd142e9c72b6c10b06514ad30e846a0d0917ab406186541fe68b451"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18b956061b8db634120b58f668592a772e87e2e78bc1f6a906cfcaa0cc7991c1"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:daba396199399ccabafbfc509037ac635a6bc18510ad1add8fd16d4739cdd106"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4d63f4d446e10ad19ed01188d6c1e1bb134cde8c18b0aa2acfd973d41fcc5ada"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8a5e7cc39a45fc430af1aefc4d77ee6bad72c5bcdb1322cfde852c15192b8bd4"}, + {file = "wrapt-1.17.0-cp312-cp312-win32.whl", hash = "sha256:0a0a1a1ec28b641f2a3a2c35cbe86c00051c04fffcfcc577ffcdd707df3f8635"}, + {file = "wrapt-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:3c34f6896a01b84bab196f7119770fd8466c8ae3dfa73c59c0bb281e7b588ce7"}, + {file = "wrapt-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:714c12485aa52efbc0fc0ade1e9ab3a70343db82627f90f2ecbc898fdf0bb181"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da427d311782324a376cacb47c1a4adc43f99fd9d996ffc1b3e8529c4074d393"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba1739fb38441a27a676f4de4123d3e858e494fac05868b7a281c0a383c098f4"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e711fc1acc7468463bc084d1b68561e40d1eaa135d8c509a65dd534403d83d7b"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:140ea00c87fafc42739bd74a94a5a9003f8e72c27c47cd4f61d8e05e6dec8721"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:73a96fd11d2b2e77d623a7f26e004cc31f131a365add1ce1ce9a19e55a1eef90"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0b48554952f0f387984da81ccfa73b62e52817a4386d070c75e4db7d43a28c4a"}, + {file = "wrapt-1.17.0-cp313-cp313-win32.whl", hash = "sha256:498fec8da10e3e62edd1e7368f4b24aa362ac0ad931e678332d1b209aec93045"}, + {file = "wrapt-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd136bb85f4568fffca995bd3c8d52080b1e5b225dbf1c2b17b66b4c5fa02838"}, + {file = "wrapt-1.17.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17fcf043d0b4724858f25b8826c36e08f9fb2e475410bece0ec44a22d533da9b"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4a557d97f12813dc5e18dad9fa765ae44ddd56a672bb5de4825527c847d6379"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0229b247b0fc7dee0d36176cbb79dbaf2a9eb7ecc50ec3121f40ef443155fb1d"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8425cfce27b8b20c9b89d77fb50e368d8306a90bf2b6eef2cdf5cd5083adf83f"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c900108df470060174108012de06d45f514aa4ec21a191e7ab42988ff42a86c"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4e547b447073fc0dbfcbff15154c1be8823d10dab4ad401bdb1575e3fdedff1b"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:914f66f3b6fc7b915d46c1cc424bc2441841083de01b90f9e81109c9759e43ab"}, + {file = "wrapt-1.17.0-cp313-cp313t-win32.whl", hash = "sha256:a4192b45dff127c7d69b3bdfb4d3e47b64179a0b9900b6351859f3001397dabf"}, + {file = "wrapt-1.17.0-cp313-cp313t-win_amd64.whl", hash = "sha256:4f643df3d4419ea3f856c5c3f40fec1d65ea2e89ec812c83f7767c8730f9827a"}, + {file = "wrapt-1.17.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:69c40d4655e078ede067a7095544bcec5a963566e17503e75a3a3e0fe2803b13"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f495b6754358979379f84534f8dd7a43ff8cff2558dcdea4a148a6e713a758f"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:baa7ef4e0886a6f482e00d1d5bcd37c201b383f1d314643dfb0367169f94f04c"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fc931382e56627ec4acb01e09ce66e5c03c384ca52606111cee50d931a342d"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8f8909cdb9f1b237786c09a810e24ee5e15ef17019f7cecb207ce205b9b5fcce"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ad47b095f0bdc5585bced35bd088cbfe4177236c7df9984b3cc46b391cc60627"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:948a9bd0fb2c5120457b07e59c8d7210cbc8703243225dbd78f4dfc13c8d2d1f"}, + {file = "wrapt-1.17.0-cp38-cp38-win32.whl", hash = "sha256:5ae271862b2142f4bc687bdbfcc942e2473a89999a54231aa1c2c676e28f29ea"}, + {file = "wrapt-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:f335579a1b485c834849e9075191c9898e0731af45705c2ebf70e0cd5d58beed"}, + {file = "wrapt-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d751300b94e35b6016d4b1e7d0e7bbc3b5e1751e2405ef908316c2a9024008a1"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7264cbb4a18dc4acfd73b63e4bcfec9c9802614572025bdd44d0721983fc1d9c"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33539c6f5b96cf0b1105a0ff4cf5db9332e773bb521cc804a90e58dc49b10578"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c30970bdee1cad6a8da2044febd824ef6dc4cc0b19e39af3085c763fdec7de33"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bc7f729a72b16ee21795a943f85c6244971724819819a41ddbaeb691b2dd85ad"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6ff02a91c4fc9b6a94e1c9c20f62ea06a7e375f42fe57587f004d1078ac86ca9"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2dfb7cff84e72e7bf975b06b4989477873dcf160b2fd89959c629535df53d4e0"}, + {file = "wrapt-1.17.0-cp39-cp39-win32.whl", hash = "sha256:2399408ac33ffd5b200480ee858baa58d77dd30e0dd0cab6a8a9547135f30a88"}, + {file = "wrapt-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:4f763a29ee6a20c529496a20a7bcb16a73de27f5da6a843249c7047daf135977"}, + {file = "wrapt-1.17.0-py3-none-any.whl", hash = "sha256:d2c63b93548eda58abf5188e505ffed0229bf675f7c3090f8e36ad55b8cbc371"}, + {file = "wrapt-1.17.0.tar.gz", hash = "sha256:16187aa2317c731170a88ef35e8937ae0f533c402872c1ee5e6d079fcf320801"}, ] [[package]] name = "zipp" -version = "3.20.1" +version = "3.21.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "zipp-3.20.1-py3-none-any.whl", hash = "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064"}, - {file = "zipp-3.20.1.tar.gz", hash = "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b"}, + {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, + {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, ] [package.extras] @@ -2384,4 +3499,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.10.0,<4.0" -content-hash = "5c9569efd521cade8a375b3375b898869fb70925acc52f32660f90c3faf31ba2" +content-hash = "228a4f5081f4295cda39181eab5cb1dc2f1e19923236e9d5f7bf966aed84d13f" diff --git a/pyproject.toml b/pyproject.toml index 0ad84d4..f383b8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "exasol-script-languages-container-ci-setup" -version = "1.5.0" +version = "1.6.0" description = "Manages AWS cloud CI build infrastructure." license = "MIT" @@ -25,11 +25,12 @@ requires = ["poetry_core>=1.0.0"] build-backend = "poetry.core.masonry.api" -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] toml = ">=0.10.2" pytest = "^7.1.1" pytest-mock = "^3.7.0" cfn-lint = "^0.75.1" +exasol-toolbox = ">=0.16.0" [tool.pytest.ini_options] minversion = "6.0" @@ -37,3 +38,42 @@ minversion = "6.0" testpaths = [ "test" ] + + +[tool.coverage.run] +source = [ + "exasol", +] + +[tool.coverage.report] +fail_under = 15 + + +[tool.black] +line-length = 88 +verbose = false +include = "\\.pyi?$" + + +[tool.isort] +profile = "black" +force_grid_wrap = 2 + + +[tool.pylint.master] +fail-under = 6.66 +output-format = "colorized,json:.lint.json,text:.lint.txt" + +[tool.pylint.format] +max-line-length = 88 +max-module-lines = 800 + +[tool.mypy] +ignore_errors = true + +[[tool.mypy.overrides]] +module = [ + "tests.*", + "test.*", +] +ignore_errors = true \ No newline at end of file diff --git a/scripts/build/check_release.py b/scripts/build/check_release.py index 9b3ebca..96ea2fc 100644 --- a/scripts/build/check_release.py +++ b/scripts/build/check_release.py @@ -2,8 +2,8 @@ import sys from pathlib import Path -from git import Repo import toml +from git import Repo def get_git_version(): @@ -20,13 +20,15 @@ def get_git_version(): def get_poetry_version(): - parsed_toml = toml.load('pyproject.toml') + parsed_toml = toml.load("pyproject.toml") return parsed_toml["tool"]["poetry"]["version"].strip() def get_change_log_version(): # Path overloads __truediv__ - with open(Path(__file__).parent / ".." / ".." / "doc" / "changes" / "changelog.md") as changelog: + with open( + Path(__file__).parent / ".." / ".." / "doc" / "changes" / "changelog.md" + ) as changelog: changelog_str = changelog.read() # Search for the FIRST pattern like: "* [0.5.0](changes_0.5.0.md)" in the changelog file. # Note that we encapsulate the [(0.5.0)] with parenthesis, which tells re to return the matching string as group @@ -34,7 +36,7 @@ def get_change_log_version(): return version_match.groups()[0] -if __name__ == '__main__': +if __name__ == "__main__": poetry_version = get_poetry_version() latest_tag = get_git_version() changelog_version = get_change_log_version() diff --git a/test/conftest.py b/test/conftest.py index 139597f..e69de29 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,2 +0,0 @@ - - diff --git a/test/contract_tests/aws_access/cloudformation_service.py b/test/contract_tests/aws_access/cloudformation_service.py index 93b6af3..1678149 100644 --- a/test/contract_tests/aws_access/cloudformation_service.py +++ b/test/contract_tests/aws_access/cloudformation_service.py @@ -1,9 +1,15 @@ import pytest -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.cloudformation_service import CloudFormationService -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ValidationResult, \ - ListStackResourcesResult -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.cloudformation_service import ( + CloudFormationService, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ( + ListStackResourcesResult, + ValidationResult, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) class ValidateContractContract: @@ -17,8 +23,12 @@ def template_body(self) -> str: raise NotImplementedError() @pytest.fixture(scope="class") - def validation_result(self, cloudformation_service, template_body) -> ValidationResult: - validation_result = cloudformation_service.validate_template(template_body=template_body) + def validation_result( + self, cloudformation_service, template_body + ) -> ValidationResult: + validation_result = cloudformation_service.validate_template( + template_body=template_body + ) return validation_result def test_validation_result_is_not_none(self, validation_result): @@ -44,26 +54,34 @@ def number_of_resources(self) -> int: raise NotImplementedError() @pytest.fixture(scope="class") - def list_stack_resources_result(self, cloudformation_service, stack_name) -> ListStackResourcesResult: + def list_stack_resources_result( + self, cloudformation_service, stack_name + ) -> ListStackResourcesResult: list_stack_resources_result = cloudformation_service.list_stack_resources( - stack_name=stack_name, - next_token=None + stack_name=stack_name, next_token=None ) return list_stack_resources_result - def test_stack_resource_summaries_count(self, list_stack_resources_result, number_of_resources): - assert len(list_stack_resources_result.stack_resource_summaries) == number_of_resources + def test_stack_resource_summaries_count( + self, list_stack_resources_result, number_of_resources + ): + assert ( + len(list_stack_resources_result.stack_resource_summaries) + == number_of_resources + ) def test_physical_resource_ids_is_not_none(self, list_stack_resources_result): - resources_with_physical_resource_id = [stack_resource_summary - for stack_resource_summary - in list_stack_resources_result.stack_resource_summaries - if stack_resource_summary.physical_resource_id is not None] + resources_with_physical_resource_id = [ + stack_resource_summary + for stack_resource_summary in list_stack_resources_result.stack_resource_summaries + if stack_resource_summary.physical_resource_id is not None + ] assert len(resources_with_physical_resource_id) > 0 def test_resource_type(self, list_stack_resources_result, resource_type): - resources_with_given_resource_type = [stack_resource_summary.physical_resource_id - for stack_resource_summary - in list_stack_resources_result.stack_resource_summaries - if stack_resource_summary.resource_type == resource_type] + resources_with_given_resource_type = [ + stack_resource_summary.physical_resource_id + for stack_resource_summary in list_stack_resources_result.stack_resource_summaries + if stack_resource_summary.resource_type == resource_type + ] assert len(resources_with_given_resource_type) > 0 diff --git a/test/contract_tests/aws_access/code_build_service.py b/test/contract_tests/aws_access/code_build_service.py index ff031e1..4fae600 100644 --- a/test/contract_tests/aws_access/code_build_service.py +++ b/test/contract_tests/aws_access/code_build_service.py @@ -1,10 +1,21 @@ -from typing import List, Dict, Tuple +from typing import ( + Dict, + List, + Tuple, +) import pytest -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.codebuild_service import CodeBuildService -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.codebuild import BuildBatchStatus, BuildBatch -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.codebuild_service import ( + CodeBuildService, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.codebuild import ( + BuildBatch, + BuildBatchStatus, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) class StartCodeBuildContract: @@ -26,12 +37,18 @@ def environment_variables_override(self) -> List[Dict[str, str]]: raise NotImplementedError() @pytest.fixture(scope="class") - def build_batch(self, codebuild_service, project_name, source_version, - environment_variables_override) -> BuildBatch: + def build_batch( + self, + codebuild_service, + project_name, + source_version, + environment_variables_override, + ) -> BuildBatch: build_batch = codebuild_service.start_build_batch( project_name=project_name, source_version=source_version, - environment_variables_override=environment_variables_override) + environment_variables_override=environment_variables_override, + ) return build_batch def test_build_batch_status(self, build_batch): @@ -57,13 +74,21 @@ def environment_variables_override(self) -> List[Dict[str, str]]: raise NotImplementedError() @pytest.fixture(scope="class") - def build_batches(self, codebuild_service, project_name, source_version, - environment_variables_override) -> Tuple[BuildBatch, BuildBatch]: + def build_batches( + self, + codebuild_service, + project_name, + source_version, + environment_variables_override, + ) -> Tuple[BuildBatch, BuildBatch]: build_batch_from_start = codebuild_service.start_build_batch( project_name=project_name, source_version=source_version, - environment_variables_override=environment_variables_override) - build_batches_from_get = codebuild_service.batch_get_build_batches(build_batch_ids=[build_batch_from_start.id]) + environment_variables_override=environment_variables_override, + ) + build_batches_from_get = codebuild_service.batch_get_build_batches( + build_batch_ids=[build_batch_from_start.id] + ) return build_batch_from_start, build_batches_from_get[0] def test_build_batch_id(self, build_batches): @@ -88,7 +113,9 @@ def build_batch_id(self, codebuild_service) -> PhysicalResourceId: @pytest.fixture(scope="class") def build_batches(self, codebuild_service, build_batch_id) -> List[BuildBatch]: - build_batches = codebuild_service.batch_get_build_batches(build_batch_ids=[build_batch_id]) + build_batches = codebuild_service.batch_get_build_batches( + build_batch_ids=[build_batch_id] + ) return build_batches @pytest.fixture @@ -105,25 +132,33 @@ def test_build_batch_status(self, build_batches, expected_build_batch_status): assert build_batches[0].build_batch_status == expected_build_batch_status -class BatchGetBuildBatchesSingleBuildIdInProgressContract(BatchGetBuildBatchesSingleBuildIdContract): +class BatchGetBuildBatchesSingleBuildIdInProgressContract( + BatchGetBuildBatchesSingleBuildIdContract +): def expected_build_batch_status(self) -> BuildBatchStatus: return BuildBatchStatus.IN_PROGRESS -class BatchGetBuildBatchesSingleBuildIdSucceededContract(BatchGetBuildBatchesSingleBuildIdContract): +class BatchGetBuildBatchesSingleBuildIdSucceededContract( + BatchGetBuildBatchesSingleBuildIdContract +): def expected_build_batch_status(self) -> BuildBatchStatus: return BuildBatchStatus.SUCCEEDED -class BatchGetBuildBatchesSingleBuildIdFailedContract(BatchGetBuildBatchesSingleBuildIdContract): +class BatchGetBuildBatchesSingleBuildIdFailedContract( + BatchGetBuildBatchesSingleBuildIdContract +): def expected_build_batch_status(self) -> BuildBatchStatus: return BuildBatchStatus.FAILED -class BatchGetBuildBatchesSingleBuildIdStoppedContract(BatchGetBuildBatchesSingleBuildIdContract): +class BatchGetBuildBatchesSingleBuildIdStoppedContract( + BatchGetBuildBatchesSingleBuildIdContract +): def expected_build_batch_status(self) -> BuildBatchStatus: return BuildBatchStatus.STOPPED diff --git a/test/contract_tests/aws_access/secretmanager_service.py b/test/contract_tests/aws_access/secretmanager_service.py index 50f8859..3cf60a6 100644 --- a/test/contract_tests/aws_access/secretmanager_service.py +++ b/test/contract_tests/aws_access/secretmanager_service.py @@ -1,8 +1,15 @@ import pytest -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId, ARN -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.secretsmanager import Secret -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.secretsmanager_service import SecretsManagerService +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + ARN, + PhysicalResourceId, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.secretsmanager import ( + Secret, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.secretsmanager_service import ( + SecretsManagerService, +) class GetSecretValueArnEqualContract: diff --git a/test/integration_tests/__init__.py b/test/integration/__init__.py similarity index 100% rename from test/integration_tests/__init__.py rename to test/integration/__init__.py diff --git a/test/integration_tests/test_deploy_ci.py b/test/integration/test_deploy_ci.py similarity index 59% rename from test/integration_tests/test_deploy_ci.py rename to test/integration/test_deploy_ci.py index eacc85a..7b047eb 100644 --- a/test/integration_tests/test_deploy_ci.py +++ b/test/integration/test_deploy_ci.py @@ -1,8 +1,12 @@ import pytest from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.ci_build import CI_BUILD_WEBHOOK_FILTER_PATTERN -from exasol_script_languages_container_ci_setup.lib.render_template import render_template +from exasol_script_languages_container_ci_setup.lib.ci_build import ( + CI_BUILD_WEBHOOK_FILTER_PATTERN, +) +from exasol_script_languages_container_ci_setup.lib.render_template import ( + render_template, +) PROJECT = "slc" GH_URL = "https://github.com/slc" @@ -11,9 +15,13 @@ @pytest.fixture def ci_code_build_yml(): - return render_template("slc_code_build.yaml", project=PROJECT, - dockerhub_secret_arn=DOCKERHUB_SECRET_ARN, github_url=GH_URL, - webhook_filter_pattern=CI_BUILD_WEBHOOK_FILTER_PATTERN) + return render_template( + "slc_code_build.yaml", + project=PROJECT, + dockerhub_secret_arn=DOCKERHUB_SECRET_ARN, + github_url=GH_URL, + webhook_filter_pattern=CI_BUILD_WEBHOOK_FILTER_PATTERN, + ) def test_deploy_ci_template(ci_code_build_yml): @@ -23,8 +31,12 @@ def test_deploy_ci_template(ci_code_build_yml): @pytest.fixture def release_code_build_yml(): - return render_template("slc_code_release_build.yaml", project=PROJECT, - dockerhub_secret_arn=DOCKERHUB_SECRET_ARN, github_url=GH_URL) + return render_template( + "slc_code_release_build.yaml", + project=PROJECT, + dockerhub_secret_arn=DOCKERHUB_SECRET_ARN, + github_url=GH_URL, + ) def test_deploy_release_template(release_code_build_yml): diff --git a/test/integration_tests/test_deploy_source_credentials.py b/test/integration/test_deploy_source_credentials.py similarity index 66% rename from test/integration_tests/test_deploy_source_credentials.py rename to test/integration/test_deploy_source_credentials.py index a5690c7..e33c041 100644 --- a/test/integration_tests/test_deploy_source_credentials.py +++ b/test/integration/test_deploy_source_credentials.py @@ -1,7 +1,9 @@ import pytest from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.render_template import render_template +from exasol_script_languages_container_ci_setup.lib.render_template import ( + render_template, +) SECRET_NAME = "test_secret" SECRET_USER_KEY = "test_secret_user_key" @@ -10,10 +12,12 @@ @pytest.fixture def source_credentials_yml(): - return render_template("slc_source_credential.yaml", - secret_name=SECRET_NAME, - secret_user_key=SECRET_USER_KEY, - secret_token_key=SECRET_TOKEN_KEY) + return render_template( + "slc_source_credential.yaml", + secret_name=SECRET_NAME, + secret_user_key=SECRET_USER_KEY, + secret_token_key=SECRET_TOKEN_KEY, + ) def test_deploy_source_credentials_template(source_credentials_yml): diff --git a/test/mock_cast.py b/test/mock_cast.py index 3a3866e..b6ca022 100644 --- a/test/mock_cast.py +++ b/test/mock_cast.py @@ -1,4 +1,7 @@ -from typing import Any, cast +from typing import ( + Any, + cast, +) from unittest.mock import Mock diff --git a/test/unit_tests/__init__.py b/test/unit/__init__.py similarity index 100% rename from test/unit_tests/__init__.py rename to test/unit/__init__.py diff --git a/test/unit_tests/aws/__init__.py b/test/unit/aws/__init__.py similarity index 100% rename from test/unit_tests/aws/__init__.py rename to test/unit/aws/__init__.py diff --git a/test/unit_tests/aws/wrapper/__init__.py b/test/unit/aws/wrapper/__init__.py similarity index 100% rename from test/unit_tests/aws/wrapper/__init__.py rename to test/unit/aws/wrapper/__init__.py diff --git a/test/unit_tests/aws/wrapper/datamodels/__init__.py b/test/unit/aws/wrapper/datamodels/__init__.py similarity index 100% rename from test/unit_tests/aws/wrapper/datamodels/__init__.py rename to test/unit/aws/wrapper/datamodels/__init__.py diff --git a/test/unit_tests/aws/wrapper/datamodels/cloudformation/__init__.py b/test/unit/aws/wrapper/datamodels/cloudformation/__init__.py similarity index 100% rename from test/unit_tests/aws/wrapper/datamodels/cloudformation/__init__.py rename to test/unit/aws/wrapper/datamodels/cloudformation/__init__.py diff --git a/test/unit_tests/aws/wrapper/datamodels/cloudformation/test_list_stack_resources_result.py b/test/unit/aws/wrapper/datamodels/cloudformation/test_list_stack_resources_result.py similarity index 51% rename from test/unit_tests/aws/wrapper/datamodels/cloudformation/test_list_stack_resources_result.py rename to test/unit/aws/wrapper/datamodels/cloudformation/test_list_stack_resources_result.py index fc4ead8..d1f6f05 100644 --- a/test/unit_tests/aws/wrapper/datamodels/cloudformation/test_list_stack_resources_result.py +++ b/test/unit/aws/wrapper/datamodels/cloudformation/test_list_stack_resources_result.py @@ -1,94 +1,98 @@ import pytest -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import \ - ListStackResourcesResult, NextToken, StackResourceSummary -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ( + ListStackResourcesResult, + NextToken, + StackResourceSummary, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) def test_with_next_token(): - expected_list_stack_resources_result = \ - ListStackResourcesResult( - next_token=NextToken(aws_next_token="aws_next_token"), - stack_resource_summaries=[] - ) + expected_list_stack_resources_result = ListStackResourcesResult( + next_token=NextToken(aws_next_token="aws_next_token"), + stack_resource_summaries=[], + ) boto_list_stack_resources_result = { "NextToken": expected_list_stack_resources_result.next_token.aws_next_token, - "StackResourceSummaries": [] + "StackResourceSummaries": [], } - list_stack_resources_result = ListStackResourcesResult.from_boto(boto_list_stack_resources_result) + list_stack_resources_result = ListStackResourcesResult.from_boto( + boto_list_stack_resources_result + ) assert list_stack_resources_result == expected_list_stack_resources_result def test_with_next_token_none(): - expected_list_stack_resources_result = \ - ListStackResourcesResult( - next_token=None, - stack_resource_summaries=[] - ) - boto_list_stack_resources_result = { - "NextToken": None, - "StackResourceSummaries": [] - } - list_stack_resources_result = ListStackResourcesResult.from_boto(boto_list_stack_resources_result) + expected_list_stack_resources_result = ListStackResourcesResult( + next_token=None, stack_resource_summaries=[] + ) + boto_list_stack_resources_result = {"NextToken": None, "StackResourceSummaries": []} + list_stack_resources_result = ListStackResourcesResult.from_boto( + boto_list_stack_resources_result + ) assert list_stack_resources_result == expected_list_stack_resources_result def test_without_next_token_none(): - expected_list_stack_resources_result = \ - ListStackResourcesResult( - next_token=None, - stack_resource_summaries=[] - ) - boto_list_stack_resources_result = { - "StackResourceSummaries": [] - } - list_stack_resources_result = ListStackResourcesResult.from_boto(boto_list_stack_resources_result) + expected_list_stack_resources_result = ListStackResourcesResult( + next_token=None, stack_resource_summaries=[] + ) + boto_list_stack_resources_result = {"StackResourceSummaries": []} + list_stack_resources_result = ListStackResourcesResult.from_boto( + boto_list_stack_resources_result + ) assert list_stack_resources_result == expected_list_stack_resources_result @pytest.mark.parametrize("count", range(3)) def test_with_multiple_stack_resource_summary(count: int): - expected_list_stack_resources_result = \ - ListStackResourcesResult( - next_token=None, - stack_resource_summaries=[ - StackResourceSummary( - physical_resource_id=PhysicalResourceId(f"physical_resource_id_{i}"), - resource_type=f"resource_type_{i}" - ) - for i in range(count) - ] - ) + expected_list_stack_resources_result = ListStackResourcesResult( + next_token=None, + stack_resource_summaries=[ + StackResourceSummary( + physical_resource_id=PhysicalResourceId(f"physical_resource_id_{i}"), + resource_type=f"resource_type_{i}", + ) + for i in range(count) + ], + ) boto_list_stack_resources_result = { "StackResourceSummaries": [ { "PhysicalResourceId": summary.physical_resource_id.aws_physical_resource_id, - "ResourceType": summary.resource_type + "ResourceType": summary.resource_type, } for summary in expected_list_stack_resources_result.stack_resource_summaries ] } - list_stack_resources_result = ListStackResourcesResult.from_boto(boto_list_stack_resources_result) + list_stack_resources_result = ListStackResourcesResult.from_boto( + boto_list_stack_resources_result + ) assert list_stack_resources_result == expected_list_stack_resources_result def test_without_stack_resource_summaries(): boto_list_stack_resources_result = {} with pytest.raises(KeyError): - list_stack_resources_result = ListStackResourcesResult.from_boto(boto_list_stack_resources_result) + list_stack_resources_result = ListStackResourcesResult.from_boto( + boto_list_stack_resources_result + ) def test_with_extra_keys(): - expected_list_stack_resources_result = \ - ListStackResourcesResult( - next_token=None, - stack_resource_summaries=[] - ) + expected_list_stack_resources_result = ListStackResourcesResult( + next_token=None, stack_resource_summaries=[] + ) boto_list_stack_resources_result = { "NextToken": None, "StackResourceSummaries": [], "extra1": None, - "extra2": 1 + "extra2": 1, } - list_stack_resources_result = ListStackResourcesResult.from_boto(boto_list_stack_resources_result) + list_stack_resources_result = ListStackResourcesResult.from_boto( + boto_list_stack_resources_result + ) assert list_stack_resources_result == expected_list_stack_resources_result diff --git a/test/unit_tests/aws/wrapper/datamodels/cloudformation/test_stack_resource_summary.py b/test/unit/aws/wrapper/datamodels/cloudformation/test_stack_resource_summary.py similarity index 79% rename from test/unit_tests/aws/wrapper/datamodels/cloudformation/test_stack_resource_summary.py rename to test/unit/aws/wrapper/datamodels/cloudformation/test_stack_resource_summary.py index 8c7fe2e..81ebce8 100644 --- a/test/unit_tests/aws/wrapper/datamodels/cloudformation/test_stack_resource_summary.py +++ b/test/unit/aws/wrapper/datamodels/cloudformation/test_stack_resource_summary.py @@ -1,16 +1,21 @@ import pytest -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import StackResourceSummary -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ( + StackResourceSummary, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) def test_valid(): expected_stack_resource_summary = StackResourceSummary( physical_resource_id=PhysicalResourceId("physical_resource_id"), - resource_type="resource_type") + resource_type="resource_type", + ) boto_stack_resource_summary = { "PhysicalResourceId": expected_stack_resource_summary.physical_resource_id.aws_physical_resource_id, - "ResourceType": expected_stack_resource_summary.resource_type + "ResourceType": expected_stack_resource_summary.resource_type, } stack_resource_summary = StackResourceSummary.from_boto(boto_stack_resource_summary) assert stack_resource_summary == expected_stack_resource_summary @@ -18,24 +23,22 @@ def test_valid(): def test_without_physical_resource_id(): expected_stack_resource_summary = StackResourceSummary( - physical_resource_id=None, - resource_type="resource_type") + physical_resource_id=None, resource_type="resource_type" + ) - boto_stack_resource_summary = { - "ResourceType": "resource_type" - } + boto_stack_resource_summary = {"ResourceType": "resource_type"} stack_resource_summary = StackResourceSummary.from_boto(boto_stack_resource_summary) assert stack_resource_summary == expected_stack_resource_summary def test_physical_resource_id_none(): expected_stack_resource_summary = StackResourceSummary( - physical_resource_id=None, - resource_type="resource_type") + physical_resource_id=None, resource_type="resource_type" + ) boto_stack_resource_summary = { "physical_resource_id": None, - "ResourceType": "resource_type" + "ResourceType": "resource_type", } stack_resource_summary = StackResourceSummary.from_boto(boto_stack_resource_summary) assert stack_resource_summary == expected_stack_resource_summary @@ -46,18 +49,21 @@ def test_without_resource_type(): boto_stack_resource_summary = { "PhysicalResourceId": "physical_resource_id", } - stack_resource_summary = StackResourceSummary.from_boto(boto_stack_resource_summary) + stack_resource_summary = StackResourceSummary.from_boto( + boto_stack_resource_summary + ) def test_with_extra_keys(): expected_stack_resource_summary = StackResourceSummary( physical_resource_id=PhysicalResourceId("physical_resource_id"), - resource_type="resource_type") + resource_type="resource_type", + ) boto_stack_resource_summary = { "PhysicalResourceId": expected_stack_resource_summary.physical_resource_id.aws_physical_resource_id, "ResourceType": expected_stack_resource_summary.resource_type, "extra1": None, - "extra2": 1 + "extra2": 1, } stack_resource_summary = StackResourceSummary.from_boto(boto_stack_resource_summary) assert stack_resource_summary == expected_stack_resource_summary diff --git a/test/unit_tests/aws/wrapper/datamodels/cloudformation/test_validation_result.py b/test/unit/aws/wrapper/datamodels/cloudformation/test_validation_result.py similarity index 75% rename from test/unit_tests/aws/wrapper/datamodels/cloudformation/test_validation_result.py rename to test/unit/aws/wrapper/datamodels/cloudformation/test_validation_result.py index 4b037aa..067faf7 100644 --- a/test/unit_tests/aws/wrapper/datamodels/cloudformation/test_validation_result.py +++ b/test/unit/aws/wrapper/datamodels/cloudformation/test_validation_result.py @@ -1,4 +1,6 @@ -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ValidationResult +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ( + ValidationResult, +) def test_empyt_dict(): @@ -8,9 +10,6 @@ def test_empyt_dict(): def test_with_extra_keys(): - boto_validation_result = { - "extra1": None, - "extra2": 1 - } + boto_validation_result = {"extra1": None, "extra2": 1} validation_result = ValidationResult.from_boto(boto_validation_result) assert validation_result == ValidationResult() diff --git a/test/unit_tests/aws/wrapper/datamodels/codebuild/__init__.py b/test/unit/aws/wrapper/datamodels/codebuild/__init__.py similarity index 100% rename from test/unit_tests/aws/wrapper/datamodels/codebuild/__init__.py rename to test/unit/aws/wrapper/datamodels/codebuild/__init__.py diff --git a/test/unit_tests/aws/wrapper/datamodels/codebuild/test_build_batch.py b/test/unit/aws/wrapper/datamodels/codebuild/test_build_batch.py similarity index 64% rename from test/unit_tests/aws/wrapper/datamodels/codebuild/test_build_batch.py rename to test/unit/aws/wrapper/datamodels/codebuild/test_build_batch.py index 7372442..f50b517 100644 --- a/test/unit_tests/aws/wrapper/datamodels/codebuild/test_build_batch.py +++ b/test/unit/aws/wrapper/datamodels/codebuild/test_build_batch.py @@ -1,13 +1,17 @@ import pytest -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.codebuild import BuildBatch, BuildBatchStatus -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.codebuild import ( + BuildBatch, + BuildBatchStatus, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) def test_with_id(): expected_build_batch = BuildBatch( - id=PhysicalResourceId("expected_id"), - build_batch_status=None + id=PhysicalResourceId("expected_id"), build_batch_status=None ) boto_buildbatch = { "id": expected_build_batch.id.aws_physical_resource_id, @@ -15,31 +19,25 @@ def test_with_id(): build_batch = BuildBatch.from_boto(boto_buildbatch) assert build_batch == expected_build_batch + @pytest.mark.parametrize("status", BuildBatchStatus) def test_with_build_batch_status(status): expected_build_batch = BuildBatch( - id=None, - build_batch_status=BuildBatchStatus.SUCCEEDED + id=None, build_batch_status=BuildBatchStatus.SUCCEEDED ) - boto_buildbatch = { - "buildBatchStatus": expected_build_batch.build_batch_status.name - } + boto_buildbatch = {"buildBatchStatus": expected_build_batch.build_batch_status.name} build_batch = BuildBatch.from_boto(boto_buildbatch) assert build_batch == expected_build_batch + def test_with_unknown_build_batch_status(): - boto_buildbatch = { - "buildBatchStatus": "MY_UNKNOWN_BUILD_STATUS" - } + boto_buildbatch = {"buildBatchStatus": "MY_UNKNOWN_BUILD_STATUS"} with pytest.raises(KeyError): build_batch = BuildBatch.from_boto(boto_buildbatch) def test_empty(): - expected_build_batch = BuildBatch( - id=None, - build_batch_status=None - ) + expected_build_batch = BuildBatch(id=None, build_batch_status=None) boto_buildbatch = {} build_batch = BuildBatch.from_boto(boto_buildbatch) assert build_batch == expected_build_batch @@ -48,36 +46,27 @@ def test_empty(): def test_with_extra_keys(): expected_build_batch = BuildBatch( id=PhysicalResourceId("expected_id"), - build_batch_status=BuildBatchStatus.SUCCEEDED + build_batch_status=BuildBatchStatus.SUCCEEDED, ) boto_buildbatch = { "id": expected_build_batch.id.aws_physical_resource_id, "buildBatchStatus": expected_build_batch.build_batch_status.name, "extra1": None, - "extra2": 1 + "extra2": 1, } build_batch = BuildBatch.from_boto(boto_buildbatch) assert build_batch == expected_build_batch def test_id_is_None(): - expected_build_batch = BuildBatch( - id=None, - build_batch_status=None - ) - boto_buildbatch = { - "id": None - } + expected_build_batch = BuildBatch(id=None, build_batch_status=None) + boto_buildbatch = {"id": None} build_batch = BuildBatch.from_boto(boto_buildbatch) assert build_batch == expected_build_batch + def test_build_batch_status_is_None(): - expected_build_batch = BuildBatch( - id=None, - build_batch_status=None - ) - boto_buildbatch = { - "buildBatchStatus": None - } + expected_build_batch = BuildBatch(id=None, build_batch_status=None) + boto_buildbatch = {"buildBatchStatus": None} build_batch = BuildBatch.from_boto(boto_buildbatch) assert build_batch == expected_build_batch diff --git a/test/unit_tests/aws/wrapper/datamodels/secretsmanager/__init__.py b/test/unit/aws/wrapper/datamodels/secretsmanager/__init__.py similarity index 100% rename from test/unit_tests/aws/wrapper/datamodels/secretsmanager/__init__.py rename to test/unit/aws/wrapper/datamodels/secretsmanager/__init__.py diff --git a/test/unit_tests/aws/wrapper/datamodels/secretsmanager/test_secret.py b/test/unit/aws/wrapper/datamodels/secretsmanager/test_secret.py similarity index 76% rename from test/unit_tests/aws/wrapper/datamodels/secretsmanager/test_secret.py rename to test/unit/aws/wrapper/datamodels/secretsmanager/test_secret.py index c255546..0d27214 100644 --- a/test/unit_tests/aws/wrapper/datamodels/secretsmanager/test_secret.py +++ b/test/unit/aws/wrapper/datamodels/secretsmanager/test_secret.py @@ -1,7 +1,11 @@ import pytest -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ARN -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.secretsmanager import Secret +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + ARN, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.secretsmanager import ( + Secret, +) def test_arn_exists(): @@ -19,18 +23,12 @@ def test_arn_not_exists(): def test_with_extra_keys(): expected = Secret(arn=ARN(aws_arn="EXPECTED_ARN")) - boto_secret = { - "ARN": expected.arn.aws_arn, - "extra1": None, - "extra2": 1 - } + boto_secret = {"ARN": expected.arn.aws_arn, "extra1": None, "extra2": 1} actual = Secret.from_boto(boto_secret) assert actual == expected def test_empty_arn(): with pytest.raises(ValueError, match="ARN was None"): - boto_secret = { - "ARN": None - } + boto_secret = {"ARN": None} secret = Secret.from_boto(boto_secret) diff --git a/test/unit_tests/aws/wrapper/test_aws_client.py b/test/unit/aws/wrapper/test_aws_client.py similarity index 64% rename from test/unit_tests/aws/wrapper/test_aws_client.py rename to test/unit/aws/wrapper/test_aws_client.py index 4d5b7cf..278b88b 100644 --- a/test/unit_tests/aws/wrapper/test_aws_client.py +++ b/test/unit/aws/wrapper/test_aws_client.py @@ -1,17 +1,25 @@ import dataclasses +from test.mock_cast import mock_cast from typing import Union -from unittest.mock import MagicMock, Mock, call, create_autospec +from unittest.mock import ( + MagicMock, + Mock, + call, + create_autospec, +) from boto3 import Session -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.aws_client import AwsClient -from test.mock_cast import mock_cast +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.aws_client import ( + AwsClient, +) def test_init(): boto_session_factory = Mock() - aws_client = AwsClient(profile="profile", region="region", - boto_session_factory=boto_session_factory) + aws_client = AwsClient( + profile="profile", region="region", boto_session_factory=boto_session_factory + ) assert boto_session_factory.mock_calls == [] @@ -19,81 +27,93 @@ def test_init(): class CodeBuildServiceTestSetup: boto_session: Union[MagicMock, Session] = create_autospec(Session) boto_session_factory = Mock(return_value=boto_session) - aws_client = AwsClient(profile="profile", region="region", - boto_session_factory=boto_session_factory) + aws_client = AwsClient( + profile="profile", region="region", boto_session_factory=boto_session_factory + ) codebuild_service = aws_client.create_codebuild_service() def test_create_codebuild_service_boto_session_factory(): setup = CodeBuildServiceTestSetup() assert setup.boto_session_factory.mock_calls == [ - call(profile_name='profile', region_name='region'), + call(profile_name="profile", region_name="region"), ] def test_create_codebuild_service_boto_session_client(): setup = CodeBuildServiceTestSetup() assert setup.boto_session.mock_calls == [ - call.client('codebuild'), + call.client("codebuild"), ] def test_create_codebuild_service_internal_aws_client(): setup = CodeBuildServiceTestSetup() - assert setup.codebuild_service.internal_aws_client == mock_cast(setup.boto_session.client).return_value + assert ( + setup.codebuild_service.internal_aws_client + == mock_cast(setup.boto_session.client).return_value + ) @dataclasses.dataclass class CloudFormationServiceTestSetup: boto_session: Union[MagicMock, Session] = create_autospec(Session) boto_session_factory = Mock(return_value=boto_session) - aws_client = AwsClient(profile="profile", region="region", - boto_session_factory=boto_session_factory) + aws_client = AwsClient( + profile="profile", region="region", boto_session_factory=boto_session_factory + ) cloudformation_service = aws_client.create_cloudformation_service() def test_create_cloudformation_service_boto_session_factory(): setup = CloudFormationServiceTestSetup() assert setup.boto_session_factory.mock_calls == [ - call(profile_name='profile', region_name='region'), + call(profile_name="profile", region_name="region"), ] def test_create_cloudformation_service_boto_session_client(): setup = CloudFormationServiceTestSetup() assert setup.boto_session.mock_calls == [ - call.client('cloudformation'), + call.client("cloudformation"), ] def test_create_cloudformation_service_internal_aws_client(): setup = CloudFormationServiceTestSetup() - assert setup.cloudformation_service.internal_aws_client == mock_cast(setup.boto_session.client).return_value + assert ( + setup.cloudformation_service.internal_aws_client + == mock_cast(setup.boto_session.client).return_value + ) @dataclasses.dataclass class SecreteManagerServiceTestSetup: boto_session: Union[MagicMock, Session] = create_autospec(Session) boto_session_factory = Mock(return_value=boto_session) - aws_client = AwsClient(profile="profile", region="region", - boto_session_factory=boto_session_factory) + aws_client = AwsClient( + profile="profile", region="region", boto_session_factory=boto_session_factory + ) secretsmanager_service = aws_client.create_secretsmanager_service() def test_create_secretsmanager_service_boto_session_factory(): setup = SecreteManagerServiceTestSetup() assert setup.boto_session_factory.mock_calls == [ - call(profile_name='profile', region_name='region'), + call(profile_name="profile", region_name="region"), ] def test_create_secretsmanager_service_boto_session_client(): setup = SecreteManagerServiceTestSetup() assert setup.boto_session.mock_calls == [ - call.client('secretsmanager'), + call.client("secretsmanager"), ] def test_create_secretsmanager_service_internal_aws_client(): setup = SecreteManagerServiceTestSetup() - assert setup.secretsmanager_service.internal_aws_client == mock_cast(setup.boto_session.client).return_value + assert ( + setup.secretsmanager_service.internal_aws_client + == mock_cast(setup.boto_session.client).return_value + ) diff --git a/test/unit_tests/aws/wrapper/test_cloudformation_service.py b/test/unit/aws/wrapper/test_cloudformation_service.py similarity index 58% rename from test/unit_tests/aws/wrapper/test_cloudformation_service.py rename to test/unit/aws/wrapper/test_cloudformation_service.py index a0644ce..4c6d5b2 100644 --- a/test/unit_tests/aws/wrapper/test_cloudformation_service.py +++ b/test/unit/aws/wrapper/test_cloudformation_service.py @@ -1,13 +1,22 @@ import dataclasses +from test.mock_cast import mock_cast from typing import Optional -from unittest.mock import Mock, call +from unittest.mock import ( + Mock, + call, +) import pytest -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import NextToken -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.cloudformation_service import CloudFormationService -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId -from test.mock_cast import mock_cast +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.cloudformation_service import ( + CloudFormationService, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ( + NextToken, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) def test_init(): @@ -22,20 +31,30 @@ class ValidateTemplateSetup: from_boto = Mock() service = CloudFormationService(internal_aws_client=internal_aws_client) template_body = "TemplateBody" - validation_result = service.validate_template(template_body=template_body, from_boto=from_boto) - internal_aws_client_validate_template_return_value = mock_cast(internal_aws_client.validate_template).return_value + validation_result = service.validate_template( + template_body=template_body, from_boto=from_boto + ) + internal_aws_client_validate_template_return_value = mock_cast( + internal_aws_client.validate_template + ).return_value def test_validate_template_internal_aws_client(): setup = ValidateTemplateSetup() - assert setup.internal_aws_client.mock_calls == [call.validate_template(TemplateBody=setup.template_body)] \ - and setup.from_boto.mock_calls == [call(setup.internal_aws_client_validate_template_return_value)] \ - and setup.validation_result == setup.from_boto.return_value + assert ( + setup.internal_aws_client.mock_calls + == [call.validate_template(TemplateBody=setup.template_body)] + and setup.from_boto.mock_calls + == [call(setup.internal_aws_client_validate_template_return_value)] + and setup.validation_result == setup.from_boto.return_value + ) def test_validate_template_from_boto(): setup = ValidateTemplateSetup() - assert setup.from_boto.mock_calls == [call(setup.internal_aws_client_validate_template_return_value)] + assert setup.from_boto.mock_calls == [ + call(setup.internal_aws_client_validate_template_return_value) + ] def test_validate_template_result(): @@ -48,19 +67,30 @@ def __init__(self, next_token: Optional[NextToken]): self.next_token = next_token self.internal_aws_client = Mock() self.from_boto = Mock() - self.service = CloudFormationService(internal_aws_client=self.internal_aws_client) - self.physical_resource_id = PhysicalResourceId(aws_physical_resource_id="stack_name") + self.service = CloudFormationService( + internal_aws_client=self.internal_aws_client + ) + self.physical_resource_id = PhysicalResourceId( + aws_physical_resource_id="stack_name" + ) self.list_stack_resources_result = self.service.list_stack_resources( - stack_name=self.physical_resource_id, next_token=next_token, from_boto=self.from_boto) + stack_name=self.physical_resource_id, + next_token=next_token, + from_boto=self.from_boto, + ) self.aws_next_token = None if next_token is None else next_token.aws_next_token self.internal_aws_client_list_stack_resources_return_value = mock_cast( - self.internal_aws_client.list_stack_resources).return_value + self.internal_aws_client.list_stack_resources + ).return_value def test_list_stack_resources_internal_aws_client_next_token_is_none(): setup = ListStackResourcesTestSetup(None) assert setup.internal_aws_client.mock_calls == [ - call.list_stack_resources(StackName=setup.physical_resource_id.aws_physical_resource_id)] + call.list_stack_resources( + StackName=setup.physical_resource_id.aws_physical_resource_id + ) + ] def test_list_stack_resources_internal_aws_client_next_token_is_not_none(): @@ -69,20 +99,22 @@ def test_list_stack_resources_internal_aws_client_next_token_is_not_none(): assert setup.internal_aws_client.mock_calls == [ call.list_stack_resources( StackName=setup.physical_resource_id.aws_physical_resource_id, - NextToken=next_token.aws_next_token) + NextToken=next_token.aws_next_token, + ) ] -list_stack_resources_parameters = pytest.mark.parametrize("next_token", [ - NextToken(aws_next_token="next_token"), - None -]) +list_stack_resources_parameters = pytest.mark.parametrize( + "next_token", [NextToken(aws_next_token="next_token"), None] +) @list_stack_resources_parameters def test_list_stack_resources_from_boto(next_token): setup = ListStackResourcesTestSetup(next_token) - assert setup.from_boto.mock_calls == [call(setup.internal_aws_client_list_stack_resources_return_value)] + assert setup.from_boto.mock_calls == [ + call(setup.internal_aws_client_list_stack_resources_return_value) + ] @list_stack_resources_parameters diff --git a/test/unit_tests/aws/wrapper/test_codebuild_service.py b/test/unit/aws/wrapper/test_codebuild_service.py similarity index 62% rename from test/unit_tests/aws/wrapper/test_codebuild_service.py rename to test/unit/aws/wrapper/test_codebuild_service.py index e07011f..76926fe 100644 --- a/test/unit_tests/aws/wrapper/test_codebuild_service.py +++ b/test/unit/aws/wrapper/test_codebuild_service.py @@ -1,9 +1,16 @@ import dataclasses -from unittest.mock import Mock, call - -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.codebuild_service import CodeBuildService -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId from test.mock_cast import mock_cast +from unittest.mock import ( + Mock, + call, +) + +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.codebuild_service import ( + CodeBuildService, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) def test_init(): @@ -17,27 +24,35 @@ class BatchGetBuildBatchesTestSetup: internal_aws_client = Mock() batch_get_build_batches_return_values = [Mock(), Mock()] mock_cast(internal_aws_client.batch_get_build_batches).return_value = { - 'buildBatches': batch_get_build_batches_return_values + "buildBatches": batch_get_build_batches_return_values } from_boto = Mock() from_boto_return_values = [Mock(), Mock()] from_boto.side_effect = from_boto_return_values service = CodeBuildService(internal_aws_client=internal_aws_client) - build_batch_ids = [PhysicalResourceId(aws_physical_resource_id="1"), - PhysicalResourceId(aws_physical_resource_id="2")] - build_batches = service.batch_get_build_batches(build_batch_ids=build_batch_ids, from_boto=from_boto) + build_batch_ids = [ + PhysicalResourceId(aws_physical_resource_id="1"), + PhysicalResourceId(aws_physical_resource_id="2"), + ] + build_batches = service.batch_get_build_batches( + build_batch_ids=build_batch_ids, from_boto=from_boto + ) ids = [id.aws_physical_resource_id for id in build_batch_ids] def test_batch_get_build_batches_internal_aws_client(): setup = BatchGetBuildBatchesTestSetup() - assert setup.internal_aws_client.mock_calls == [call.batch_get_build_batches(ids=setup.ids)] + assert setup.internal_aws_client.mock_calls == [ + call.batch_get_build_batches(ids=setup.ids) + ] def test_batch_get_build_batches_from_boto(): setup = BatchGetBuildBatchesTestSetup() - assert setup.from_boto.mock_calls == [call(return_value) for return_value in - setup.batch_get_build_batches_return_values] + assert setup.from_boto.mock_calls == [ + call(return_value) + for return_value in setup.batch_get_build_batches_return_values + ] def test_batch_get_build_batches_result(): @@ -50,25 +65,32 @@ class StartBuildBatchTestSetup: internal_aws_client = Mock() from_boto_input = Mock() start_build_batch_return_values = {"buildBatch": from_boto_input} - mock_cast(internal_aws_client.start_build_batch).return_value = start_build_batch_return_values + mock_cast(internal_aws_client.start_build_batch).return_value = ( + start_build_batch_return_values + ) from_boto = Mock() from_boto.return_value = Mock() service = CodeBuildService(internal_aws_client=internal_aws_client) projectName = PhysicalResourceId(aws_physical_resource_id="id") sourceVersion = Mock() environmentVariablesOverride = Mock() - build_batch = service.start_build_batch(project_name=projectName, - source_version=sourceVersion, - environment_variables_override=environmentVariablesOverride, - from_boto=from_boto) + build_batch = service.start_build_batch( + project_name=projectName, + source_version=sourceVersion, + environment_variables_override=environmentVariablesOverride, + from_boto=from_boto, + ) def test_start_build_batch_internal_aws_client(): setup = StartBuildBatchTestSetup() assert setup.internal_aws_client.mock_calls == [ - call.start_build_batch(projectName=setup.projectName.aws_physical_resource_id, - sourceVersion=setup.sourceVersion, - environmentVariablesOverride=setup.environmentVariablesOverride)] + call.start_build_batch( + projectName=setup.projectName.aws_physical_resource_id, + sourceVersion=setup.sourceVersion, + environmentVariablesOverride=setup.environmentVariablesOverride, + ) + ] def test_start_build_batch_from_boto(): diff --git a/test/unit_tests/aws/wrapper/test_secretsmanager_service.py b/test/unit/aws/wrapper/test_secretsmanager_service.py similarity index 78% rename from test/unit_tests/aws/wrapper/test_secretsmanager_service.py rename to test/unit/aws/wrapper/test_secretsmanager_service.py index d97272f..06aa51d 100644 --- a/test/unit_tests/aws/wrapper/test_secretsmanager_service.py +++ b/test/unit/aws/wrapper/test_secretsmanager_service.py @@ -1,9 +1,16 @@ import dataclasses -from unittest.mock import Mock, call - -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.secretsmanager_service import SecretsManagerService from test.mock_cast import mock_cast +from unittest.mock import ( + Mock, + call, +) + +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.secretsmanager_service import ( + SecretsManagerService, +) def test_init(): @@ -16,7 +23,9 @@ def test_init(): class GetSecretValueTestSetup: internal_aws_client = Mock() get_secret_value_return_values = Mock() - mock_cast(internal_aws_client.get_secret_value).return_value = get_secret_value_return_values + mock_cast(internal_aws_client.get_secret_value).return_value = ( + get_secret_value_return_values + ) from_boto = Mock() from_boto_return_values = Mock() from_boto.return_value = from_boto_return_values @@ -27,7 +36,9 @@ class GetSecretValueTestSetup: def test_get_secret_value_internal_aws_client(): setup = GetSecretValueTestSetup() - assert setup.internal_aws_client.mock_calls == [call.get_secret_value(SecretId=setup.secret_id.aws_physical_resource_id)] + assert setup.internal_aws_client.mock_calls == [ + call.get_secret_value(SecretId=setup.secret_id.aws_physical_resource_id) + ] def test_get_secret_value_from_boto(): diff --git a/test/unit_tests/cloudformation_validation.py b/test/unit/cloudformation_validation.py similarity index 81% rename from test/unit_tests/cloudformation_validation.py rename to test/unit/cloudformation_validation.py index 110f0b5..bd11390 100644 --- a/test/unit_tests/cloudformation_validation.py +++ b/test/unit/cloudformation_validation.py @@ -10,10 +10,11 @@ def validate_using_cfn_lint(tmp_path, cloudformation_yml): with open(out_file, "w") as f: f.write(cloudformation_yml) - completed_process = subprocess.run(["cfn-lint", str(out_file.absolute())], capture_output=True) + completed_process = subprocess.run( + ["cfn-lint", str(out_file.absolute())], capture_output=True + ) try: completed_process.check_returncode() except subprocess.CalledProcessError as e: print(e.stdout) raise e - diff --git a/test/unit/conftest.py b/test/unit/conftest.py new file mode 100644 index 0000000..e69de29 diff --git a/test/unit_tests/test_aws_access_start_code_build.py b/test/unit/test_aws_access_start_code_build.py similarity index 67% rename from test/unit_tests/test_aws_access_start_code_build.py rename to test/unit/test_aws_access_start_code_build.py index 8f5e1c6..a8a00e2 100644 --- a/test/unit_tests/test_aws_access_start_code_build.py +++ b/test/unit/test_aws_access_start_code_build.py @@ -1,44 +1,81 @@ from contextlib import suppress -from typing import List, Union -from unittest.mock import Mock, call, MagicMock, create_autospec +from test.mock_cast import mock_cast +from typing import ( + List, + Union, +) +from unittest.mock import ( + MagicMock, + Mock, + call, + create_autospec, +) import pytest from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.aws_client import AwsClient, AwsClientFactory -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.codebuild_service import CodeBuildService -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.codebuild import BuildBatch, BuildBatchStatus -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId -from exasol_script_languages_container_ci_setup.lib.run_start_build import get_environment_variable_override -from test.mock_cast import mock_cast +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.aws_client import ( + AwsClient, + AwsClientFactory, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.codebuild_service import ( + CodeBuildService, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.codebuild import ( + BuildBatch, + BuildBatchStatus, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) +from exasol_script_languages_container_ci_setup.lib.run_start_build import ( + get_environment_variable_override, +) ID = "id" -BRANCH = 'branch' +BRANCH = "branch" -PROJECT = 'project' +PROJECT = "project" class TestSetup: def __init__(self, batch_get_build_batches_return_values: List[List[BuildBatch]]): - self.batch_get_build_batches_return_values = batch_get_build_batches_return_values - self.code_build_service: Union[MagicMock, CodeBuildService] = create_autospec(CodeBuildService) - mock_cast(self.code_build_service.batch_get_build_batches).side_effect = \ + self.batch_get_build_batches_return_values = ( + batch_get_build_batches_return_values + ) + self.code_build_service: Union[MagicMock, CodeBuildService] = create_autospec( + CodeBuildService + ) + mock_cast(self.code_build_service.batch_get_build_batches).side_effect = ( self.batch_get_build_batches_return_values - self.started_build_batch = BuildBatch(id=PhysicalResourceId("id"), build_batch_status=None) + ) + self.started_build_batch = BuildBatch( + id=PhysicalResourceId("id"), build_batch_status=None + ) mock_cast(self.code_build_service.start_build_batch).side_effect = [ self.started_build_batch ] self.aws_client_mock: Union[MagicMock, AwsClient] = create_autospec(AwsClient) - mock_cast(self.aws_client_mock.create_codebuild_service).side_effect = [self.code_build_service] + mock_cast(self.aws_client_mock.create_codebuild_service).side_effect = [ + self.code_build_service + ] - self.aws_client_factory_mock: Union[MagicMock, AwsClientFactory] = create_autospec(AwsClientFactory) - mock_cast(self.aws_client_factory_mock.create).side_effect = [self.aws_client_mock] + self.aws_client_factory_mock: Union[MagicMock, AwsClientFactory] = ( + create_autospec(AwsClientFactory) + ) + mock_cast(self.aws_client_factory_mock.create).side_effect = [ + self.aws_client_mock + ] self.profile = "profile" - self.aws_access = AwsAccess(aws_profile=self.profile, aws_client_factory=self.aws_client_factory_mock) - self.environment_variables_overrides = self._create_environment_variables_overrides() + self.aws_access = AwsAccess( + aws_profile=self.profile, aws_client_factory=self.aws_client_factory_mock + ) + self.environment_variables_overrides = ( + self._create_environment_variables_overrides() + ) self.sleep_function_mock = Mock() self.timeout_in_seconds = 5 self.poll_interval_seconds = 1 @@ -50,25 +87,27 @@ def run_start_codebuild(self): environment_variables_overrides=self.environment_variables_overrides, timeout_in_seconds=self.timeout_in_seconds, poll_interval_seconds=self.poll_interval_seconds, - sleep_function=self.sleep_function_mock + sleep_function=self.sleep_function_mock, ) def _create_environment_variables_overrides(self): - env_variables = [("RELEASE_ID", "release_id"), - ("DRY_RUN", "dry_run_value"), - ("GITHUB_TOKEN", "gh_token")] - environment_variables_overrides = list(map(get_environment_variable_override, env_variables)) + env_variables = [ + ("RELEASE_ID", "release_id"), + ("DRY_RUN", "dry_run_value"), + ("GITHUB_TOKEN", "gh_token"), + ] + environment_variables_overrides = list( + map(get_environment_variable_override, env_variables) + ) return environment_variables_overrides -def create_batch_get_build_batches_return_values_for_success() -> List[List[BuildBatch]]: +def create_batch_get_build_batches_return_values_for_success() -> ( + List[List[BuildBatch]] +): batch_get_build_batches_return_values = [ - [ - BuildBatch(build_batch_status=BuildBatchStatus.IN_PROGRESS, id=None) - ], - [ - BuildBatch(build_batch_status=BuildBatchStatus.SUCCEEDED, id=None) - ], + [BuildBatch(build_batch_status=BuildBatchStatus.IN_PROGRESS, id=None)], + [BuildBatch(build_batch_status=BuildBatchStatus.SUCCEEDED, id=None)], ] return batch_get_build_batches_return_values @@ -82,7 +121,9 @@ def test_success_aws_client_mock_call(): def test_success_aws_client_factory_mock_call(): setup = TestSetup(create_batch_get_build_batches_return_values_for_success()) setup.run_start_codebuild() - assert setup.aws_client_factory_mock.mock_calls == [call.create(profile=setup.profile)] + assert setup.aws_client_factory_mock.mock_calls == [ + call.create(profile=setup.profile) + ] def test_success_code_build_service_mock_call(): @@ -92,25 +133,24 @@ def test_success_code_build_service_mock_call(): call.start_build_batch( project_name=PhysicalResourceId(aws_physical_resource_id=PROJECT), source_version=BRANCH, - environment_variables_override=setup.environment_variables_overrides), + environment_variables_override=setup.environment_variables_overrides, + ), + call.batch_get_build_batches(build_batch_ids=[setup.started_build_batch.id]), call.batch_get_build_batches(build_batch_ids=[setup.started_build_batch.id]), - call.batch_get_build_batches(build_batch_ids=[setup.started_build_batch.id]) ] def test_success_sleep_function_mock_call(): setup = TestSetup(create_batch_get_build_batches_return_values_for_success()) setup.run_start_codebuild() - assert setup.sleep_function_mock.mock_calls == [ - call(1), call(1) - ] + assert setup.sleep_function_mock.mock_calls == [call(1), call(1)] -def create_batch_get_build_batches_return_values_for_timeout() -> List[List[BuildBatch]]: +def create_batch_get_build_batches_return_values_for_timeout() -> ( + List[List[BuildBatch]] +): batch_get_build_batches_return_values = [ - [ - BuildBatch(build_batch_status=BuildBatchStatus.IN_PROGRESS, id=None) - ] + [BuildBatch(build_batch_status=BuildBatchStatus.IN_PROGRESS, id=None)] for i in range(5) ] return batch_get_build_batches_return_values @@ -133,7 +173,9 @@ def test_timeout_aws_client_factory_mock_call(): setup = TestSetup(create_batch_get_build_batches_return_values_for_timeout()) with suppress(Exception): setup.run_start_codebuild() - assert setup.aws_client_factory_mock.mock_calls == [call.create(profile=setup.profile)] + assert setup.aws_client_factory_mock.mock_calls == [ + call.create(profile=setup.profile) + ] def test_timeout_code_build_service_mock_call(): @@ -144,11 +186,12 @@ def test_timeout_code_build_service_mock_call(): call.start_build_batch( project_name=PhysicalResourceId(aws_physical_resource_id=PROJECT), source_version=BRANCH, - environment_variables_override=setup.environment_variables_overrides) + environment_variables_override=setup.environment_variables_overrides, + ) ] + [ - call.batch_get_build_batches(build_batch_ids=[setup.started_build_batch.id]) - for _ in setup.batch_get_build_batches_return_values - ] + call.batch_get_build_batches(build_batch_ids=[setup.started_build_batch.id]) + for _ in setup.batch_get_build_batches_return_values + ] def test_timeout_sleep_function_mock_call(): diff --git a/test/unit_tests/test_deploy_ci.py b/test/unit/test_deploy_ci.py similarity index 55% rename from test/unit_tests/test_deploy_ci.py rename to test/unit/test_deploy_ci.py index b7fcd55..b41a5b4 100644 --- a/test/unit_tests/test_deploy_ci.py +++ b/test/unit/test_deploy_ci.py @@ -1,15 +1,29 @@ +from test.unit.cloudformation_validation import validate_using_cfn_lint from typing import Union -from unittest.mock import MagicMock, create_autospec, call +from unittest.mock import ( + MagicMock, + call, + create_autospec, +) import pytest from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ARN -from exasol_script_languages_container_ci_setup.lib.ci_build import run_deploy_ci_build, ci_stack_name, \ - CI_BUILD_WEBHOOK_FILTER_PATTERN -from exasol_script_languages_container_ci_setup.lib.release_build import run_deploy_release_build, release_stack_name -from exasol_script_languages_container_ci_setup.lib.render_template import render_template -from test.unit_tests.cloudformation_validation import validate_using_cfn_lint +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + ARN, +) +from exasol_script_languages_container_ci_setup.lib.ci_build import ( + CI_BUILD_WEBHOOK_FILTER_PATTERN, + ci_stack_name, + run_deploy_ci_build, +) +from exasol_script_languages_container_ci_setup.lib.release_build import ( + release_stack_name, + run_deploy_release_build, +) +from exasol_script_languages_container_ci_setup.lib.render_template import ( + render_template, +) PROJECT = "slc" GH_URL = "https://github.com/slc" @@ -18,21 +32,29 @@ @pytest.fixture def ci_code_build_yml(): - return render_template("slc_code_build.yaml", project=PROJECT, - dockerhub_secret_arn=DOCKERHUB_SECRET_ARN, github_url=GH_URL, - webhook_filter_pattern=CI_BUILD_WEBHOOK_FILTER_PATTERN) + return render_template( + "slc_code_build.yaml", + project=PROJECT, + dockerhub_secret_arn=DOCKERHUB_SECRET_ARN, + github_url=GH_URL, + webhook_filter_pattern=CI_BUILD_WEBHOOK_FILTER_PATTERN, + ) def test_deploy_ci_upload_invoked(ci_code_build_yml): - """" + """ " Test if function upload_cloudformation_stack() will be invoked with expected values when we run run_deploy_ci_build() """ aws_access_mock: Union[MagicMock, AwsAccess] = create_autospec(AwsAccess) - aws_access_mock.read_dockerhub_secret_arn.return_value = ARN(aws_arn=DOCKERHUB_SECRET_ARN) - run_deploy_ci_build(aws_access=aws_access_mock, project=PROJECT, - github_url=GH_URL) - assert call.upload_cloudformation_stack(ci_code_build_yml, ci_stack_name(PROJECT)) in aws_access_mock.mock_calls + aws_access_mock.read_dockerhub_secret_arn.return_value = ARN( + aws_arn=DOCKERHUB_SECRET_ARN + ) + run_deploy_ci_build(aws_access=aws_access_mock, project=PROJECT, github_url=GH_URL) + assert ( + call.upload_cloudformation_stack(ci_code_build_yml, ci_stack_name(PROJECT)) + in aws_access_mock.mock_calls + ) def test_deploy_ci_template_with_cnf_lint(tmp_path, ci_code_build_yml): @@ -41,21 +63,30 @@ def test_deploy_ci_template_with_cnf_lint(tmp_path, ci_code_build_yml): @pytest.fixture def release_code_build_yml(): - return render_template("slc_code_release_build.yaml", project=PROJECT, - dockerhub_secret_arn=DOCKERHUB_SECRET_ARN, github_url=GH_URL) + return render_template( + "slc_code_release_build.yaml", + project=PROJECT, + dockerhub_secret_arn=DOCKERHUB_SECRET_ARN, + github_url=GH_URL, + ) def test_deploy_release_upload_invoked(release_code_build_yml): - """" + """ " Test if function upload_cloudformation_stack() will be invoked with expected values when we run run_deploy_release_build() """ aws_access_mock: Union[MagicMock, AwsAccess] = create_autospec(AwsAccess) aws_access_mock.read_dockerhub_secret_arn.return_value = DOCKERHUB_SECRET_ARN - run_deploy_release_build(aws_access=aws_access_mock, project=PROJECT, - github_url=GH_URL) - assert call.upload_cloudformation_stack(release_code_build_yml, release_stack_name(PROJECT)) \ - in aws_access_mock.mock_calls + run_deploy_release_build( + aws_access=aws_access_mock, project=PROJECT, github_url=GH_URL + ) + assert ( + call.upload_cloudformation_stack( + release_code_build_yml, release_stack_name(PROJECT) + ) + in aws_access_mock.mock_calls + ) def test_deploy_release_template_with_cnf_lint(tmp_path, release_code_build_yml): diff --git a/test/unit/test_deploy_source_credentials.py b/test/unit/test_deploy_source_credentials.py new file mode 100644 index 0000000..6fb90bb --- /dev/null +++ b/test/unit/test_deploy_source_credentials.py @@ -0,0 +1,58 @@ +from test.unit.cloudformation_validation import validate_using_cfn_lint +from typing import Union +from unittest.mock import ( + MagicMock, + call, + create_autospec, +) + +import pytest + +from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess +from exasol_script_languages_container_ci_setup.lib.render_template import ( + render_template, +) +from exasol_script_languages_container_ci_setup.lib.source_credentials import ( + SOURCE_CREDENTIALS_STACK_NAME, + run_deploy_source_credentials, +) + +SECRET_NAME = "test_secret" +SECRET_USER_KEY = "test_secret_user_key" +SECRET_TOKEN_KEY = "test_secret_token_key" + + +@pytest.fixture +def source_credentials_yml(): + return render_template( + "slc_source_credential.yaml", + secret_name=SECRET_NAME, + secret_user_key=SECRET_USER_KEY, + secret_token_key=SECRET_TOKEN_KEY, + ) + + +def test_deploy_source_credentials_upload_invoked(source_credentials_yml): + """ + Test if function upload_cloudformation_stack() will be invoked with expected values + when we run run_deploy_source_credentials() + """ + aws_access_mock: Union[MagicMock, AwsAccess] = create_autospec(AwsAccess) + run_deploy_source_credentials( + aws_access=aws_access_mock, + secret_name=SECRET_NAME, + secret_user_key=SECRET_USER_KEY, + secret_token_key=SECRET_TOKEN_KEY, + ) + assert ( + call.upload_cloudformation_stack( + source_credentials_yml, SOURCE_CREDENTIALS_STACK_NAME + ) + in aws_access_mock.mock_calls + ) + + +def test_deploy_source_credentials_template_with_cnf_lint( + tmp_path, source_credentials_yml +): + validate_using_cfn_lint(tmp_path, source_credentials_yml) diff --git a/test/unit_tests/test_generate_buildspec.py b/test/unit/test_generate_buildspec.py similarity index 64% rename from test/unit_tests/test_generate_buildspec.py rename to test/unit/test_generate_buildspec.py index cb327b5..41f001d 100644 --- a/test/unit_tests/test_generate_buildspec.py +++ b/test/unit/test_generate_buildspec.py @@ -2,12 +2,23 @@ import pydantic import pytest - -from exasol_script_languages_container_ci.lib.config.config_data_model import Config, Build, Ignore, Release -from exasol_script_languages_container_ci_setup.lib.render_template import render_template -from exasol_script_languages_container_ci_setup.lib.run_generate_buildspec import run_generate_buildspec, \ - get_config_file_parameter -from exasol_script_languages_container_ci_setup.lib.run_generate_release_buildspec import run_generate_release_buildspec +from exasol_script_languages_container_ci.lib.config.config_data_model import ( + Build, + Config, + Ignore, + Release, +) + +from exasol_script_languages_container_ci_setup.lib.render_template import ( + render_template, +) +from exasol_script_languages_container_ci_setup.lib.run_generate_buildspec import ( + get_config_file_parameter, + run_generate_buildspec, +) +from exasol_script_languages_container_ci_setup.lib.run_generate_release_buildspec import ( + run_generate_release_buildspec, +) expected_result_root_buildspec = """version: 0.2 @@ -37,18 +48,22 @@ def test_buildspec(tmp_path): out_path = tmp_path / "out" out_path.mkdir(parents=False, exist_ok=False) - run_generate_buildspec((str(root_path),), str(out_path.absolute()), config_file=None) + run_generate_buildspec( + (str(root_path),), str(out_path.absolute()), config_file=None + ) - with open(out_path / "buildspec.yaml", "r") as res_file: + with open(out_path / "buildspec.yaml") as res_file: res = res_file.read() assert res == expected_result_root_buildspec.format(location=str(out_path)) - with open(out_path / "build_buildspec.yaml", "r") as res_file: + with open(out_path / "build_buildspec.yaml") as res_file: res = res_file.read() # For build_buildspec.yaml we re-use the template for testing - expected_result_build_buildspec = render_template("build_buildspec.yaml", config_file_parameter="") + expected_result_build_buildspec = render_template( + "build_buildspec.yaml", config_file_parameter="" + ) assert res == expected_result_build_buildspec @@ -62,18 +77,22 @@ def test_release_buildspec(tmp_path): out_path = tmp_path / "out" out_path.mkdir(parents=False, exist_ok=False) - run_generate_release_buildspec((str(root_path),), str(out_path.absolute()), config_file=None) + run_generate_release_buildspec( + (str(root_path),), str(out_path.absolute()), config_file=None + ) - with open(out_path / "buildspec.yaml", "r") as res_file: + with open(out_path / "buildspec.yaml") as res_file: res = res_file.read() assert res == expected_result_root_buildspec.format(location=str(out_path)) - with open(out_path / "build_buildspec.yaml", "r") as res_file: + with open(out_path / "build_buildspec.yaml") as res_file: res = res_file.read() # For build_buildspec.yaml we re-use the template for testing - expected_result_build_buildspec = render_template("release_build_buildspec.yaml", config_file_parameter="") + expected_result_build_buildspec = render_template( + "release_build_buildspec.yaml", config_file_parameter="" + ) assert res == expected_result_build_buildspec @@ -92,35 +111,32 @@ def test_buildspec_with_valid_config_file(tmp_path): config_file_path = tmp_path / "build_config.json" config = Config( - build=Build( - ignore=Ignore( - paths=[str(a_folder)] - ), - base_branch="master" - ), - release=Release( - timeout_in_minutes=10 - ) + build=Build(ignore=Ignore(paths=[str(a_folder)]), base_branch="master"), + release=Release(timeout_in_minutes=10), ) with open(config_file_path, "w") as f: f.write(config.json()) - run_generate_buildspec((str(root_path),), str(out_path.absolute()), - config_file=str(config_file_path.absolute())) + run_generate_buildspec( + (str(root_path),), + str(out_path.absolute()), + config_file=str(config_file_path.absolute()), + ) - with open(out_path / "buildspec.yaml", "r") as res_file: + with open(out_path / "buildspec.yaml") as res_file: res = res_file.read() assert res == expected_result_root_buildspec.format(location=str(out_path)) - with open(out_path / "build_buildspec.yaml", "r") as res_file: + with open(out_path / "build_buildspec.yaml") as res_file: res = res_file.read() # For build_buildspec.yaml we re-use the template for testing - expected_result_build_buildspec = render_template("build_buildspec.yaml", - config_file_parameter= - get_config_file_parameter(str(config_file_path))) + expected_result_build_buildspec = render_template( + "build_buildspec.yaml", + config_file_parameter=get_config_file_parameter(str(config_file_path)), + ) assert res == expected_result_build_buildspec @@ -139,19 +155,23 @@ def test_buildspec_with_invalid_config_file(tmp_path): config = { "build": { "ignore": { - "path": ["/tmp/pytest-of-tk/pytest-11/test_buildspec_with_valid_conf0/a_folder"] + "path": [ + "/tmp/pytest-of-tk/pytest-11/test_buildspec_with_valid_conf0/a_folder" + ] }, - "base_branch": "master"}, - "release": { - "timeout_in_minutes": 10 - } + "base_branch": "master", + }, + "release": {"timeout_in_minutes": 10}, } with open(config_file_path, "w") as f: json.dump(config, f) with pytest.raises(pydantic.ValidationError): - run_generate_buildspec((str(root_path),), str(out_path.absolute()), - config_file=str(config_file_path.absolute())) + run_generate_buildspec( + (str(root_path),), + str(out_path.absolute()), + config_file=str(config_file_path.absolute()), + ) def test_buildspec_with_invalid_folder(tmp_path): @@ -170,19 +190,15 @@ def test_buildspec_with_invalid_folder(tmp_path): a_folder = tmp_path / "a_folder" # Incorrect config (tmp_path/a_folder does not exists) config = Config( - build=Build( - ignore=Ignore( - paths=[str(a_folder)] - ), - base_branch="master" - ), - release=Release( - timeout_in_minutes=10 - ) + build=Build(ignore=Ignore(paths=[str(a_folder)]), base_branch="master"), + release=Release(timeout_in_minutes=10), ) with open(config_file_path, "w") as f: f.write(config.json()) with pytest.raises(ValueError): - run_generate_buildspec((str(root_path),), str(out_path.absolute()), - config_file=str(config_file_path.absolute())) + run_generate_buildspec( + (str(root_path),), + str(out_path.absolute()), + config_file=str(config_file_path.absolute()), + ) diff --git a/test/unit/test_start_ci_build.py b/test/unit/test_start_ci_build.py new file mode 100644 index 0000000..34c1183 --- /dev/null +++ b/test/unit/test_start_ci_build.py @@ -0,0 +1,56 @@ +from typing import Union +from unittest.mock import ( + MagicMock, + call, + create_autospec, +) + +from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ( + StackResourceSummary, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) +from exasol_script_languages_container_ci_setup.lib.run_start_build import ( + run_start_ci_build, +) + +REPO_NAME = "script-languages-repo" +BRANCH = "feature-branch" + + +def test_run_ci_build(): + """ + Test if invocation of run_start_ci_build calls AwsAccess with expected arguments. + """ + aws_access_mock: Union[MagicMock, AwsAccess] = create_autospec(AwsAccess) + physical_resource_id = PhysicalResourceId(aws_physical_resource_id="id") + aws_access_mock.get_all_stack_resources.return_value = [ + StackResourceSummary(physical_resource_id=None, resource_type="SomethingElse"), + StackResourceSummary( + physical_resource_id=physical_resource_id, + resource_type="AWS::CodeBuild::Project", + ), + StackResourceSummary(physical_resource_id=None, resource_type="SomethingElse"), + ] + timeout_in_seconds = 30 + expected_env_variable_overrides = [ + {"name": "CUSTOM_BRANCH", "value": BRANCH, "type": "PLAINTEXT"} + ] + run_start_ci_build( + aws_access=aws_access_mock, + project="slc", + branch=BRANCH, + timeout_in_seconds=timeout_in_seconds, + ) + + assert ( + call.start_codebuild( + physical_resource_id, + environment_variables_overrides=expected_env_variable_overrides, + branch=BRANCH, + timeout_in_seconds=timeout_in_seconds, + ) + in aws_access_mock.mock_calls + ) diff --git a/test/unit_tests/test_start_release_build.py b/test/unit/test_start_release_build.py similarity index 57% rename from test/unit_tests/test_start_release_build.py rename to test/unit/test_start_release_build.py index dc99560..87ce9bb 100644 --- a/test/unit_tests/test_start_release_build.py +++ b/test/unit/test_start_release_build.py @@ -1,14 +1,30 @@ from pathlib import Path from typing import Union -from unittest.mock import MagicMock, create_autospec, call +from unittest.mock import ( + MagicMock, + call, + create_autospec, +) import pytest -from exasol_script_languages_container_ci.lib.config.config_data_model import Build, Ignore, Release, Config +from exasol_script_languages_container_ci.lib.config.config_data_model import ( + Build, + Config, + Ignore, + Release, +) from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import StackResourceSummary -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId -from exasol_script_languages_container_ci_setup.lib.run_start_build import run_start_release_build, DEFAULT_TIMEOUT +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ( + StackResourceSummary, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) +from exasol_script_languages_container_ci_setup.lib.run_start_build import ( + DEFAULT_TIMEOUT, + run_start_release_build, +) UPLOAD_URL = "https://uploads.github.com/repos/exasol/script-languages-repo/releases/123/assets{?name,label}" BRANCH = "main" @@ -22,32 +38,39 @@ (10, None, 10), (None, 20, 20), (30, 40, 30), - ] + ], ) -def test_run_release_build(timeout_in_seconds: int, config_file_timeout: int, expected_result: int, tmp_path: Path): +def test_run_release_build( + timeout_in_seconds: int, + config_file_timeout: int, + expected_result: int, + tmp_path: Path, +): """ Test if invocation of run_start_release_build calls AwsAccess with expected arguments. """ aws_access_mock: Union[MagicMock, AwsAccess] = create_autospec(AwsAccess) physical_resource_id = PhysicalResourceId(aws_physical_resource_id="id") aws_access_mock.get_all_stack_resources.return_value = [ - StackResourceSummary(physical_resource_id=None, - resource_type="SomethingElse"), - StackResourceSummary(physical_resource_id=physical_resource_id, - resource_type="AWS::CodeBuild::Project"), - StackResourceSummary(physical_resource_id=None, - resource_type="SomethingElse") + StackResourceSummary(physical_resource_id=None, resource_type="SomethingElse"), + StackResourceSummary( + physical_resource_id=physical_resource_id, + resource_type="AWS::CodeBuild::Project", + ), + StackResourceSummary(physical_resource_id=None, resource_type="SomethingElse"), ] expected_env_variable_overrides = [ {"name": "RELEASE_ID", "value": "123", "type": "PLAINTEXT"}, {"name": "DRY_RUN", "value": "--no-dry-run", "type": "PLAINTEXT"}, - {"name": "GITHUB_TOKEN", "value": GITHUB_TOKEN, "type": "PLAINTEXT"} + {"name": "GITHUB_TOKEN", "value": GITHUB_TOKEN, "type": "PLAINTEXT"}, ] if config_file_timeout is not None: config_file = str(tmp_path / "config.json") - config = Config(build=Build(base_branch="master", ignore=Ignore(paths=[])), - release=Release(timeout_in_minutes=config_file_timeout)) + config = Config( + build=Build(base_branch="master", ignore=Ignore(paths=[])), + release=Release(timeout_in_minutes=config_file_timeout), + ) with open(config_file, "w") as f: f.write(config.json()) else: @@ -60,10 +83,15 @@ def test_run_release_build(timeout_in_seconds: int, config_file_timeout: int, ex branch=BRANCH, gh_token=GITHUB_TOKEN, timeout_in_seconds=timeout_in_seconds, - config_file_path=config_file) + config_file_path=config_file, + ) - assert call.start_codebuild(physical_resource_id, - environment_variables_overrides=expected_env_variable_overrides, - branch=BRANCH, - timeout_in_seconds=expected_result) \ - in aws_access_mock.mock_calls + assert ( + call.start_codebuild( + physical_resource_id, + environment_variables_overrides=expected_env_variable_overrides, + branch=BRANCH, + timeout_in_seconds=expected_result, + ) + in aws_access_mock.mock_calls + ) diff --git a/test/unit_tests/test_start_test_release_build.py b/test/unit/test_start_test_release_build.py similarity index 60% rename from test/unit_tests/test_start_test_release_build.py rename to test/unit/test_start_test_release_build.py index 8a1fa10..4bf82d8 100644 --- a/test/unit_tests/test_start_test_release_build.py +++ b/test/unit/test_start_test_release_build.py @@ -1,16 +1,34 @@ from pathlib import Path +from test.mock_cast import mock_cast from typing import Union -from unittest.mock import MagicMock, create_autospec, call +from unittest.mock import ( + MagicMock, + call, + create_autospec, +) import pytest +from exasol_script_languages_container_ci.lib.config.config_data_model import ( + Build, + Config, + Ignore, + Release, +) from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import StackResourceSummary -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId -from exasol_script_languages_container_ci.lib.config.config_data_model import Config, Build, Release, Ignore -from exasol_script_languages_container_ci_setup.lib.github_draft_release_creator import GithubDraftReleaseCreator -from exasol_script_languages_container_ci_setup.lib.run_start_build import run_start_test_release_build, DEFAULT_TIMEOUT -from test.mock_cast import mock_cast +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import ( + StackResourceSummary, +) +from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import ( + PhysicalResourceId, +) +from exasol_script_languages_container_ci_setup.lib.github_draft_release_creator import ( + GithubDraftReleaseCreator, +) +from exasol_script_languages_container_ci_setup.lib.run_start_build import ( + DEFAULT_TIMEOUT, + run_start_test_release_build, +) REPO_NAME = "script-languages-repo" BRANCH = "main" @@ -25,36 +43,43 @@ (10, None, 10), (None, 20, 20), (30, 40, 30), - ] + ], ) -def test_run_test_release_build(timeout_in_seconds: int, config_file_timeout: int, expected_result: int, - tmp_path: Path): +def test_run_test_release_build( + timeout_in_seconds: int, + config_file_timeout: int, + expected_result: int, + tmp_path: Path, +): """ Test if invocation of run_start_test_release_build calls AwsAccess with expected arguments. """ aws_access_mock: Union[MagicMock, AwsAccess] = create_autospec(AwsAccess) physical_resource_id = PhysicalResourceId(aws_physical_resource_id="id") aws_access_mock.get_all_stack_resources.return_value = [ - StackResourceSummary(physical_resource_id=None, - resource_type="SomethingElse"), - StackResourceSummary(physical_resource_id=physical_resource_id, - resource_type="AWS::CodeBuild::Project"), - StackResourceSummary(physical_resource_id=None, - resource_type="SomethingElse") + StackResourceSummary(physical_resource_id=None, resource_type="SomethingElse"), + StackResourceSummary( + physical_resource_id=physical_resource_id, + resource_type="AWS::CodeBuild::Project", + ), + StackResourceSummary(physical_resource_id=None, resource_type="SomethingElse"), ] - github_release_creator_mock: Union[MagicMock, GithubDraftReleaseCreator] = \ + github_release_creator_mock: Union[MagicMock, GithubDraftReleaseCreator] = ( create_autospec(GithubDraftReleaseCreator) + ) mock_cast(github_release_creator_mock.create_release).return_value = 123 expected_env_variable_overrides = [ {"name": "RELEASE_ID", "value": "123", "type": "PLAINTEXT"}, {"name": "DRY_RUN", "value": "--dry-run", "type": "PLAINTEXT"}, - {"name": "GITHUB_TOKEN", "value": GITHUB_TOKEN, "type": "PLAINTEXT"} + {"name": "GITHUB_TOKEN", "value": GITHUB_TOKEN, "type": "PLAINTEXT"}, ] if config_file_timeout is not None: config_file = str(tmp_path / "config.json") - config = Config(build=Build(base_branch="master", ignore=Ignore(paths=[])), - release=Release(timeout_in_minutes=config_file_timeout)) + config = Config( + build=Build(base_branch="master", ignore=Ignore(paths=[])), + release=Release(timeout_in_minutes=config_file_timeout), + ) with open(config_file, "w") as f: f.write(config.json()) else: @@ -69,11 +94,15 @@ def test_run_test_release_build(timeout_in_seconds: int, config_file_timeout: in release_title=RELEASE_TITLE, gh_token=GITHUB_TOKEN, timeout_in_seconds=timeout_in_seconds, - config_file_path=config_file + config_file_path=config_file, ) - assert call.start_codebuild(physical_resource_id, - environment_variables_overrides=expected_env_variable_overrides, - branch=BRANCH, - timeout_in_seconds=expected_result) \ - in aws_access_mock.mock_calls + assert ( + call.start_codebuild( + physical_resource_id, + environment_variables_overrides=expected_env_variable_overrides, + branch=BRANCH, + timeout_in_seconds=expected_result, + ) + in aws_access_mock.mock_calls + ) diff --git a/test/unit_tests/test_webhook_filter_pattern.py b/test/unit/test_webhook_filter_pattern.py similarity index 94% rename from test/unit_tests/test_webhook_filter_pattern.py rename to test/unit/test_webhook_filter_pattern.py index a17f7d9..e4ff82d 100644 --- a/test/unit_tests/test_webhook_filter_pattern.py +++ b/test/unit/test_webhook_filter_pattern.py @@ -1,7 +1,10 @@ -import pytest import re -from exasol_script_languages_container_ci_setup.lib.ci_build import CI_BUILD_WEBHOOK_FILTER_PATTERN +import pytest + +from exasol_script_languages_container_ci_setup.lib.ci_build import ( + CI_BUILD_WEBHOOK_FILTER_PATTERN, +) testdata = [ ("refs/heads/feature/test_branch", True), diff --git a/test/unit_tests/conftest.py b/test/unit_tests/conftest.py deleted file mode 100644 index 139597f..0000000 --- a/test/unit_tests/conftest.py +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/test/unit_tests/test_deploy_source_credentials.py b/test/unit_tests/test_deploy_source_credentials.py deleted file mode 100644 index 5e21133..0000000 --- a/test/unit_tests/test_deploy_source_credentials.py +++ /dev/null @@ -1,40 +0,0 @@ -from typing import Union -from unittest.mock import MagicMock, create_autospec, call - -import pytest - -from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.render_template import render_template -from exasol_script_languages_container_ci_setup.lib.source_credentials import ( - run_deploy_source_credentials, - SOURCE_CREDENTIALS_STACK_NAME -) -from test.unit_tests.cloudformation_validation import validate_using_cfn_lint - -SECRET_NAME = "test_secret" -SECRET_USER_KEY = "test_secret_user_key" -SECRET_TOKEN_KEY = "test_secret_token_key" - - -@pytest.fixture -def source_credentials_yml(): - return render_template("slc_source_credential.yaml", - secret_name=SECRET_NAME, - secret_user_key=SECRET_USER_KEY, - secret_token_key=SECRET_TOKEN_KEY) - - -def test_deploy_source_credentials_upload_invoked(source_credentials_yml): - """ - Test if function upload_cloudformation_stack() will be invoked with expected values - when we run run_deploy_source_credentials() - """ - aws_access_mock: Union[MagicMock, AwsAccess] = create_autospec(AwsAccess) - run_deploy_source_credentials(aws_access=aws_access_mock, secret_name=SECRET_NAME, - secret_user_key=SECRET_USER_KEY, secret_token_key=SECRET_TOKEN_KEY) - assert call.upload_cloudformation_stack(source_credentials_yml, SOURCE_CREDENTIALS_STACK_NAME) \ - in aws_access_mock.mock_calls - - -def test_deploy_source_credentials_template_with_cnf_lint(tmp_path, source_credentials_yml): - validate_using_cfn_lint(tmp_path, source_credentials_yml) diff --git a/test/unit_tests/test_start_ci_build.py b/test/unit_tests/test_start_ci_build.py deleted file mode 100644 index 8b7c76d..0000000 --- a/test/unit_tests/test_start_ci_build.py +++ /dev/null @@ -1,36 +0,0 @@ -from typing import Union -from unittest.mock import MagicMock, create_autospec, call - -from exasol_script_languages_container_ci_setup.lib.aws.aws_access import AwsAccess -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.cloudformation import StackResourceSummary -from exasol_script_languages_container_ci_setup.lib.aws.wrapper.datamodels.common import PhysicalResourceId -from exasol_script_languages_container_ci_setup.lib.run_start_build import run_start_ci_build - -REPO_NAME = "script-languages-repo" -BRANCH = "feature-branch" - - -def test_run_ci_build(): - """ - Test if invocation of run_start_ci_build calls AwsAccess with expected arguments. - """ - aws_access_mock: Union[MagicMock, AwsAccess] = create_autospec(AwsAccess) - physical_resource_id = PhysicalResourceId(aws_physical_resource_id="id") - aws_access_mock.get_all_stack_resources.return_value = [ - StackResourceSummary(physical_resource_id=None, - resource_type="SomethingElse"), - StackResourceSummary(physical_resource_id=physical_resource_id, - resource_type="AWS::CodeBuild::Project"), - StackResourceSummary(physical_resource_id=None, - resource_type="SomethingElse") - ] - timeout_in_seconds = 30 - expected_env_variable_overrides = [{"name": "CUSTOM_BRANCH", "value": BRANCH, "type": "PLAINTEXT"}] - run_start_ci_build(aws_access=aws_access_mock, project="slc", branch=BRANCH, - timeout_in_seconds=timeout_in_seconds) - - assert call.start_codebuild(physical_resource_id, - environment_variables_overrides=expected_env_variable_overrides, - branch=BRANCH, - timeout_in_seconds=timeout_in_seconds) \ - in aws_access_mock.mock_calls