aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Reinier van der Leer <pwuts@agpt.co> 2024-04-26 19:29:34 +0200
committerGravatar Reinier van der Leer <pwuts@agpt.co> 2024-04-26 19:29:34 +0200
commit3d10637a5d80a4c10441d45e5fce2ffa5601cf96 (patch)
tree2f3c8806d7d239ebccc21e149143a802a4586145
parentfix(agent/release): Add gitpython as a direct dependency (diff)
parentfix(agent/core): Set `OpenAIProvider._configuration.retries_per_request` to 7... (diff)
downloadAuto-GPT-3d10637a5d80a4c10441d45e5fce2ffa5601cf96.tar.gz
Auto-GPT-3d10637a5d80a4c10441d45e5fce2ffa5601cf96.tar.bz2
Auto-GPT-3d10637a5d80a4c10441d45e5fce2ffa5601cf96.zip
Merge commit '6ff02677d2b30bec8edd5bafcb35e399e33217da' into release-autogpt-v0.5.x
-rw-r--r--.github/CODEOWNERS10
-rw-r--r--.github/labeler.yml23
-rw-r--r--.github/workflows/arena-intake.yml169
-rw-r--r--.github/workflows/autogpt-ci.yml96
-rw-r--r--.github/workflows/autogpt-docker-cache-clean.yml6
-rw-r--r--.github/workflows/autogpt-docker-ci.yml21
-rw-r--r--.github/workflows/autogpt-docker-release.yml9
-rw-r--r--.github/workflows/autogpts-benchmark.yml97
-rw-r--r--.github/workflows/autogpts-ci.yml11
-rw-r--r--.github/workflows/benchmark-ci.yml15
-rw-r--r--.github/workflows/benchmark_publish_package.yml4
-rw-r--r--.github/workflows/build-frontend.yml46
-rw-r--r--.github/workflows/close-stale-issues.yml2
-rw-r--r--.github/workflows/frontend-ci.yml60
-rw-r--r--.github/workflows/hackathon.yml8
-rw-r--r--.github/workflows/pr-label.yml15
-rw-r--r--QUICKSTART.md64
-rw-r--r--README.md10
-rw-r--r--SECURITY.md66
-rw-r--r--autogpts/autogpt/.env.template37
-rw-r--r--autogpts/autogpt/agbenchmark_config/benchmarks.py23
-rw-r--r--autogpts/autogpt/autogpt/agent_factory/configurators.py21
-rw-r--r--autogpts/autogpt/autogpt/agent_factory/generators.py23
-rw-r--r--autogpts/autogpt/autogpt/agent_factory/profile_generator.py38
-rw-r--r--autogpts/autogpt/autogpt/agent_manager/agent_manager.py51
-rw-r--r--autogpts/autogpt/autogpt/agents/agent.py78
-rw-r--r--autogpts/autogpt/autogpt/agents/base.py57
-rw-r--r--autogpts/autogpt/autogpt/agents/features/agent_file_manager.py102
-rw-r--r--autogpts/autogpt/autogpt/agents/features/file_workspace.py65
-rw-r--r--autogpts/autogpt/autogpt/agents/prompt_strategies/one_shot.py70
-rw-r--r--autogpts/autogpt/autogpt/agents/utils/agent_file_manager.py37
-rw-r--r--autogpts/autogpt/autogpt/agents/utils/exceptions.py4
-rw-r--r--autogpts/autogpt/autogpt/app/agent_protocol_server.py206
-rw-r--r--autogpts/autogpt/autogpt/app/cli.py4
-rw-r--r--autogpts/autogpt/autogpt/app/configurator.py64
-rw-r--r--autogpts/autogpt/autogpt/app/main.py175
-rw-r--r--autogpts/autogpt/autogpt/app/setup.py42
-rw-r--r--autogpts/autogpt/autogpt/app/telemetry.py64
-rw-r--r--autogpts/autogpt/autogpt/app/utils.py112
-rw-r--r--autogpts/autogpt/autogpt/command_decorator.py2
-rw-r--r--autogpts/autogpt/autogpt/commands/execute_code.py82
-rw-r--r--autogpts/autogpt/autogpt/commands/file_operations.py69
-rw-r--r--autogpts/autogpt/autogpt/commands/file_operations_utils.py21
-rw-r--r--autogpts/autogpt/autogpt/commands/image_gen.py9
-rw-r--r--autogpts/autogpt/autogpt/commands/system.py4
-rw-r--r--autogpts/autogpt/autogpt/commands/user_interaction.py2
-rw-r--r--autogpts/autogpt/autogpt/commands/web_search.py4
-rw-r--r--autogpts/autogpt/autogpt/commands/web_selenium.py145
-rw-r--r--autogpts/autogpt/autogpt/config/ai_directives.py2
-rw-r--r--autogpts/autogpt/autogpt/config/ai_profile.py2
-rw-r--r--autogpts/autogpt/autogpt/config/config.py121
-rw-r--r--autogpts/autogpt/autogpt/core/ability/builtins/query_language_model.py2
-rw-r--r--autogpts/autogpt/autogpt/core/planning/prompt_strategies/initial_plan.py15
-rw-r--r--autogpts/autogpt/autogpt/core/planning/prompt_strategies/name_and_goals.py14
-rw-r--r--autogpts/autogpt/autogpt/core/planning/prompt_strategies/next_ability.py15
-rw-r--r--autogpts/autogpt/autogpt/core/prompting/base.py4
-rw-r--r--autogpts/autogpt/autogpt/core/prompting/utils.py20
-rw-r--r--autogpts/autogpt/autogpt/core/resource/model_providers/openai.py633
-rw-r--r--autogpts/autogpt/autogpt/core/resource/model_providers/schema.py86
-rw-r--r--autogpts/autogpt/autogpt/core/resource/schema.py15
-rw-r--r--autogpts/autogpt/autogpt/core/runner/cli_web_app/server/api.py4
-rw-r--r--autogpts/autogpt/autogpt/core/runner/client_lib/logging/config.py2
-rw-r--r--autogpts/autogpt/autogpt/core/utils/json_schema.py31
-rw-r--r--autogpts/autogpt/autogpt/core/utils/json_utils.py93
-rw-r--r--autogpts/autogpt/autogpt/file_storage/__init__.py44
-rw-r--r--autogpts/autogpt/autogpt/file_storage/base.py204
-rw-r--r--autogpts/autogpt/autogpt/file_storage/gcs.py213
-rw-r--r--autogpts/autogpt/autogpt/file_storage/local.py139
-rw-r--r--autogpts/autogpt/autogpt/file_storage/s3.py265
-rw-r--r--autogpts/autogpt/autogpt/file_workspace/__init__.py46
-rw-r--r--autogpts/autogpt/autogpt/file_workspace/base.py164
-rw-r--r--autogpts/autogpt/autogpt/file_workspace/gcs.py108
-rw-r--r--autogpts/autogpt/autogpt/file_workspace/local.py71
-rw-r--r--autogpts/autogpt/autogpt/file_workspace/s3.py128
-rw-r--r--autogpts/autogpt/autogpt/json_utils/__init__.py0
-rw-r--r--autogpts/autogpt/autogpt/json_utils/utilities.py35
-rw-r--r--autogpts/autogpt/autogpt/llm/api_manager.py111
-rw-r--r--autogpts/autogpt/autogpt/logs/config.py69
-rw-r--r--autogpts/autogpt/autogpt/logs/utils.py4
-rw-r--r--autogpts/autogpt/autogpt/models/action_history.py93
-rw-r--r--autogpts/autogpt/autogpt/models/command.py4
-rw-r--r--autogpts/autogpt/autogpt/models/context_item.py4
-rw-r--r--autogpts/autogpt/autogpt/plugins/__init__.py23
-rw-r--r--autogpts/autogpt/autogpt/plugins/plugins_config.py2
-rw-r--r--autogpts/autogpt/autogpt/processing/text.py222
-rw-r--r--autogpts/autogpt/autogpt/speech/macos_tts.py8
-rw-r--r--autogpts/autogpt/autogpt/utils.py2
-rw-r--r--autogpts/autogpt/azure.yaml.template8
-rw-r--r--autogpts/autogpt/poetry.lock3569
-rw-r--r--autogpts/autogpt/pyproject.toml16
-rw-r--r--autogpts/autogpt/tests/conftest.py52
-rw-r--r--autogpts/autogpt/tests/integration/memory/_test_json_file_memory.py20
-rw-r--r--autogpts/autogpt/tests/integration/test_execute_code.py9
-rw-r--r--autogpts/autogpt/tests/integration/test_image_gen.py18
-rw-r--r--autogpts/autogpt/tests/integration/test_web_selenium.py4
-rw-r--r--autogpts/autogpt/tests/unit/test_ai_profile.py9
-rw-r--r--autogpts/autogpt/tests/unit/test_api_manager.py89
-rw-r--r--autogpts/autogpt/tests/unit/test_config.py179
-rw-r--r--autogpts/autogpt/tests/unit/test_file_operations.py191
-rw-r--r--autogpts/autogpt/tests/unit/test_gcs_file_storage.py200
-rw-r--r--autogpts/autogpt/tests/unit/test_gcs_file_workspace.py131
-rw-r--r--autogpts/autogpt/tests/unit/test_git_commands.py9
-rw-r--r--autogpts/autogpt/tests/unit/test_json_utils.py93
-rw-r--r--autogpts/autogpt/tests/unit/test_local_file_storage.py211
-rw-r--r--autogpts/autogpt/tests/unit/test_local_file_workspace.py92
-rw-r--r--autogpts/autogpt/tests/unit/test_plugins.py2
-rw-r--r--autogpts/autogpt/tests/unit/test_s3_file_storage.py195
-rw-r--r--autogpts/autogpt/tests/unit/test_s3_file_workspace.py123
-rw-r--r--autogpts/autogpt/tests/unit/test_text_file_parsers.py3
-rw-r--r--autogpts/autogpt/tests/unit/test_utils.py141
-rw-r--r--autogpts/autogpt/tests/utils.py4
-rw-r--r--autogpts/autogpt/tests/vcr/__init__.py63
-rw-r--r--autogpts/autogpt/tests/vcr/vcr_filter.py135
m---------autogpts/autogpt/tests/vcr_cassettes0
-rw-r--r--autogpts/forge/forge/__main__.py14
-rw-r--r--autogpts/forge/forge/actions/__init__.py2
-rw-r--r--autogpts/forge/forge/actions/finish.py3
-rw-r--r--autogpts/forge/forge/actions/registry.py2
-rw-r--r--autogpts/forge/forge/actions/web/web_search.py4
-rw-r--r--autogpts/forge/forge/actions/web/web_selenium.py17
-rw-r--r--autogpts/forge/forge/agent.py3
-rw-r--r--autogpts/forge/forge/app.py1
-rw-r--r--autogpts/forge/forge/db.py13
-rw-r--r--autogpts/forge/forge/llm.py28
-rw-r--r--autogpts/forge/forge/memory/__init__.py2
-rw-r--r--autogpts/forge/forge/memory/chroma_memstore.py5
-rw-r--r--autogpts/forge/forge/sdk/__init__.py6
-rw-r--r--autogpts/forge/forge/sdk/agent.py11
-rw-r--r--autogpts/forge/forge/sdk/db.py73
-rw-r--r--autogpts/forge/forge/sdk/db_test.py8
-rw-r--r--autogpts/forge/forge/sdk/routes/agent_protocol.py86
-rw-r--r--autogpts/forge/forge/sdk/utils.py39
-rw-r--r--autogpts/forge/forge/sdk/workspace.py1
-rw-r--r--autogpts/forge/poetry.lock2347
-rw-r--r--autogpts/forge/pyproject.toml12
-rw-r--r--autogpts/forge/tutorials/003_crafting_agent_logic.md20
-rw-r--r--benchmark/.env.example2
-rw-r--r--benchmark/agbenchmark/README.md2
-rw-r--r--benchmark/agbenchmark/__main__.py469
-rw-r--r--benchmark/agbenchmark/agent_api_interface.py120
-rw-r--r--benchmark/agbenchmark/agent_interface.py38
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/__init__.py42
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/api/__init__.py4
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/api/agent_api.py1647
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/api_client.py838
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/api_response.py28
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/configuration.py447
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/docs/AgentApi.md615
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/exceptions.py154
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/models/__init__.py25
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/models/artifact.py72
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/models/artifacts.py77
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/models/pagination.py75
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/models/step.py146
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/models/step_all_of.py133
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/models/step_request_body.py77
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/models/step_result.py89
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/models/task.py99
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/models/task_all_of.py87
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/models/task_request_body.py77
-rw-r--r--benchmark/agbenchmark/agent_protocol_client/rest.py311
-rw-r--r--benchmark/agbenchmark/app.py575
-rw-r--r--benchmark/agbenchmark/challenges/__init__.py56
-rw-r--r--benchmark/agbenchmark/challenges/base.py107
-rw-r--r--benchmark/agbenchmark/challenges/builtin.py449
-rw-r--r--benchmark/agbenchmark/challenges/verticals/code/5_tic_tac_toe/custom_python/test.py2
-rw-r--r--benchmark/agbenchmark/challenges/verticals/code/5_tic_tac_toe/data.json2
-rw-r--r--benchmark/agbenchmark/challenges/verticals/scrape/4_revenue_retrieval_2/data.json30
-rw-r--r--benchmark/agbenchmark/challenges/verticals/synthesize/1_basic_content_gen/data.json4
-rw-r--r--benchmark/agbenchmark/challenges/webarena.py531
-rw-r--r--benchmark/agbenchmark/challenges/webarena_selection.json523
-rw-r--r--benchmark/agbenchmark/config.py127
-rw-r--r--benchmark/agbenchmark/conftest.py486
-rw-r--r--benchmark/agbenchmark/execute_sub_process.py79
-rw-r--r--benchmark/agbenchmark/generate_test.py233
-rw-r--r--benchmark/agbenchmark/main.py158
-rw-r--r--benchmark/agbenchmark/reports/ReportManager.py205
-rw-r--r--benchmark/agbenchmark/reports/agent_benchmark_config.py18
-rw-r--r--benchmark/agbenchmark/reports/processing/process_report.py32
-rw-r--r--benchmark/agbenchmark/reports/processing/report_types.py127
-rw-r--r--benchmark/agbenchmark/reports/processing/report_types_v2.py46
-rw-r--r--benchmark/agbenchmark/reports/reports.py241
-rw-r--r--benchmark/agbenchmark/schema.py172
-rw-r--r--benchmark/agbenchmark/utils/challenge.py236
-rw-r--r--benchmark/agbenchmark/utils/data_types.py233
-rw-r--r--benchmark/agbenchmark/utils/dependencies/graphs.py17
-rw-r--r--benchmark/agbenchmark/utils/get_data_from_helicone.py35
-rw-r--r--benchmark/agbenchmark/utils/logging.py74
-rw-r--r--benchmark/agbenchmark/utils/utils.py161
-rw-r--r--benchmark/notebooks/LLM Score Experimentation.ipynb10
-rw-r--r--benchmark/poetry.lock1885
-rw-r--r--benchmark/pyproject.toml11
-rwxr-xr-xbenchmark/reports/format.py139
-rw-r--r--benchmark/server.py121
-rw-r--r--cli.py70
-rw-r--r--docs/content/AutoGPT/configuration/options.md6
-rw-r--r--docs/content/AutoGPT/setup/docker.md7
-rw-r--r--docs/content/AutoGPT/usage.md2
-rw-r--r--docs/content/forge/get-started.md3
-rw-r--r--docs/mkdocs.yml2
-rw-r--r--docs/netlify.toml2
-rw-r--r--frontend/lib/views/chat/chat_input_field.dart5
202 files changed, 12694 insertions, 13826 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 110493c3f..d586fc2c4 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,5 +1,5 @@
-.github/workflows/ @Significant-Gravitas/maintainers
-autogpts/autogpt/ @Pwuts
-benchmark/ @Significant-Gravitas/benchmarkers
-forge/ @Swiftyos
-frontend/ @hunteraraujo
+.github/workflows/ @Significant-Gravitas/devops
+autogpts/autogpt/ @Significant-Gravitas/maintainers
+autogpts/forge/ @Significant-Gravitas/forge-maintainers
+benchmark/ @Significant-Gravitas/benchmark-maintainers
+frontend/ @Significant-Gravitas/frontend-maintainers
diff --git a/.github/labeler.yml b/.github/labeler.yml
new file mode 100644
index 000000000..140174388
--- /dev/null
+++ b/.github/labeler.yml
@@ -0,0 +1,23 @@
+AutoGPT Agent:
+- changed-files:
+ - any-glob-to-any-file: autogpts/autogpt/**
+
+Forge:
+- changed-files:
+ - any-glob-to-any-file: autogpts/forge/**
+
+Benchmark:
+- changed-files:
+ - any-glob-to-any-file: benchmark/**
+
+Frontend:
+- changed-files:
+ - any-glob-to-any-file: frontend/**
+
+Arena:
+- changed-files:
+ - any-glob-to-any-file: arena/**
+
+documentation:
+- changed-files:
+ - any-glob-to-any-file: docs/**
diff --git a/.github/workflows/arena-intake.yml b/.github/workflows/arena-intake.yml
new file mode 100644
index 000000000..a77540471
--- /dev/null
+++ b/.github/workflows/arena-intake.yml
@@ -0,0 +1,169 @@
+name: Arena intake
+
+on:
+ # We recommend `pull_request_target` so that github secrets are available.
+ # In `pull_request` we wouldn't be able to change labels of fork PRs
+ pull_request_target:
+ types: [ opened, synchronize ]
+ paths:
+ - 'arena/**'
+
+jobs:
+ check:
+ permissions:
+ pull-requests: write
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout PR
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+
+ - name: Check Arena entry
+ uses: actions/github-script@v7
+ with:
+ script: |
+ console.log('⚙️ Setting up...');
+
+ const fs = require('fs');
+ const path = require('path');
+
+ const pr = context.payload.pull_request;
+ const isFork = pr.head.repo.fork;
+
+ console.log('🔄️ Fetching PR diff metadata...');
+ const prFilesChanged = (await github.rest.pulls.listFiles({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: pr.number,
+ })).data;
+ console.debug(prFilesChanged);
+ const arenaFilesChanged = prFilesChanged.filter(
+ ({ filename: file }) => file.startsWith('arena/') && file.endsWith('.json')
+ );
+ const hasChangesInAutogptsFolder = prFilesChanged.some(
+ ({ filename }) => filename.startsWith('autogpts/')
+ );
+
+ console.log(`🗒️ ${arenaFilesChanged.length} arena entries affected`);
+ console.debug(arenaFilesChanged);
+ if (arenaFilesChanged.length === 0) {
+ // If no files in `arena/` are changed, this job does not need to run.
+ return;
+ }
+
+ let close = false;
+ let flagForManualCheck = false;
+ let issues = [];
+
+ if (isFork) {
+ if (arenaFilesChanged.length > 1) {
+ // Impacting multiple entries in `arena/` is not allowed
+ issues.push('This pull request impacts multiple arena entries');
+ }
+ if (hasChangesInAutogptsFolder) {
+ // PRs that include the custom agent are generally not allowed
+ issues.push(
+ 'This pull request includes changes in `autogpts/`.\n'
+ + 'Please make sure to only submit your arena entry (`arena/*.json`), '
+ + 'and not to accidentally include your custom agent itself.'
+ );
+ }
+ }
+
+ if (arenaFilesChanged.length === 1) {
+ const newArenaFile = arenaFilesChanged[0]
+ const newArenaFileName = path.basename(newArenaFile.filename)
+ console.log(`🗒️ Arena entry in PR: ${newArenaFile}`);
+
+ if (newArenaFile.status != 'added') {
+ flagForManualCheck = true;
+ }
+
+ if (pr.mergeable != false) {
+ const newArenaEntry = JSON.parse(fs.readFileSync(newArenaFile.filename));
+ const allArenaFiles = await (await glob.create('arena/*.json')).glob();
+ console.debug(newArenaEntry);
+
+ console.log(`➡️ Checking ${newArenaFileName} against existing entries...`);
+ for (const file of allArenaFiles) {
+ const existingEntryName = path.basename(file);
+
+ if (existingEntryName === newArenaFileName) {
+ continue;
+ }
+
+ console.debug(`Checking against ${existingEntryName}...`);
+
+ const arenaEntry = JSON.parse(fs.readFileSync(file));
+ if (arenaEntry.github_repo_url === newArenaEntry.github_repo_url) {
+ console.log(`⚠️ Duplicate detected: ${existingEntryName}`);
+ issues.push(
+ `The \`github_repo_url\` specified in __${newArenaFileName}__ `
+ + `already exists in __${existingEntryName}__. `
+ + `This PR will be closed as duplicate.`
+ )
+ close = true;
+ }
+ }
+ } else {
+ console.log('⚠️ PR has conflicts');
+ issues.push(
+ `__${newArenaFileName}__ conflicts with existing entry with the same name`
+ )
+ close = true;
+ }
+ } // end if (arenaFilesChanged.length === 1)
+
+ console.log('🏁 Finished checking against existing entries');
+
+ if (issues.length == 0) {
+ console.log('✅ No issues detected');
+ if (flagForManualCheck) {
+ console.log('🤔 Requesting review from maintainers...');
+ await github.rest.pulls.requestReviewers({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: pr.number,
+ reviewers: ['Pwuts'],
+ // team_reviewers: ['maintainers'], // doesn't work: https://stackoverflow.com/a/64977184/4751645
+ });
+ } else {
+ console.log('➡️ Approving PR...');
+ await github.rest.pulls.createReview({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: pr.number,
+ event: 'APPROVE',
+ });
+ }
+ } else {
+ console.log(`⚠️ ${issues.length} issues detected`);
+
+ console.log('➡️ Posting comment indicating issues...');
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: pr.number,
+ body: `Our automation found one or more issues with this submission:\n`
+ + issues.map(i => `- ${i.replace('\n', '\n ')}`).join('\n'),
+ });
+
+ console.log("➡️ Applying label 'invalid'...");
+ await github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: pr.number,
+ labels: ['invalid'],
+ });
+
+ if (close) {
+ console.log('➡️ Auto-closing PR...');
+ await github.rest.pulls.update({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: pr.number,
+ state: 'closed',
+ });
+ }
+ }
diff --git a/.github/workflows/autogpt-ci.yml b/.github/workflows/autogpt-ci.yml
index 2ce756a7a..bc3858e88 100644
--- a/.github/workflows/autogpt-ci.yml
+++ b/.github/workflows/autogpt-ci.yml
@@ -20,6 +20,7 @@ concurrency:
defaults:
run:
+ shell: bash
working-directory: autogpts/autogpt
jobs:
@@ -30,12 +31,12 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python ${{ env.min-python-version }}
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: ${{ env.min-python-version }}
@@ -44,7 +45,7 @@ jobs:
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
- name: Set up Python dependency cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.cache/pypoetry
key: ${{ runner.os }}-poetry-${{ hashFiles('autogpts/autogpt/pyproject.toml') }}-${{ steps.get_date.outputs.date }}
@@ -77,24 +78,43 @@ jobs:
test:
permissions:
contents: read
- runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
+ fail-fast: false
matrix:
python-version: ["3.10"]
-
- services:
- minio:
- image: minio/minio:edge-cicd
- ports:
- - 9000:9000
- options: >
- --health-interval=10s --health-timeout=5s --health-retries=3
- --health-cmd="curl -f http://localhost:9000/minio/health/live"
+ platform-os: [ubuntu, macos, macos-arm64, windows]
+ runs-on: ${{ matrix.platform-os != 'macos-arm64' && format('{0}-latest', matrix.platform-os) || 'macos-14' }}
steps:
+ # Quite slow on macOS (2~4 minutes to set up Docker)
+ # - name: Set up Docker (macOS)
+ # if: runner.os == 'macOS'
+ # uses: crazy-max/ghaction-setup-docker@v3
+
+ - name: Start MinIO service (Linux)
+ if: runner.os == 'Linux'
+ working-directory: '.'
+ run: |
+ docker pull minio/minio:edge-cicd
+ docker run -d -p 9000:9000 minio/minio:edge-cicd
+
+ - name: Start MinIO service (macOS)
+ if: runner.os == 'macOS'
+ working-directory: ${{ runner.temp }}
+ run: |
+ brew install minio/stable/minio
+ mkdir data
+ minio server ./data &
+
+ # No MinIO on Windows:
+ # - Windows doesn't support running Linux Docker containers
+ # - It doesn't seem possible to start background processes on Windows. They are
+ # killed after the step returns.
+ # See: https://github.com/actions/runner/issues/598#issuecomment-2011890429
+
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
@@ -136,7 +156,7 @@ jobs:
fi
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
@@ -145,15 +165,34 @@ jobs:
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
- name: Set up Python dependency cache
- uses: actions/cache@v3
+ # On Windows, unpacking cached dependencies takes longer than just installing them
+ if: runner.os != 'Windows'
+ uses: actions/cache@v4
with:
- path: ~/.cache/pypoetry
- key: ${{ runner.os }}-poetry-${{ hashFiles('autogpts/autogpt/pyproject.toml') }}-${{ steps.get_date.outputs.date }}
+ path: ${{ runner.os == 'macOS' && '~/Library/Caches/pypoetry' || '~/.cache/pypoetry' }}
+ key: poetry-${{ runner.os }}-${{ hashFiles('autogpts/autogpt/poetry.lock') }}
- - name: Install Python dependencies
+ - name: Install Poetry (Unix)
+ if: runner.os != 'Windows'
run: |
curl -sSL https://install.python-poetry.org | python3 -
- poetry install
+
+ if [ "${{ runner.os }}" = "macOS" ]; then
+ PATH="$HOME/.local/bin:$PATH"
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
+ fi
+
+ - name: Install Poetry (Windows)
+ if: runner.os == 'Windows'
+ shell: pwsh
+ run: |
+ (Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | python -
+
+ $env:PATH += ";$env:APPDATA\Python\Scripts"
+ echo "$env:APPDATA\Python\Scripts" >> $env:GITHUB_PATH
+
+ - name: Install Python dependencies
+ run: poetry install
- name: Run pytest with coverage
run: |
@@ -165,12 +204,15 @@ jobs:
CI: true
PLAIN_OUTPUT: True
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- S3_ENDPOINT_URL: http://localhost:9000
+ S3_ENDPOINT_URL: ${{ runner.os != 'Windows' && 'http://127.0.0.1:9000' || '' }}
AWS_ACCESS_KEY_ID: minioadmin
AWS_SECRET_ACCESS_KEY: minioadmin
- name: Upload coverage reports to Codecov
- uses: codecov/codecov-action@v3
+ uses: codecov/codecov-action@v4
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ flags: autogpt-agent,${{ runner.os }}
- id: setup_git_auth
name: Set up git token authentication
@@ -178,7 +220,11 @@ jobs:
if: success() || failure()
run: |
config_key="http.${{ github.server_url }}/.extraheader"
- base64_pat=$(echo -n "pat:${{ secrets.PAT_REVIEW }}" | base64 -w0)
+ if [ "${{ runner.os }}" = 'macOS' ]; then
+ base64_pat=$(echo -n "pat:${{ secrets.PAT_REVIEW }}" | base64)
+ else
+ base64_pat=$(echo -n "pat:${{ secrets.PAT_REVIEW }}" | base64 -w0)
+ fi
git config "$config_key" \
"Authorization: Basic $base64_pat"
@@ -239,12 +285,12 @@ jobs:
echo "Adding label and comment..."
echo $TOKEN | gh auth login --with-token
gh issue edit $PR_NUMBER --add-label "behaviour change"
- gh issue comment $PR_NUMBER --body "You changed AutoGPT's behaviour. The cassettes have been updated and will be merged to the submodule when this Pull Request gets merged."
+ gh issue comment $PR_NUMBER --body "You changed AutoGPT's behaviour on ${{ runner.os }}. The cassettes have been updated and will be merged to the submodule when this Pull Request gets merged."
fi
- name: Upload logs to artifact
if: always()
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: test-logs
path: autogpts/autogpt/logs/
diff --git a/.github/workflows/autogpt-docker-cache-clean.yml b/.github/workflows/autogpt-docker-cache-clean.yml
index 780caf44f..22c940128 100644
--- a/.github/workflows/autogpt-docker-cache-clean.yml
+++ b/.github/workflows/autogpt-docker-cache-clean.yml
@@ -16,14 +16,14 @@ jobs:
build-type: [release, dev]
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v2
+ uses: docker/setup-buildx-action@v3
- id: build
name: Build image
- uses: docker/build-push-action@v3
+ uses: docker/build-push-action@v5
with:
context: autogpts/autogpt
build-args: BUILD_TYPE=${{ matrix.build-type }}
diff --git a/.github/workflows/autogpt-docker-ci.yml b/.github/workflows/autogpt-docker-ci.yml
index dc555c381..4ef63547e 100644
--- a/.github/workflows/autogpt-docker-ci.yml
+++ b/.github/workflows/autogpt-docker-ci.yml
@@ -24,7 +24,7 @@ defaults:
env:
IMAGE_NAME: auto-gpt
- DEPLOY_IMAGE_NAME: ${{ secrets.DOCKER_USER }}/auto-gpt
+ DEPLOY_IMAGE_NAME: ${{ secrets.DOCKER_USER && format('{0}/', secrets.DOCKER_USER) || '' }}auto-gpt
DEV_IMAGE_TAG: latest-dev
jobs:
@@ -35,10 +35,10 @@ jobs:
build-type: [release, dev]
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v2
+ uses: docker/setup-buildx-action@v3
- if: runner.debug
run: |
@@ -47,11 +47,12 @@ jobs:
- id: build
name: Build image
- uses: docker/build-push-action@v3
+ uses: docker/build-push-action@v5
with:
context: autogpts/autogpt
build-args: BUILD_TYPE=${{ matrix.build-type }}
tags: ${{ env.IMAGE_NAME }}
+ labels: GIT_REVISION=${{ github.sha }}
load: true # save to docker images
# cache layers in GitHub Actions cache to speed up builds
cache-from: type=gha,scope=autogpt-docker-${{ matrix.build-type }}
@@ -100,28 +101,30 @@ jobs:
steps:
- name: Check out repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
submodules: true
- - name: Log in to Docker hub
- uses: docker/login-action@v2
+ - if: github.event_name == 'push'
+ name: Log in to Docker hub
+ uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v2
+ uses: docker/setup-buildx-action@v3
- id: build
name: Build image
- uses: docker/build-push-action@v3
+ uses: docker/build-push-action@v5
with:
context: autogpts/autogpt
build-args: BUILD_TYPE=dev # include pytest
tags: >
${{ env.IMAGE_NAME }},
${{ env.DEPLOY_IMAGE_NAME }}:${{ env.DEV_IMAGE_TAG }}
+ labels: GIT_REVISION=${{ github.sha }}
load: true # save to docker images
# cache layers in GitHub Actions cache to speed up builds
cache-from: type=gha,scope=autogpt-docker-dev
diff --git a/.github/workflows/autogpt-docker-release.yml b/.github/workflows/autogpt-docker-release.yml
index 4213c78b5..f45a63a2a 100644
--- a/.github/workflows/autogpt-docker-release.yml
+++ b/.github/workflows/autogpt-docker-release.yml
@@ -24,16 +24,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Log in to Docker hub
- uses: docker/login-action@v2
+ uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v2
+ uses: docker/setup-buildx-action@v3
# slashes are not allowed in image tags, but can appear in git branch or tag names
- id: sanitize_tag
@@ -46,7 +46,7 @@ jobs:
- id: build
name: Build image
- uses: docker/build-push-action@v3
+ uses: docker/build-push-action@v5
with:
context: autogpts/autogpt
build-args: BUILD_TYPE=release
@@ -56,6 +56,7 @@ jobs:
${{ env.IMAGE_NAME }},
${{ env.DEPLOY_IMAGE_NAME }}:latest,
${{ env.DEPLOY_IMAGE_NAME }}:${{ steps.sanitize_tag.outputs.tag }}
+ labels: GIT_REVISION=${{ github.sha }}
# cache layers in GitHub Actions cache to speed up builds
cache-from: ${{ !inputs.no_cache && 'type=gha' || '' }},scope=autogpt-docker-release
diff --git a/.github/workflows/autogpts-benchmark.yml b/.github/workflows/autogpts-benchmark.yml
new file mode 100644
index 000000000..fb1cb6f08
--- /dev/null
+++ b/.github/workflows/autogpts-benchmark.yml
@@ -0,0 +1,97 @@
+name: AutoGPTs Nightly Benchmark
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: '0 2 * * *'
+
+jobs:
+ benchmark:
+ permissions:
+ contents: write
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ agent-name: [ autogpt ]
+ fail-fast: false
+ timeout-minutes: 120
+ env:
+ min-python-version: '3.10'
+ REPORTS_BRANCH: data/benchmark-reports
+ REPORTS_FOLDER: ${{ format('benchmark/reports/{0}', matrix.agent-name) }}
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ submodules: true
+
+ - name: Set up Python ${{ env.min-python-version }}
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{ env.min-python-version }}
+
+ - name: Install Poetry
+ run: curl -sSL https://install.python-poetry.org | python -
+
+ - name: Prepare reports folder
+ run: mkdir -p ${{ env.REPORTS_FOLDER }}
+
+ - run: poetry -C benchmark install
+
+ - name: Benchmark ${{ matrix.agent-name }}
+ run: |
+ ./run agent start ${{ matrix.agent-name }}
+ cd autogpts/${{ matrix.agent-name }}
+
+ set +e # Do not quit on non-zero exit codes
+ poetry run agbenchmark run -N 3 \
+ --test=ReadFile \
+ --test=BasicRetrieval --test=RevenueRetrieval2 \
+ --test=CombineCsv --test=LabelCsv --test=AnswerQuestionCombineCsv \
+ --test=UrlShortener --test=TicTacToe --test=Battleship \
+ --test=WebArenaTask_0 --test=WebArenaTask_21 --test=WebArenaTask_124 \
+ --test=WebArenaTask_134 --test=WebArenaTask_163
+
+ # Convert exit code 1 (some challenges failed) to exit code 0
+ if [ $? -eq 0 ] || [ $? -eq 1 ]; then
+ exit 0
+ else
+ exit $?
+ fi
+ env:
+ AGENT_NAME: ${{ matrix.agent-name }}
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
+ REQUESTS_CA_BUNDLE: /etc/ssl/certs/ca-certificates.crt
+ REPORTS_FOLDER: ${{ format('../../{0}', env.REPORTS_FOLDER) }} # account for changed workdir
+
+ TELEMETRY_ENVIRONMENT: autogpt-benchmark-ci
+ TELEMETRY_OPT_IN: ${{ github.ref_name == 'master' }}
+
+ - name: Push reports to data branch
+ run: |
+ # BODGE: Remove success_rate.json and regression_tests.json to avoid conflicts on checkout
+ rm ${{ env.REPORTS_FOLDER }}/*.json
+
+ # Find folder with newest (untracked) report in it
+ report_subfolder=$(find ${{ env.REPORTS_FOLDER }} -type f -name 'report.json' \
+ | xargs -I {} dirname {} \
+ | xargs -I {} git ls-files --others --exclude-standard {} \
+ | xargs -I {} dirname {} \
+ | sort -u)
+ json_report_file="$report_subfolder/report.json"
+
+ # Convert JSON report to Markdown
+ markdown_report_file="$report_subfolder/report.md"
+ poetry -C benchmark run benchmark/reports/format.py "$json_report_file" > "$markdown_report_file"
+ cat "$markdown_report_file" >> $GITHUB_STEP_SUMMARY
+
+ git config --global user.name 'GitHub Actions'
+ git config --global user.email 'github-actions@agpt.co'
+ git fetch origin ${{ env.REPORTS_BRANCH }}:${{ env.REPORTS_BRANCH }} \
+ && git checkout ${{ env.REPORTS_BRANCH }} \
+ || git checkout --orphan ${{ env.REPORTS_BRANCH }}
+ git reset --hard
+ git add ${{ env.REPORTS_FOLDER }}
+ git commit -m "Benchmark report for ${{ matrix.agent-name }} @ $(date +'%Y-%m-%d')" \
+ && git push origin ${{ env.REPORTS_BRANCH }}
diff --git a/.github/workflows/autogpts-ci.yml b/.github/workflows/autogpts-ci.yml
index 0385470ac..19f8c5ab2 100644
--- a/.github/workflows/autogpts-ci.yml
+++ b/.github/workflows/autogpts-ci.yml
@@ -37,13 +37,13 @@ jobs:
min-python-version: '3.10'
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Set up Python ${{ env.min-python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v5
with:
python-version: ${{ env.min-python-version }}
@@ -56,13 +56,14 @@ jobs:
run: |
./run agent start ${{ matrix.agent-name }}
cd autogpts/${{ matrix.agent-name }}
- poetry run agbenchmark --mock
+ poetry run agbenchmark --mock --test=BasicRetrieval --test=Battleship --test=WebArenaTask_0
poetry run agbenchmark --test=WriteFile
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
AGENT_NAME: ${{ matrix.agent-name }}
- HELICONE_API_KEY: ${{ secrets.HELICONE_API_KEY }}
REQUESTS_CA_BUNDLE: /etc/ssl/certs/ca-certificates.crt
HELICONE_CACHE_ENABLED: false
HELICONE_PROPERTY_AGENT: ${{ matrix.agent-name }}
- REPORT_LOCATION: ${{ format('../../reports/{0}', matrix.agent-name) }}
+ REPORTS_FOLDER: ${{ format('../../reports/{0}', matrix.agent-name) }}
+ TELEMETRY_ENVIRONMENT: autogpt-ci
+ TELEMETRY_OPT_IN: ${{ github.ref_name == 'master' }}
diff --git a/.github/workflows/benchmark-ci.yml b/.github/workflows/benchmark-ci.yml
index 5f95dd025..88c5750ac 100644
--- a/.github/workflows/benchmark-ci.yml
+++ b/.github/workflows/benchmark-ci.yml
@@ -23,12 +23,12 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python ${{ env.min-python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v5
with:
python-version: ${{ env.min-python-version }}
@@ -78,13 +78,13 @@ jobs:
timeout-minutes: 20
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Set up Python ${{ env.min-python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v5
with:
python-version: ${{ env.min-python-version }}
@@ -96,11 +96,10 @@ jobs:
- name: Run regression tests
run: |
./run agent start ${{ matrix.agent-name }}
- sleep 10
cd autogpts/${{ matrix.agent-name }}
+
set +e # Ignore non-zero exit codes and continue execution
echo "Running the following command: poetry run agbenchmark --maintain --mock"
-
poetry run agbenchmark --maintain --mock
EXIT_CODE=$?
set -e # Stop ignoring non-zero exit codes
@@ -127,7 +126,7 @@ jobs:
poetry run agbenchmark --mock
poetry run pytest -vv -s tests
-
+
CHANGED=$(git diff --name-only | grep -E '(agbenchmark/challenges)|(../frontend/assets)') || echo "No diffs"
if [ ! -z "$CHANGED" ]; then
echo "There are unstaged changes please run agbenchmark and commit those changes since they are needed."
@@ -138,3 +137,5 @@ jobs:
fi
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
+ TELEMETRY_ENVIRONMENT: autogpt-benchmark-ci
+ TELEMETRY_OPT_IN: ${{ github.ref_name == 'master' }}
diff --git a/.github/workflows/benchmark_publish_package.yml b/.github/workflows/benchmark_publish_package.yml
index de0ca66fe..3332e6501 100644
--- a/.github/workflows/benchmark_publish_package.yml
+++ b/.github/workflows/benchmark_publish_package.yml
@@ -10,13 +10,13 @@ jobs:
contents: write
steps:
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Set up Python
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v5
with:
python-version: 3.8
diff --git a/.github/workflows/build-frontend.yml b/.github/workflows/build-frontend.yml
deleted file mode 100644
index dedf67f3c..000000000
--- a/.github/workflows/build-frontend.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-name: Build and Commit Frontend
-
-on:
- push:
- branches:
- - master
- - development
- - 'ci-test*' # This will match any branch that starts with "ci-test"
- paths:
- - 'frontend/**'
-
-jobs:
- build:
- permissions:
- contents: write
- runs-on: ubuntu-latest
- steps:
- - name: Checkout Repo
- uses: actions/checkout@v2
- - name: Setup Flutter
- uses: subosito/flutter-action@v1
- with:
- flutter-version: '3.13.2'
- - name: Build Flutter Web
- run: |
- cd frontend
- flutter build web --base-href /app/
- - name: Set branch name
- id: vars
- run: echo "::set-output name=branch::frontend_build_${GITHUB_SHA}"
- - name: Commit and Push
- run: |
- git config --local user.email "action@github.com"
- git config --local user.name "GitHub Action"
- git add frontend/build/web
- git commit -m "Update frontend build" -a
- git checkout -b ${{ steps.vars.outputs.branch }}
- echo "Commit hash: ${GITHUB_SHA}"
- git push origin ${{ steps.vars.outputs.branch }}
- # - name: Create Pull Request
- # uses: peter-evans/create-pull-request@v3
- # with:
- # title: "Update frontend build"
- # body: "This PR updates the frontend build."
- # branch: ${{ steps.vars.outputs.branch }}
- # base: "master"
diff --git a/.github/workflows/close-stale-issues.yml b/.github/workflows/close-stale-issues.yml
index f8d66dcea..22276417f 100644
--- a/.github/workflows/close-stale-issues.yml
+++ b/.github/workflows/close-stale-issues.yml
@@ -11,7 +11,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- - uses: actions/stale@v8
+ - uses: actions/stale@v9
with:
# operations-per-run: 5000
stale-issue-message: >
diff --git a/.github/workflows/frontend-ci.yml b/.github/workflows/frontend-ci.yml
new file mode 100644
index 000000000..4f4d71871
--- /dev/null
+++ b/.github/workflows/frontend-ci.yml
@@ -0,0 +1,60 @@
+name: Frontend CI/CD
+
+on:
+ push:
+ branches:
+ - master
+ - development
+ - 'ci-test*' # This will match any branch that starts with "ci-test"
+ paths:
+ - 'frontend/**'
+ - '.github/workflows/frontend-ci.yml'
+ pull_request:
+ paths:
+ - 'frontend/**'
+ - '.github/workflows/frontend-ci.yml'
+
+jobs:
+ build:
+ permissions:
+ contents: write
+ pull-requests: write
+ runs-on: ubuntu-latest
+ env:
+ BUILD_BRANCH: ${{ format('frontend-build/{0}', github.ref_name) }}
+
+ steps:
+ - name: Checkout Repo
+ uses: actions/checkout@v4
+
+ - name: Setup Flutter
+ uses: subosito/flutter-action@v2
+ with:
+ flutter-version: '3.13.2'
+
+ - name: Build Flutter to Web
+ run: |
+ cd frontend
+ flutter build web --base-href /app/
+
+ # - name: Commit and Push to ${{ env.BUILD_BRANCH }}
+ # if: github.event_name == 'push'
+ # run: |
+ # git config --local user.email "action@github.com"
+ # git config --local user.name "GitHub Action"
+ # git add frontend/build/web
+ # git checkout -B ${{ env.BUILD_BRANCH }}
+ # git commit -m "Update frontend build to ${GITHUB_SHA:0:7}" -a
+ # git push -f origin ${{ env.BUILD_BRANCH }}
+
+ - name: Create PR ${{ env.BUILD_BRANCH }} -> ${{ github.ref_name }}
+ if: github.event_name == 'push'
+ uses: peter-evans/create-pull-request@v6
+ with:
+ add-paths: frontend/build/web
+ base: ${{ github.ref_name }}
+ branch: ${{ env.BUILD_BRANCH }}
+ delete-branch: true
+ title: "Update frontend build in `${{ github.ref_name }}`"
+ body: "This PR updates the frontend build based on commit ${{ github.sha }}."
+ commit-message: "Update frontend build based on commit ${{ github.sha }}"
diff --git a/.github/workflows/hackathon.yml b/.github/workflows/hackathon.yml
index a8b592eb9..94b2c752f 100644
--- a/.github/workflows/hackathon.yml
+++ b/.github/workflows/hackathon.yml
@@ -88,13 +88,13 @@ jobs:
run: docker ps
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Set up Python ${{ env.min-python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v5
with:
python-version: ${{ env.min-python-version }}
@@ -107,7 +107,7 @@ jobs:
curl -sSL https://install.python-poetry.org | python -
- name: Install Node.js
- uses: actions/setup-node@v1
+ uses: actions/setup-node@v4
with:
node-version: v18.15
@@ -121,7 +121,7 @@ jobs:
./run agent start $AGENT_NAME
cd ../benchmark
poetry install
- poetry run agbenchmark --no_dep
+ poetry run agbenchmark --no-dep
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
SERP_API_KEY: ${{ secrets.SERP_API_KEY }}
diff --git a/.github/workflows/pr-label.yml b/.github/workflows/pr-label.yml
index 512daf116..415637702 100644
--- a/.github/workflows/pr-label.yml
+++ b/.github/workflows/pr-label.yml
@@ -52,6 +52,15 @@ jobs:
l_label: 'size/l'
l_max_size: 500
xl_label: 'size/xl'
- message_if_xl: >
- This PR exceeds the recommended size of 500 lines.
- Please make sure you are NOT addressing multiple issues with one PR.
+ message_if_xl:
+
+ scope:
+ if: ${{ github.event_name == 'pull_request_target' }}
+ permissions:
+ contents: read
+ pull-requests: write
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/labeler@v5
+ with:
+ sync-labels: true
diff --git a/QUICKSTART.md b/QUICKSTART.md
index 5eab892e3..885533883 100644
--- a/QUICKSTART.md
+++ b/QUICKSTART.md
@@ -77,37 +77,47 @@ After executing the above commands, running `./run setup` should work successful
#### Store Project Files within the WSL File System
If you continue to experience issues, consider storing your project files within the WSL file system instead of the Windows file system. This method avoids issues related to path translations and permissions and provides a more consistent development environment.
-
- You can keep running the command to get feedback on where you are up to with your setup.
- When setup has been completed, the command will return an output like this:
- ![Setup Complete](docs/content/imgs/quickstart/006_setup_complete.png)
+You can keep running the command to get feedback on where you are up to with your setup.
+When setup has been completed, the command will return an output like this:
+
+![Setup Complete](docs/content/imgs/quickstart/006_setup_complete.png)
## Creating Your Agent
- Now setup has been completed its time to create your agent template.
- Do so by running the `./run agent create YOUR_AGENT_NAME` replacing YOUR_AGENT_NAME with a name of your choice. Examples of valid names: swiftyosgpt or SwiftyosAgent or swiftyos_agent
-
- ![Create an Agent](docs/content/imgs/quickstart/007_create_agent.png)
-
- Upon creating your agent its time to officially enter the Arena!
- Do so by running `./run arena enter YOUR_AGENT_NAME`
-
- ![Enter the Arena](docs/content/imgs/quickstart/008_enter_arena.png)
-
- > Note: for advanced users, create a new branch and create a file called YOUR_AGENT_NAME.json in the arena directory. Then commit this and create a PR to merge into the main repo. Only single file entries will be permitted. The json file needs the following format.
- ```json
- {
- "github_repo_url": "https://github.com/Swiftyos/YourAgentName",
- "timestamp": "2023-09-18T10:03:38.051498",
- "commit_hash_to_benchmark": "ac36f7bfc7f23ad8800339fa55943c1405d80d5e",
- "branch_to_benchmark": "master"
- }
- ```
- - github_repo_url: the url to your fork
- - timestamp: timestamp of the last update of this file
- - commit_hash_to_benchmark: the commit hash of your entry. You update each time you have an something ready to be officially entered into the hackathon
- - branch_to_benchmark: the branch you are using to develop your agent on, default is master.
+After completing the setup, the next step is to create your agent template.
+Execute the command `./run agent create YOUR_AGENT_NAME`, where `YOUR_AGENT_NAME` should be replaced with a name of your choosing.
+
+Tips for naming your agent:
+* Give it its own unique name, or name it after yourself
+* Include an important aspect of your agent in the name, such as its purpose
+
+Examples: `SwiftyosAssistant`, `PwutsPRAgent`, `Narvis`, `evo.ninja`
+
+![Create an Agent](docs/content/imgs/quickstart/007_create_agent.png)
+
+### Optional: Entering the Arena
+
+Entering the Arena is an optional step intended for those who wish to actively participate in the agent leaderboard. If you decide to participate, you can enter the Arena by running `./run arena enter YOUR_AGENT_NAME`. This step is not mandatory for the development or testing of your agent.
+
+Entries with names like `agent`, `ExampleAgent`, `test_agent` or `MyExampleGPT` will NOT be merged. We also don't accept copycat entries that use the name of other projects, like `AutoGPT` or `evo.ninja`.
+
+![Enter the Arena](docs/content/imgs/quickstart/008_enter_arena.png)
+
+> **Note**
+> For advanced users, create a new branch and create a file called YOUR_AGENT_NAME.json in the arena directory. Then commit this and create a PR to merge into the main repo. Only single file entries will be permitted. The json file needs the following format:
+> ```json
+> {
+> "github_repo_url": "https://github.com/Swiftyos/YourAgentName",
+> "timestamp": "2023-09-18T10:03:38.051498",
+> "commit_hash_to_benchmark": "ac36f7bfc7f23ad8800339fa55943c1405d80d5e",
+> "branch_to_benchmark": "master"
+> }
+> ```
+> - `github_repo_url`: the url to your fork
+> - `timestamp`: timestamp of the last update of this file
+> - `commit_hash_to_benchmark`: the commit hash of your entry. You update each time you have an something ready to be officially entered into the hackathon
+> - `branch_to_benchmark`: the branch you are using to develop your agent on, default is master.
## Running your Agent
diff --git a/README.md b/README.md
index a139cd2e8..b3716cf54 100644
--- a/README.md
+++ b/README.md
@@ -102,7 +102,11 @@ To maintain a uniform standard and ensure seamless compatibility with many curre
---
<p align="center">
- <a href="https://star-history.com/#Significant-Gravitas/AutoGPT&Date">
- <img src="https://api.star-history.com/svg?repos=Significant-Gravitas/AutoGPT&type=Date" alt="Star History Chart">
- </a>
+<a href="https://star-history.com/#Significant-Gravitas/AutoGPT">
+ <picture>
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=Significant-Gravitas/AutoGPT&type=Date&theme=dark" />
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=Significant-Gravitas/AutoGPT&type=Date" />
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=Significant-Gravitas/AutoGPT&type=Date" />
+ </picture>
+</a>
</p>
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..4d51706d4
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,66 @@
+# Security Policy
+
+ - [**Using AutoGPT Securely**](#using-AutoGPT-securely)
+ - [Restrict Workspace](#restrict-workspace)
+ - [Untrusted inputs](#untrusted-inputs)
+ - [Data privacy](#data-privacy)
+ - [Untrusted environments or networks](#untrusted-environments-or-networks)
+ - [Multi-Tenant environments](#multi-tenant-environments)
+ - [**Reporting a Vulnerability**](#reporting-a-vulnerability)
+
+## Using AutoGPT Securely
+
+### Restrict Workspace
+
+Since agents can read and write files, it is important to keep them restricted to a specific workspace. This happens by default *unless* RESTRICT_TO_WORKSPACE is set to False.
+
+Disabling RESTRICT_TO_WORKSPACE can increase security risks. However, if you still need to disable it, consider running AutoGPT inside a [sandbox](https://developers.google.com/code-sandboxing), to mitigate some of these risks.
+
+### Untrusted inputs
+
+When handling untrusted inputs, it's crucial to isolate the execution and carefully pre-process inputs to mitigate script injection risks.
+
+For maximum security when handling untrusted inputs, you may need to employ the following:
+
+* Sandboxing: Isolate the process.
+* Updates: Keep your libraries (including AutoGPT) updated with the latest security patches.
+* Input Sanitation: Before feeding data to the model, sanitize inputs rigorously. This involves techniques such as:
+ * Validation: Enforce strict rules on allowed characters and data types.
+ * Filtering: Remove potentially malicious scripts or code fragments.
+ * Encoding: Convert special characters into safe representations.
+ * Verification: Run tooling that identifies potential script injections (e.g. [models that detect prompt injection attempts](https://python.langchain.com/docs/guides/safety/hugging_face_prompt_injection)).
+
+### Data privacy
+
+To protect sensitive data from potential leaks or unauthorized access, it is crucial to sandbox the agent execution. This means running it in a secure, isolated environment, which helps mitigate many attack vectors.
+
+### Untrusted environments or networks
+
+Since AutoGPT performs network calls to the OpenAI API, it is important to always run it with trusted environments and networks. Running it on untrusted environments can expose your API KEY to attackers.
+Additionally, running it on an untrusted network can expose your data to potential network attacks.
+
+However, even when running on trusted networks, it is important to always encrypt sensitive data while sending it over the network.
+
+### Multi-Tenant environments
+
+If you intend to run multiple AutoGPT brains in parallel, it is your responsibility to ensure the models do not interact or access each other's data.
+
+The primary areas of concern are tenant isolation, resource allocation, model sharing and hardware attacks.
+
+- Tenant Isolation: you must make sure that the tenants run separately to prevent unwanted access to the data from other tenants. Keeping model network traffic separate is also important because you not only prevent unauthorized access to data, but also prevent malicious users or tenants sending prompts to execute under another tenant’s identity.
+
+- Resource Allocation: a denial of service caused by one tenant can affect the overall system health. Implement safeguards like rate limits, access controls, and health monitoring.
+
+- Data Sharing: in a multi-tenant design with data sharing, ensure tenants and users understand the security risks and sandbox agent execution to mitigate risks.
+
+- Hardware Attacks: the hardware (GPUs or TPUs) can also be attacked. [Research](https://scholar.google.com/scholar?q=gpu+side+channel) has shown that side channel attacks on GPUs are possible, which can make data leak from other brains or processes running on the same system at the same time.
+
+## Reporting a Vulnerability
+
+Beware that none of the topics under [Using AutoGPT Securely](#using-AutoGPT-securely) are considered vulnerabilities on AutoGPT.
+
+However, If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
+
+Please disclose it as a private [security advisory](https://github.com/Significant-Gravitas/AutoGPT/security/advisories/new).
+
+A team of volunteers on a reasonable-effort basis maintains this project. As such, please give us at least 90 days to work on a fix before public exposure.
diff --git a/autogpts/autogpt/.env.template b/autogpts/autogpt/.env.template
index 886cfe4db..a79f97b68 100644
--- a/autogpts/autogpt/.env.template
+++ b/autogpts/autogpt/.env.template
@@ -5,6 +5,10 @@
## OPENAI_API_KEY - OpenAI API Key (Example: my-openai-api-key)
OPENAI_API_KEY=your-openai-api-key
+## TELEMETRY_OPT_IN - Share telemetry on errors and other issues with the AutoGPT team, e.g. through Sentry.
+## This helps us to spot and solve problems earlier & faster. (Default: DISABLED)
+# TELEMETRY_OPT_IN=true
+
## EXECUTE_LOCAL_COMMANDS - Allow local command execution (Default: False)
# EXECUTE_LOCAL_COMMANDS=False
@@ -16,12 +20,12 @@ OPENAI_API_KEY=your-openai-api-key
## DISABLED_COMMAND_CATEGORIES - The list of categories of commands that are disabled (Default: None)
# DISABLED_COMMAND_CATEGORIES=
-## WORKSPACE_BACKEND - Choose a storage backend for workspace contents
+## FILE_STORAGE_BACKEND - Choose a storage backend for contents
## Options: local, gcs, s3
-# WORKSPACE_BACKEND=local
+# FILE_STORAGE_BACKEND=local
-## WORKSPACE_STORAGE_BUCKET - GCS/S3 Bucket to store workspace contents in
-# WORKSPACE_STORAGE_BUCKET=autogpt
+## STORAGE_BUCKET - GCS/S3 Bucket to store contents in
+# STORAGE_BUCKET=autogpt
## GCS Credentials
# see https://cloud.google.com/storage/docs/authentication#libauth
@@ -76,22 +80,24 @@ OPENAI_API_KEY=your-openai-api-key
## USE_AZURE - Use Azure OpenAI or not (Default: False)
# USE_AZURE=False
-## AZURE_CONFIG_FILE - The path to the azure.yaml file, relative to the AutoGPT root directory. (Default: azure.yaml)
+## AZURE_CONFIG_FILE - The path to the azure.yaml file, relative to the folder containing this file. (Default: azure.yaml)
# AZURE_CONFIG_FILE=azure.yaml
+# AZURE_OPENAI_AD_TOKEN=
+# AZURE_OPENAI_ENDPOINT=
################################################################################
### LLM MODELS
################################################################################
-## SMART_LLM - Smart language model (Default: gpt-4-0314)
-# SMART_LLM=gpt-4-0314
+## SMART_LLM - Smart language model (Default: gpt-4-turbo-preview)
+# SMART_LLM=gpt-4-turbo-preview
-## FAST_LLM - Fast language model (Default: gpt-3.5-turbo-16k)
-# FAST_LLM=gpt-3.5-turbo-16k
+## FAST_LLM - Fast language model (Default: gpt-3.5-turbo-0125)
+# FAST_LLM=gpt-3.5-turbo-0125
## EMBEDDING_MODEL - Model to use for creating embeddings
-# EMBEDDING_MODEL=text-embedding-ada-002
+# EMBEDDING_MODEL=text-embedding-3-small
################################################################################
### SHELL EXECUTION
@@ -220,3 +226,14 @@ OPENAI_API_KEY=your-openai-api-key
## PLAIN_OUTPUT - Disables animated typing and the spinner in the console output. (Default: False)
# PLAIN_OUTPUT=False
+
+
+################################################################################
+### Agent Protocol Server Settings
+################################################################################
+## AP_SERVER_PORT - Specifies what port the agent protocol server will listen on. (Default: 8000)
+## AP_SERVER_DB_URL - Specifies what connection url the agent protocol database will connect to (Default: Internal SQLite)
+## AP_SERVER_CORS_ALLOWED_ORIGINS - Comma separated list of allowed origins for CORS. (Default: http://localhost:{AP_SERVER_PORT})
+# AP_SERVER_PORT=8000
+# AP_SERVER_DB_URL=sqlite:///data/ap_server.db
+# AP_SERVER_CORS_ALLOWED_ORIGINS=
diff --git a/autogpts/autogpt/agbenchmark_config/benchmarks.py b/autogpts/autogpt/agbenchmark_config/benchmarks.py
index c7e75406e..61b16984f 100644
--- a/autogpts/autogpt/agbenchmark_config/benchmarks.py
+++ b/autogpts/autogpt/agbenchmark_config/benchmarks.py
@@ -3,10 +3,12 @@ import logging
import sys
from pathlib import Path
+from autogpt.agent_manager.agent_manager import AgentManager
from autogpt.agents.agent import Agent, AgentConfiguration, AgentSettings
from autogpt.app.main import _configure_openai_provider, run_interaction_loop
from autogpt.commands import COMMAND_CATEGORIES
from autogpt.config import AIProfile, ConfigBuilder
+from autogpt.file_storage import FileStorageBackendName, get_storage
from autogpt.logs.config import configure_logging
from autogpt.models.command_registry import CommandRegistry
@@ -19,12 +21,13 @@ def run_specific_agent(task: str, continuous_mode: bool = False) -> None:
def bootstrap_agent(task: str, continuous_mode: bool) -> Agent:
- config = ConfigBuilder.build_config_from_env()
- config.logging.level = logging.DEBUG
- config.logging.log_dir = LOG_DIR
- config.logging.plain_console_output = True
- configure_logging(**config.logging.dict())
+ configure_logging(
+ level=logging.DEBUG,
+ log_dir=LOG_DIR,
+ plain_console_output=True,
+ )
+ config = ConfigBuilder.build_config_from_env()
config.continuous_mode = continuous_mode
config.continuous_limit = 20
config.noninteractive_mode = True
@@ -42,6 +45,7 @@ def bootstrap_agent(task: str, continuous_mode: bool) -> Agent:
agent_prompt_config.use_functions_api = config.openai_functions
agent_settings = AgentSettings(
name=Agent.default_settings.name,
+ agent_id=AgentManager.generate_id("AutoGPT-benchmark"),
description=Agent.default_settings.description,
ai_profile=ai_profile,
config=AgentConfiguration(
@@ -55,13 +59,20 @@ def bootstrap_agent(task: str, continuous_mode: bool) -> Agent:
history=Agent.default_settings.history.copy(deep=True),
)
+ local = config.file_storage_backend == FileStorageBackendName.LOCAL
+ restrict_to_root = not local or config.restrict_to_workspace
+ file_storage = get_storage(
+ config.file_storage_backend, root_path="data", restrict_to_root=restrict_to_root
+ )
+ file_storage.initialize()
+
agent = Agent(
settings=agent_settings,
llm_provider=_configure_openai_provider(config),
command_registry=command_registry,
+ file_storage=file_storage,
legacy_config=config,
)
- agent.attach_fs(config.app_data_dir / "agents" / "AutoGPT-benchmark") # HACK
return agent
diff --git a/autogpts/autogpt/autogpt/agent_factory/configurators.py b/autogpts/autogpt/autogpt/agent_factory/configurators.py
index a8e9cbab6..c938ba506 100644
--- a/autogpts/autogpt/autogpt/agent_factory/configurators.py
+++ b/autogpts/autogpt/autogpt/agent_factory/configurators.py
@@ -1,19 +1,21 @@
from typing import Optional
-from autogpt.agent_manager import AgentManager
from autogpt.agents.agent import Agent, AgentConfiguration, AgentSettings
from autogpt.commands import COMMAND_CATEGORIES
from autogpt.config import AIDirectives, AIProfile, Config
from autogpt.core.resource.model_providers import ChatModelProvider
+from autogpt.file_storage.base import FileStorage
from autogpt.logs.config import configure_chat_plugins
from autogpt.models.command_registry import CommandRegistry
from autogpt.plugins import scan_plugins
def create_agent(
+ agent_id: str,
task: str,
ai_profile: AIProfile,
app_config: Config,
+ file_storage: FileStorage,
llm_provider: ChatModelProvider,
directives: Optional[AIDirectives] = None,
) -> Agent:
@@ -23,26 +25,28 @@ def create_agent(
directives = AIDirectives.from_file(app_config.prompt_settings_file)
agent = _configure_agent(
+ agent_id=agent_id,
task=task,
ai_profile=ai_profile,
directives=directives,
app_config=app_config,
+ file_storage=file_storage,
llm_provider=llm_provider,
)
- agent.state.agent_id = AgentManager.generate_id(agent.ai_profile.ai_name)
-
return agent
def configure_agent_with_state(
state: AgentSettings,
app_config: Config,
+ file_storage: FileStorage,
llm_provider: ChatModelProvider,
) -> Agent:
return _configure_agent(
state=state,
app_config=app_config,
+ file_storage=file_storage,
llm_provider=llm_provider,
)
@@ -50,14 +54,17 @@ def configure_agent_with_state(
def _configure_agent(
app_config: Config,
llm_provider: ChatModelProvider,
+ file_storage: FileStorage,
+ agent_id: str = "",
task: str = "",
ai_profile: Optional[AIProfile] = None,
directives: Optional[AIDirectives] = None,
state: Optional[AgentSettings] = None,
) -> Agent:
- if not (state or task and ai_profile and directives):
+ if not (state or agent_id and task and ai_profile and directives):
raise TypeError(
- "Either (state) or (task, ai_profile, directives) must be specified"
+ "Either (state) or (agent_id, task, ai_profile, directives)"
+ " must be specified"
)
app_config.plugins = scan_plugins(app_config)
@@ -70,6 +77,7 @@ def _configure_agent(
)
agent_state = state or create_agent_state(
+ agent_id=agent_id,
task=task,
ai_profile=ai_profile,
directives=directives,
@@ -82,11 +90,13 @@ def _configure_agent(
settings=agent_state,
llm_provider=llm_provider,
command_registry=command_registry,
+ file_storage=file_storage,
legacy_config=app_config,
)
def create_agent_state(
+ agent_id: str,
task: str,
ai_profile: AIProfile,
directives: AIDirectives,
@@ -96,6 +106,7 @@ def create_agent_state(
agent_prompt_config.use_functions_api = app_config.openai_functions
return AgentSettings(
+ agent_id=agent_id,
name=Agent.default_settings.name,
description=Agent.default_settings.description,
task=task,
diff --git a/autogpts/autogpt/autogpt/agent_factory/generators.py b/autogpts/autogpt/autogpt/agent_factory/generators.py
index 2713d5cbb..9f9c44600 100644
--- a/autogpts/autogpt/autogpt/agent_factory/generators.py
+++ b/autogpts/autogpt/autogpt/agent_factory/generators.py
@@ -1,21 +1,26 @@
-from typing import TYPE_CHECKING
+from __future__ import annotations
-if TYPE_CHECKING:
- from autogpt.agents.agent import Agent
- from autogpt.config import Config
- from autogpt.core.resource.model_providers.schema import ChatModelProvider
+from typing import TYPE_CHECKING
from autogpt.config.ai_directives import AIDirectives
+from autogpt.file_storage.base import FileStorage
from .configurators import _configure_agent
from .profile_generator import generate_agent_profile_for_task
+if TYPE_CHECKING:
+ from autogpt.agents.agent import Agent
+ from autogpt.config import Config
+ from autogpt.core.resource.model_providers.schema import ChatModelProvider
+
async def generate_agent_for_task(
+ agent_id: str,
task: str,
- app_config: "Config",
- llm_provider: "ChatModelProvider",
-) -> "Agent":
+ app_config: Config,
+ file_storage: FileStorage,
+ llm_provider: ChatModelProvider,
+) -> Agent:
base_directives = AIDirectives.from_file(app_config.prompt_settings_file)
ai_profile, task_directives = await generate_agent_profile_for_task(
task=task,
@@ -23,9 +28,11 @@ async def generate_agent_for_task(
llm_provider=llm_provider,
)
return _configure_agent(
+ agent_id=agent_id,
task=task,
ai_profile=ai_profile,
directives=base_directives + task_directives,
app_config=app_config,
+ file_storage=file_storage,
llm_provider=llm_provider,
)
diff --git a/autogpts/autogpt/autogpt/agent_factory/profile_generator.py b/autogpts/autogpt/autogpt/agent_factory/profile_generator.py
index fd0e947f1..78afbe51a 100644
--- a/autogpts/autogpt/autogpt/agent_factory/profile_generator.py
+++ b/autogpts/autogpt/autogpt/agent_factory/profile_generator.py
@@ -8,9 +8,8 @@ from autogpt.core.prompting import (
LanguageModelClassification,
PromptStrategy,
)
-from autogpt.core.prompting.utils import json_loads
from autogpt.core.resource.model_providers.schema import (
- AssistantChatMessageDict,
+ AssistantChatMessage,
ChatMessage,
ChatModelProvider,
CompletionModelFunction,
@@ -186,7 +185,7 @@ class AgentProfileGenerator(PromptStrategy):
def parse_response_content(
self,
- response_content: AssistantChatMessageDict,
+ response_content: AssistantChatMessage,
) -> tuple[AIProfile, AIDirectives]:
"""Parse the actual text response from the objective model.
@@ -198,16 +197,19 @@ class AgentProfileGenerator(PromptStrategy):
"""
try:
- arguments = json_loads(
- response_content["tool_calls"][0]["function"]["arguments"]
- )
+ if not response_content.tool_calls:
+ raise ValueError(
+ f"LLM did not call {self._create_agent_function.name} function; "
+ "agent profile creation failed"
+ )
+ arguments: object = response_content.tool_calls[0].function.arguments
ai_profile = AIProfile(
ai_name=arguments.get("name"),
ai_role=arguments.get("description"),
)
ai_directives = AIDirectives(
- best_practices=arguments["directives"].get("best_practices"),
- constraints=arguments["directives"].get("constraints"),
+ best_practices=arguments.get("directives", {}).get("best_practices"),
+ constraints=arguments.get("directives", {}).get("constraints"),
resources=[],
)
except KeyError:
@@ -233,18 +235,14 @@ async def generate_agent_profile_for_task(
prompt = agent_profile_generator.build_prompt(task)
# Call LLM with the string as user input
- output = (
- await llm_provider.create_chat_completion(
- prompt.messages,
- model_name=app_config.smart_llm,
- functions=prompt.functions,
- )
- ).response
+ output = await llm_provider.create_chat_completion(
+ prompt.messages,
+ model_name=app_config.smart_llm,
+ functions=prompt.functions,
+ completion_parser=agent_profile_generator.parse_response_content,
+ )
# Debug LLM Output
- logger.debug(f"AI Config Generator Raw Output: {output}")
-
- # Parse the output
- ai_profile, ai_directives = agent_profile_generator.parse_response_content(output)
+ logger.debug(f"AI Config Generator Raw Output: {output.response}")
- return ai_profile, ai_directives
+ return output.parsed_result
diff --git a/autogpts/autogpt/autogpt/agent_manager/agent_manager.py b/autogpts/autogpt/autogpt/agent_manager/agent_manager.py
index 0b4731bc6..fd3becf84 100644
--- a/autogpts/autogpt/autogpt/agent_manager/agent_manager.py
+++ b/autogpts/autogpt/autogpt/agent_manager/agent_manager.py
@@ -2,47 +2,44 @@ from __future__ import annotations
import uuid
from pathlib import Path
-from typing import TYPE_CHECKING
-if TYPE_CHECKING:
- from autogpt.agents.agent import AgentSettings
-
-from autogpt.agents.utils.agent_file_manager import AgentFileManager
+from autogpt.agents.agent import AgentSettings
+from autogpt.file_storage.base import FileStorage
class AgentManager:
- def __init__(self, app_data_dir: Path):
- self.agents_dir = app_data_dir / "agents"
- if not self.agents_dir.exists():
- self.agents_dir.mkdir()
+ def __init__(self, file_storage: FileStorage):
+ self.file_manager = file_storage.clone_with_subroot("agents")
@staticmethod
def generate_id(agent_name: str) -> str:
+ """Generate a unique ID for an agent given agent name."""
unique_id = str(uuid.uuid4())[:8]
return f"{agent_name}-{unique_id}"
def list_agents(self) -> list[str]:
- return [
- dir.name
- for dir in self.agents_dir.iterdir()
- if dir.is_dir() and AgentFileManager(dir).state_file_path.exists()
- ]
-
- def get_agent_dir(self, agent_id: str, must_exist: bool = False) -> Path:
+ """Return all agent directories within storage."""
+ agent_dirs: list[str] = []
+ for dir in self.file_manager.list_folders():
+ if self.file_manager.exists(dir / "state.json"):
+ agent_dirs.append(dir.name)
+ return agent_dirs
+
+ def get_agent_dir(self, agent_id: str) -> Path:
+ """Return the directory of the agent with the given ID."""
assert len(agent_id) > 0
- agent_dir = self.agents_dir / agent_id
- if must_exist and not agent_dir.exists():
+ agent_dir: Path | None = None
+ if self.file_manager.exists(agent_id):
+ agent_dir = self.file_manager.root / agent_id
+ else:
raise FileNotFoundError(f"No agent with ID '{agent_id}'")
return agent_dir
- def retrieve_state(self, agent_id: str) -> AgentSettings:
- from autogpt.agents.agent import AgentSettings
-
- agent_dir = self.get_agent_dir(agent_id, True)
- state_file = AgentFileManager(agent_dir).state_file_path
- if not state_file.exists():
+ def load_agent_state(self, agent_id: str) -> AgentSettings:
+ """Load the state of the agent with the given ID."""
+ state_file_path = Path(agent_id) / "state.json"
+ if not self.file_manager.exists(state_file_path):
raise FileNotFoundError(f"Agent with ID '{agent_id}' has no state.json")
- state = AgentSettings.load_from_json_file(state_file)
- state.agent_data_dir = agent_dir
- return state
+ state = self.file_manager.read_file(state_file_path)
+ return AgentSettings.parse_raw(state)
diff --git a/autogpts/autogpt/autogpt/agents/agent.py b/autogpts/autogpt/autogpt/agents/agent.py
index fa387e79d..744607682 100644
--- a/autogpts/autogpt/autogpt/agents/agent.py
+++ b/autogpts/autogpt/autogpt/agents/agent.py
@@ -6,26 +6,24 @@ import time
from datetime import datetime
from typing import TYPE_CHECKING, Optional
-if TYPE_CHECKING:
- from autogpt.config import Config
- from autogpt.models.command_registry import CommandRegistry
-
+import sentry_sdk
from pydantic import Field
from autogpt.core.configuration import Configurable
from autogpt.core.prompting import ChatPrompt
from autogpt.core.resource.model_providers import (
+ AssistantChatMessage,
ChatMessage,
ChatModelProvider,
- ChatModelResponse,
)
-from autogpt.llm.api_manager import ApiManager
+from autogpt.file_storage.base import FileStorage
from autogpt.logs.log_cycle import (
CURRENT_CONTEXT_FILE_NAME,
NEXT_ACTION_FILE_NAME,
USER_INPUT_FILE_NAME,
LogCycleHandler,
)
+from autogpt.logs.utils import fmt_kwargs
from autogpt.models.action_history import (
Action,
ActionErrorResult,
@@ -37,14 +35,24 @@ from autogpt.models.command import CommandOutput
from autogpt.models.context_item import ContextItem
from .base import BaseAgent, BaseAgentConfiguration, BaseAgentSettings
+from .features.agent_file_manager import AgentFileManagerMixin
from .features.context import ContextMixin
-from .features.file_workspace import FileWorkspaceMixin
from .features.watchdog import WatchdogMixin
from .prompt_strategies.one_shot import (
OneShotAgentPromptConfiguration,
OneShotAgentPromptStrategy,
)
-from .utils.exceptions import AgentException, CommandExecutionError, UnknownCommandError
+from .utils.exceptions import (
+ AgentException,
+ AgentTerminated,
+ CommandExecutionError,
+ DuplicateOperationError,
+ UnknownCommandError,
+)
+
+if TYPE_CHECKING:
+ from autogpt.config import Config
+ from autogpt.models.command_registry import CommandRegistry
logger = logging.getLogger(__name__)
@@ -64,7 +72,7 @@ class AgentSettings(BaseAgentSettings):
class Agent(
ContextMixin,
- FileWorkspaceMixin,
+ AgentFileManagerMixin,
WatchdogMixin,
BaseAgent,
Configurable[AgentSettings],
@@ -76,11 +84,14 @@ class Agent(
description=__doc__,
)
+ prompt_strategy: OneShotAgentPromptStrategy
+
def __init__(
self,
settings: AgentSettings,
llm_provider: ChatModelProvider,
command_registry: CommandRegistry,
+ file_storage: FileStorage,
legacy_config: Config,
):
prompt_strategy = OneShotAgentPromptStrategy(
@@ -92,6 +103,7 @@ class Agent(
llm_provider=llm_provider,
prompt_strategy=prompt_strategy,
command_registry=command_registry,
+ file_storage=file_storage,
legacy_config=legacy_config,
)
@@ -116,30 +128,6 @@ class Agent(
ChatMessage.system(f"The current time and date is {time.strftime('%c')}"),
)
- # Add budget information (if any) to prompt
- api_manager = ApiManager()
- if api_manager.get_total_budget() > 0.0:
- remaining_budget = (
- api_manager.get_total_budget() - api_manager.get_total_cost()
- )
- if remaining_budget < 0:
- remaining_budget = 0
-
- budget_msg = ChatMessage.system(
- f"Your remaining API budget is ${remaining_budget:.3f}"
- + (
- " BUDGET EXCEEDED! SHUT DOWN!\n\n"
- if remaining_budget == 0
- else " Budget very nearly exceeded! Shut down gracefully!\n\n"
- if remaining_budget < 0.005
- else " Budget nearly exceeded. Finish up.\n\n"
- if remaining_budget < 0.01
- else ""
- ),
- )
- logger.debug(budget_msg)
- extra_messages.append(budget_msg)
-
if include_os_info is None:
include_os_info = self.legacy_config.execute_local_commands
@@ -164,20 +152,25 @@ class Agent(
return prompt
def parse_and_process_response(
- self, llm_response: ChatModelResponse, *args, **kwargs
+ self, llm_response: AssistantChatMessage, *args, **kwargs
) -> Agent.ThoughtProcessOutput:
for plugin in self.config.plugins:
if not plugin.can_handle_post_planning():
continue
- llm_response.response["content"] = plugin.post_planning(
- llm_response.response.get("content", "")
- )
+ llm_response.content = plugin.post_planning(llm_response.content or "")
(
command_name,
arguments,
assistant_reply_dict,
- ) = self.prompt_strategy.parse_response_content(llm_response.response)
+ ) = self.prompt_strategy.parse_response_content(llm_response)
+
+ # Check if command_name and arguments are already in the event_history
+ if self.event_history.matches_last_command(command_name, arguments):
+ raise DuplicateOperationError(
+ f"The command {command_name} with arguments {arguments} "
+ f"has been just executed."
+ )
self.log_cycle_handler.log_cycle(
self.ai_profile.ai_name,
@@ -243,8 +236,14 @@ class Agent(
self.context.add(context_item)
result = ActionSuccessResult(outputs=return_value)
+ except AgentTerminated:
+ raise
except AgentException as e:
result = ActionErrorResult.from_exception(e)
+ logger.warning(
+ f"{command_name}({fmt_kwargs(command_args)}) raised an error: {e}"
+ )
+ sentry_sdk.capture_exception(e)
result_tlength = self.llm_provider.count_tokens(str(result), self.llm.name)
if result_tlength > self.send_token_limit // 3:
@@ -263,6 +262,9 @@ class Agent(
# Update action history
self.event_history.register_result(result)
+ await self.event_history.handle_compression(
+ self.llm_provider, self.legacy_config
+ )
return result
diff --git a/autogpts/autogpt/autogpt/agents/base.py b/autogpts/autogpt/autogpt/agents/base.py
index 7c34d40ad..774070e8c 100644
--- a/autogpts/autogpt/autogpt/agents/base.py
+++ b/autogpts/autogpt/autogpt/agents/base.py
@@ -2,7 +2,6 @@ from __future__ import annotations
import logging
from abc import ABC, abstractmethod
-from pathlib import Path
from typing import TYPE_CHECKING, Any, Optional
from auto_gpt_plugin_template import AutoGPTPluginTemplate
@@ -12,6 +11,7 @@ if TYPE_CHECKING:
from autogpt.config import Config
from autogpt.core.prompting.base import PromptStrategy
from autogpt.core.resource.model_providers.schema import (
+ AssistantChatMessage,
ChatModelInfo,
ChatModelProvider,
ChatModelResponse,
@@ -38,12 +38,11 @@ from autogpt.core.resource.model_providers.openai import (
OpenAIModelName,
)
from autogpt.core.runner.client_lib.logging.helpers import dump_prompt
+from autogpt.file_storage.base import FileStorage
from autogpt.llm.providers.openai import get_openai_command_specs
from autogpt.models.action_history import ActionResult, EpisodicActionHistory
from autogpt.prompts.prompt import DEFAULT_TRIGGERING_PROMPT
-from .utils.agent_file_manager import AgentFileManager
-
logger = logging.getLogger(__name__)
CommandName = str
@@ -125,7 +124,6 @@ class BaseAgentConfiguration(SystemConfiguration):
class BaseAgentSettings(SystemSettings):
agent_id: str = ""
- agent_data_dir: Optional[Path] = None
ai_profile: AIProfile = Field(default_factory=lambda: AIProfile(ai_name="AutoGPT"))
"""The AI profile or "personality" of the agent."""
@@ -146,14 +144,6 @@ class BaseAgentSettings(SystemSettings):
history: EpisodicActionHistory = Field(default_factory=EpisodicActionHistory)
"""(STATE) The action history of the agent."""
- def save_to_json_file(self, file_path: Path) -> None:
- with file_path.open("w") as f:
- f.write(self.json())
-
- @classmethod
- def load_from_json_file(cls, file_path: Path):
- return cls.parse_file(file_path)
-
class BaseAgent(Configurable[BaseAgentSettings], ABC):
"""Base class for all AutoGPT agent classes."""
@@ -171,6 +161,7 @@ class BaseAgent(Configurable[BaseAgentSettings], ABC):
llm_provider: ChatModelProvider,
prompt_strategy: PromptStrategy,
command_registry: CommandRegistry,
+ file_storage: FileStorage,
legacy_config: Config,
):
self.state = settings
@@ -182,12 +173,6 @@ class BaseAgent(Configurable[BaseAgentSettings], ABC):
self.legacy_config = legacy_config
"""LEGACY: Monolithic application configuration."""
- self.file_manager: AgentFileManager = (
- AgentFileManager(settings.agent_data_dir)
- if settings.agent_data_dir
- else None
- ) # type: ignore
-
self.llm_provider = llm_provider
self.prompt_strategy = prompt_strategy
@@ -202,21 +187,6 @@ class BaseAgent(Configurable[BaseAgentSettings], ABC):
logger.debug(f"Created {__class__} '{self.ai_profile.ai_name}'")
- def set_id(self, new_id: str, new_agent_dir: Optional[Path] = None):
- self.state.agent_id = new_id
- if self.state.agent_data_dir:
- if not new_agent_dir:
- raise ValueError(
- "new_agent_dir must be specified if one is currently configured"
- )
- self.attach_fs(new_agent_dir)
-
- def attach_fs(self, agent_dir: Path) -> AgentFileManager:
- self.file_manager = AgentFileManager(agent_dir)
- self.file_manager.initialize()
- self.state.agent_data_dir = agent_dir
- return self.file_manager
-
@property
def llm(self) -> ChatModelInfo:
"""The LLM that the agent uses to think."""
@@ -235,10 +205,6 @@ class BaseAgent(Configurable[BaseAgentSettings], ABC):
Returns:
The command name and arguments, if any, and the agent's thoughts.
"""
- assert self.file_manager, (
- f"Agent has no FileManager: call {__class__.__name__}.attach_fs()"
- " before trying to run the agent."
- )
# Scratchpad as surrogate PromptGenerator for plugin hooks
self._prompt_scratchpad = PromptScratchpad()
@@ -247,7 +213,7 @@ class BaseAgent(Configurable[BaseAgentSettings], ABC):
prompt = self.on_before_think(prompt, scratchpad=self._prompt_scratchpad)
logger.debug(f"Executing prompt:\n{dump_prompt(prompt)}")
- raw_response = await self.llm_provider.create_chat_completion(
+ response = await self.llm_provider.create_chat_completion(
prompt.messages,
functions=get_openai_command_specs(
self.command_registry.list_available_commands(self)
@@ -256,11 +222,16 @@ class BaseAgent(Configurable[BaseAgentSettings], ABC):
if self.config.use_functions_api
else [],
model_name=self.llm.name,
+ completion_parser=lambda r: self.parse_and_process_response(
+ r,
+ prompt,
+ scratchpad=self._prompt_scratchpad,
+ ),
)
self.config.cycle_count += 1
return self.on_response(
- llm_response=raw_response,
+ llm_response=response,
prompt=prompt,
scratchpad=self._prompt_scratchpad,
)
@@ -397,18 +368,14 @@ class BaseAgent(Configurable[BaseAgentSettings], ABC):
The parsed command name and command args, if any, and the agent thoughts.
"""
- return self.parse_and_process_response(
- llm_response,
- prompt,
- scratchpad=scratchpad,
- )
+ return llm_response.parsed_result
# TODO: update memory/context
@abstractmethod
def parse_and_process_response(
self,
- llm_response: ChatModelResponse,
+ llm_response: AssistantChatMessage,
prompt: ChatPrompt,
scratchpad: PromptScratchpad,
) -> ThoughtProcessOutput:
diff --git a/autogpts/autogpt/autogpt/agents/features/agent_file_manager.py b/autogpts/autogpt/autogpt/agents/features/agent_file_manager.py
new file mode 100644
index 000000000..80257fbea
--- /dev/null
+++ b/autogpts/autogpt/autogpt/agents/features/agent_file_manager.py
@@ -0,0 +1,102 @@
+from __future__ import annotations
+
+import logging
+from typing import Optional
+
+from autogpt.file_storage.base import FileStorage
+
+from ..base import BaseAgent, BaseAgentSettings
+
+logger = logging.getLogger(__name__)
+
+
+class AgentFileManagerMixin:
+ """Mixin that adds file manager (e.g. Agent state)
+ and workspace manager (e.g. Agent output files) support."""
+
+ files: FileStorage
+ """Agent-related files, e.g. state, logs.
+ Use `workspace` to access the agent's workspace files."""
+
+ workspace: FileStorage
+ """Workspace that the agent has access to, e.g. for reading/writing files.
+ Use `files` to access agent-related files, e.g. state, logs."""
+
+ STATE_FILE = "state.json"
+ """The name of the file where the agent's state is stored."""
+
+ LOGS_FILE = "file_logger.log"
+ """The name of the file where the agent's logs are stored."""
+
+ def __init__(self, **kwargs):
+ # Initialize other bases first, because we need the config from BaseAgent
+ super(AgentFileManagerMixin, self).__init__(**kwargs)
+
+ if not isinstance(self, BaseAgent):
+ raise NotImplementedError(
+ f"{__class__.__name__} can only be applied to BaseAgent derivatives"
+ )
+
+ if "file_storage" not in kwargs:
+ raise ValueError(
+ "AgentFileManagerMixin requires a file_storage in the constructor."
+ )
+
+ state: BaseAgentSettings = getattr(self, "state")
+ if not state.agent_id:
+ raise ValueError("Agent must have an ID.")
+
+ file_storage: FileStorage = kwargs["file_storage"]
+ self.files = file_storage.clone_with_subroot(f"agents/{state.agent_id}/")
+ self.workspace = file_storage.clone_with_subroot(
+ f"agents/{state.agent_id}/workspace"
+ )
+ self._file_storage = file_storage
+ # Read and cache logs
+ self._file_logs_cache = []
+ if self.files.exists(self.LOGS_FILE):
+ self._file_logs_cache = self.files.read_file(self.LOGS_FILE).split("\n")
+
+ async def log_file_operation(self, content: str) -> None:
+ """Log a file operation to the agent's log file."""
+ logger.debug(f"Logging operation: {content}")
+ self._file_logs_cache.append(content)
+ await self.files.write_file(
+ self.LOGS_FILE, "\n".join(self._file_logs_cache) + "\n"
+ )
+
+ def get_file_operation_lines(self) -> list[str]:
+ """Get the agent's file operation logs as list of strings."""
+ return self._file_logs_cache
+
+ async def save_state(self, save_as: Optional[str] = None) -> None:
+ """Save the agent's state to the state file."""
+ state: BaseAgentSettings = getattr(self, "state")
+ if save_as:
+ temp_id = state.agent_id
+ state.agent_id = save_as
+ self._file_storage.make_dir(f"agents/{save_as}")
+ # Save state
+ await self._file_storage.write_file(
+ f"agents/{save_as}/{self.STATE_FILE}", state.json()
+ )
+ # Copy workspace
+ self._file_storage.copy(
+ f"agents/{temp_id}/workspace",
+ f"agents/{save_as}/workspace",
+ )
+ state.agent_id = temp_id
+ else:
+ await self.files.write_file(self.files.root / self.STATE_FILE, state.json())
+
+ def change_agent_id(self, new_id: str):
+ """Change the agent's ID and update the file storage accordingly."""
+ state: BaseAgentSettings = getattr(self, "state")
+ # Rename the agent's files and workspace
+ self._file_storage.rename(f"agents/{state.agent_id}", f"agents/{new_id}")
+ # Update the file storage objects
+ self.files = self._file_storage.clone_with_subroot(f"agents/{new_id}/")
+ self.workspace = self._file_storage.clone_with_subroot(
+ f"agents/{new_id}/workspace"
+ )
+ state.agent_id = new_id
diff --git a/autogpts/autogpt/autogpt/agents/features/file_workspace.py b/autogpts/autogpt/autogpt/agents/features/file_workspace.py
deleted file mode 100644
index 22ab8119d..000000000
--- a/autogpts/autogpt/autogpt/agents/features/file_workspace.py
+++ /dev/null
@@ -1,65 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-if TYPE_CHECKING:
- from pathlib import Path
-
- from ..base import BaseAgent, Config
-
-from autogpt.file_workspace import (
- FileWorkspace,
- FileWorkspaceBackendName,
- get_workspace,
-)
-
-from ..base import AgentFileManager, BaseAgentSettings
-
-
-class FileWorkspaceMixin:
- """Mixin that adds workspace support to a class"""
-
- workspace: FileWorkspace = None
- """Workspace that the agent has access to, e.g. for reading/writing files."""
-
- def __init__(self, **kwargs):
- # Initialize other bases first, because we need the config from BaseAgent
- super(FileWorkspaceMixin, self).__init__(**kwargs)
-
- file_manager: AgentFileManager = getattr(self, "file_manager")
- if not file_manager:
- return
-
- self._setup_workspace()
-
- def attach_fs(self, agent_dir: Path):
- res = super(FileWorkspaceMixin, self).attach_fs(agent_dir)
-
- self._setup_workspace()
-
- return res
-
- def _setup_workspace(self) -> None:
- settings: BaseAgentSettings = getattr(self, "state")
- assert settings.agent_id, "Cannot attach workspace to anonymous agent"
- app_config: Config = getattr(self, "legacy_config")
- file_manager: AgentFileManager = getattr(self, "file_manager")
-
- ws_backend = app_config.workspace_backend
- local = ws_backend == FileWorkspaceBackendName.LOCAL
- workspace = get_workspace(
- backend=ws_backend,
- id=settings.agent_id if not local else "",
- root_path=file_manager.root / "workspace" if local else None,
- )
- if local and settings.config.allow_fs_access:
- workspace._restrict_to_root = False # type: ignore
- workspace.initialize()
- self.workspace = workspace
-
-
-def get_agent_workspace(agent: BaseAgent) -> FileWorkspace | None:
- if isinstance(agent, FileWorkspaceMixin):
- return agent.workspace
-
- return None
diff --git a/autogpts/autogpt/autogpt/agents/prompt_strategies/one_shot.py b/autogpts/autogpt/autogpt/agents/prompt_strategies/one_shot.py
index 1bfe9f5ba..994df6181 100644
--- a/autogpts/autogpt/autogpt/agents/prompt_strategies/one_shot.py
+++ b/autogpts/autogpt/autogpt/agents/prompt_strategies/one_shot.py
@@ -21,12 +21,12 @@ from autogpt.core.prompting import (
PromptStrategy,
)
from autogpt.core.resource.model_providers.schema import (
- AssistantChatMessageDict,
+ AssistantChatMessage,
ChatMessage,
CompletionModelFunction,
)
from autogpt.core.utils.json_schema import JSONSchema
-from autogpt.json_utils.utilities import extract_dict_from_response
+from autogpt.core.utils.json_utils import extract_dict_from_json
from autogpt.prompts.utils import format_numbered_list, indent
@@ -264,25 +264,16 @@ class OneShotAgentPromptStrategy(PromptStrategy):
steps: list[str] = []
tokens: int = 0
- # start: int = len(episode_history)
+ n_episodes = len(episode_history)
- for i, c in reversed(list(enumerate(episode_history))):
- step = f"### Step {i+1}: Executed `{c.action.format_call()}`\n"
- step += f'- **Reasoning:** "{c.action.reasoning}"\n'
- step += (
- f"- **Status:** `{c.result.status if c.result else 'did_not_finish'}`\n"
- )
- if c.result:
- if c.result.status == "success":
- result = str(c.result)
- result = "\n" + indent(result) if "\n" in result else result
- step += f"- **Output:** {result}"
- elif c.result.status == "error":
- step += f"- **Reason:** {c.result.reason}\n"
- if c.result.error:
- step += f"- **Error:** {c.result.error}\n"
- elif c.result.status == "interrupted_by_human":
- step += f"- **Feedback:** {c.result.feedback}\n"
+ for i, episode in enumerate(reversed(episode_history)):
+ # Use full format for the latest 4 steps, summary or format for older steps
+ if i < 4 or episode.summary is None:
+ step_content = indent(episode.format(), 2).strip()
+ else:
+ step_content = episode.summary
+
+ step = f"* Step {n_episodes - i}: {step_content}"
if max_tokens and count_tokens:
step_tokens = count_tokens(step)
@@ -291,10 +282,6 @@ class OneShotAgentPromptStrategy(PromptStrategy):
tokens += step_tokens
steps.insert(0, step)
- # start = i
-
- # # TODO: summarize remaining
- # part = slice(0, start)
return "\n\n".join(steps)
@@ -386,17 +373,26 @@ class OneShotAgentPromptStrategy(PromptStrategy):
def parse_response_content(
self,
- response: AssistantChatMessageDict,
+ response: AssistantChatMessage,
) -> Agent.ThoughtProcessOutput:
- if "content" not in response:
+ if not response.content:
raise InvalidAgentResponseError("Assistant response has no text content")
- assistant_reply_dict = extract_dict_from_response(response["content"])
-
- _, errors = self.response_schema.validate_object(
- object=assistant_reply_dict,
- logger=self.logger,
+ self.logger.debug(
+ "LLM response content:"
+ + (
+ f"\n{response.content}"
+ if "\n" in response.content
+ else f" '{response.content}'"
+ )
+ )
+ assistant_reply_dict = extract_dict_from_json(response.content)
+ self.logger.debug(
+ "Validating object extracted from LLM response:\n"
+ f"{json.dumps(assistant_reply_dict, indent=4)}"
)
+
+ _, errors = self.response_schema.validate_object(assistant_reply_dict)
if errors:
raise InvalidAgentResponseError(
"Validation of response failed:\n "
@@ -417,14 +413,14 @@ class OneShotAgentPromptStrategy(PromptStrategy):
def extract_command(
assistant_reply_json: dict,
- assistant_reply: AssistantChatMessageDict,
+ assistant_reply: AssistantChatMessage,
use_openai_functions_api: bool,
) -> tuple[str, dict[str, str]]:
"""Parse the response and return the command name and arguments
Args:
assistant_reply_json (dict): The response object from the AI
- assistant_reply (ChatModelResponse): The model response from the AI
+ assistant_reply (AssistantChatMessage): The model response from the AI
config (Config): The config object
Returns:
@@ -436,13 +432,11 @@ def extract_command(
Exception: If any other error occurs
"""
if use_openai_functions_api:
- if not assistant_reply.get("tool_calls"):
+ if not assistant_reply.tool_calls:
raise InvalidAgentResponseError("No 'tool_calls' in assistant reply")
assistant_reply_json["command"] = {
- "name": assistant_reply["tool_calls"][0]["function"]["name"],
- "args": json.loads(
- assistant_reply["tool_calls"][0]["function"]["arguments"]
- ),
+ "name": assistant_reply.tool_calls[0].function.name,
+ "args": assistant_reply.tool_calls[0].function.arguments,
}
try:
if not isinstance(assistant_reply_json, dict):
diff --git a/autogpts/autogpt/autogpt/agents/utils/agent_file_manager.py b/autogpts/autogpt/autogpt/agents/utils/agent_file_manager.py
deleted file mode 100644
index 4db788bf2..000000000
--- a/autogpts/autogpt/autogpt/agents/utils/agent_file_manager.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from __future__ import annotations
-
-import logging
-from pathlib import Path
-
-logger = logging.getLogger(__name__)
-
-
-class AgentFileManager:
- """A class that represents a workspace for an AutoGPT agent."""
-
- def __init__(self, agent_data_dir: Path):
- self._root = agent_data_dir.resolve()
-
- @property
- def root(self) -> Path:
- """The root directory of the workspace."""
- return self._root
-
- def initialize(self) -> None:
- self.root.mkdir(exist_ok=True, parents=True)
- self.init_file_ops_log(self.file_ops_log_path)
-
- @property
- def state_file_path(self) -> Path:
- return self.root / "state.json"
-
- @property
- def file_ops_log_path(self) -> Path:
- return self.root / "file_logger.log"
-
- @staticmethod
- def init_file_ops_log(file_logger_path: Path) -> Path:
- if not file_logger_path.exists():
- with file_logger_path.open(mode="w", encoding="utf-8") as f:
- f.write("")
- return file_logger_path
diff --git a/autogpts/autogpt/autogpt/agents/utils/exceptions.py b/autogpts/autogpt/autogpt/agents/utils/exceptions.py
index 704922b0a..211c8443c 100644
--- a/autogpts/autogpt/autogpt/agents/utils/exceptions.py
+++ b/autogpts/autogpt/autogpt/agents/utils/exceptions.py
@@ -18,6 +18,10 @@ class AgentTerminated(AgentException):
"""The agent terminated or was terminated"""
+class AgentFinished(AgentTerminated):
+ """The agent self-terminated"""
+
+
class ConfigurationError(AgentException):
"""Error caused by invalid, incompatible or otherwise incorrect configuration"""
diff --git a/autogpts/autogpt/autogpt/app/agent_protocol_server.py b/autogpts/autogpt/autogpt/app/agent_protocol_server.py
index 1ee6f1efa..fe0a3a0ee 100644
--- a/autogpts/autogpt/autogpt/app/agent_protocol_server.py
+++ b/autogpts/autogpt/autogpt/app/agent_protocol_server.py
@@ -1,7 +1,7 @@
-import copy
import logging
import os
import pathlib
+from collections import defaultdict
from io import BytesIO
from uuid import uuid4
@@ -26,39 +26,54 @@ from forge.sdk.model import (
from forge.sdk.routes.agent_protocol import base_router
from hypercorn.asyncio import serve as hypercorn_serve
from hypercorn.config import Config as HypercornConfig
+from sentry_sdk import set_user
from autogpt.agent_factory.configurators import configure_agent_with_state
from autogpt.agent_factory.generators import generate_agent_for_task
from autogpt.agent_manager import AgentManager
+from autogpt.agents.utils.exceptions import AgentFinished
+from autogpt.app.utils import is_port_free
from autogpt.commands.system import finish
from autogpt.commands.user_interaction import ask_user
from autogpt.config import Config
from autogpt.core.resource.model_providers import ChatModelProvider
-from autogpt.file_workspace import (
- FileWorkspace,
- FileWorkspaceBackendName,
- get_workspace,
-)
+from autogpt.core.resource.model_providers.openai import OpenAIProvider
+from autogpt.core.resource.model_providers.schema import ModelProviderBudget
+from autogpt.file_storage import FileStorage
+from autogpt.logs.utils import fmt_kwargs
from autogpt.models.action_history import ActionErrorResult, ActionSuccessResult
logger = logging.getLogger(__name__)
class AgentProtocolServer:
+ _task_budgets: dict[str, ModelProviderBudget]
+
def __init__(
self,
app_config: Config,
database: AgentDB,
+ file_storage: FileStorage,
llm_provider: ChatModelProvider,
):
self.app_config = app_config
self.db = database
+ self.file_storage = file_storage
self.llm_provider = llm_provider
- self.agent_manager = AgentManager(app_data_dir=app_config.app_data_dir)
+ self.agent_manager = AgentManager(file_storage)
+ self._task_budgets = defaultdict(ModelProviderBudget)
async def start(self, port: int = 8000, router: APIRouter = base_router):
"""Start the agent server."""
logger.debug("Starting the agent server...")
+ if not is_port_free(port):
+ logger.error(f"Port {port} is already in use.")
+ logger.info(
+ "You can specify a port by either setting the AP_SERVER_PORT "
+ "environment variable or defining AP_SERVER_PORT in the .env file."
+ )
+ return
+
config = HypercornConfig()
config.bind = [f"localhost:{port}"]
app = FastAPI(
@@ -68,11 +83,14 @@ class AgentProtocolServer:
version="v0.4",
)
- # Add CORS middleware
- origins = [
- "*",
- # Add any other origins you want to whitelist
+ # Configure CORS middleware
+ default_origins = [f"http://localhost:{port}"] # Default only local access
+ configured_origins = [
+ origin
+ for origin in os.getenv("AP_SERVER_CORS_ALLOWED_ORIGINS", "").split(",")
+ if origin # Empty list if not configured
]
+ origins = configured_origins or default_origins
app.add_middleware(
CORSMiddleware,
@@ -116,20 +134,23 @@ class AgentProtocolServer:
"""
Create a task for the agent.
"""
+ if user_id := (task_request.additional_input or {}).get("user_id"):
+ set_user({"id": user_id})
+
task = await self.db.create_task(
input=task_request.input,
additional_input=task_request.additional_input,
)
logger.debug(f"Creating agent for task: '{task.input}'")
task_agent = await generate_agent_for_task(
+ agent_id=task_agent_id(task.task_id),
task=task.input,
app_config=self.app_config,
+ file_storage=self.file_storage,
llm_provider=self._get_task_llm_provider(task),
)
- agent_id = task_agent.state.agent_id = task_agent_id(task.task_id)
- logger.debug(f"New agent ID: {agent_id}")
- task_agent.attach_fs(self.app_config.app_data_dir / "agents" / agent_id)
- task_agent.state.save_to_json_file(task_agent.file_manager.state_file_path)
+ await task_agent.save_state()
+
return task
async def list_tasks(self, page: int = 1, pageSize: int = 10) -> TaskListResponse:
@@ -167,11 +188,15 @@ class AgentProtocolServer:
# Restore Agent instance
task = await self.get_task(task_id)
agent = configure_agent_with_state(
- state=self.agent_manager.retrieve_state(task_agent_id(task_id)),
+ state=self.agent_manager.load_agent_state(task_agent_id(task_id)),
app_config=self.app_config,
+ file_storage=self.file_storage,
llm_provider=self._get_task_llm_provider(task),
)
+ if user_id := (task.additional_input or {}).get("user_id"):
+ set_user({"id": user_id})
+
# According to the Agent Protocol spec, the first execute_step request contains
# the same task input as the parent create_task request.
# To prevent this from interfering with the agent's process, we ignore the input
@@ -212,23 +237,10 @@ class AgentProtocolServer:
# Execute previously proposed action
if execute_command:
assert execute_command_args is not None
- agent.workspace.on_write_file = lambda path: self.db.create_artifact(
- task_id=step.task_id,
- step_id=step.step_id,
- file_name=path.parts[-1],
- agent_created=True,
- relative_path=str(path),
+ agent.workspace.on_write_file = lambda path: self._on_agent_write_file(
+ task=task, step=step, relative_path=path
)
- if step.is_last and execute_command == finish.__name__:
- assert execute_command_args
- step = await self.db.update_step(
- task_id=task_id,
- step_id=step.step_id,
- output=execute_command_args["reason"],
- )
- return step
-
if execute_command == ask_user.__name__: # HACK
execute_result = ActionSuccessResult(outputs=user_input)
agent.event_history.register_result(execute_result)
@@ -240,11 +252,31 @@ class AgentProtocolServer:
step_id=step.step_id,
status="running",
)
- # Execute previously proposed action
- execute_result = await agent.execute(
- command_name=execute_command,
- command_args=execute_command_args,
- )
+
+ try:
+ # Execute previously proposed action
+ execute_result = await agent.execute(
+ command_name=execute_command,
+ command_args=execute_command_args,
+ )
+ except AgentFinished:
+ additional_output = {}
+ task_total_cost = agent.llm_provider.get_incurred_cost()
+ if task_total_cost > 0:
+ additional_output["task_total_cost"] = task_total_cost
+ logger.info(
+ f"Total LLM cost for task {task_id}: "
+ f"${round(task_total_cost, 2)}"
+ )
+
+ step = await self.db.update_step(
+ task_id=task_id,
+ step_id=step.step_id,
+ output=execute_command_args["reason"],
+ additional_output=additional_output,
+ )
+ await agent.save_state()
+ return step
else:
assert user_input
execute_result = await agent.execute(
@@ -290,12 +322,16 @@ class AgentProtocolServer:
"name": execute_command,
"args": execute_command_args,
"result": (
- orjson.loads(execute_result.json())
- if not isinstance(execute_result, ActionErrorResult)
- else {
- "error": str(execute_result.error),
- "reason": execute_result.reason,
- }
+ ""
+ if execute_result is None
+ else (
+ orjson.loads(execute_result.json())
+ if not isinstance(execute_result, ActionErrorResult)
+ else {
+ "error": str(execute_result.error),
+ "reason": execute_result.reason,
+ }
+ )
),
},
}
@@ -305,6 +341,14 @@ class AgentProtocolServer:
**raw_output,
}
+ task_cumulative_cost = agent.llm_provider.get_incurred_cost()
+ if task_cumulative_cost > 0:
+ additional_output["task_cumulative_cost"] = task_cumulative_cost
+ logger.debug(
+ f"Running total LLM cost for task {task_id}: "
+ f"${round(task_cumulative_cost, 3)}"
+ )
+
step = await self.db.update_step(
task_id=task_id,
step_id=step.step_id,
@@ -313,9 +357,33 @@ class AgentProtocolServer:
additional_output=additional_output,
)
- agent.state.save_to_json_file(agent.file_manager.state_file_path)
+ await agent.save_state()
return step
+ async def _on_agent_write_file(
+ self, task: Task, step: Step, relative_path: pathlib.Path
+ ) -> None:
+ """
+ Creates an Artifact for the written file, or updates the Artifact if it exists.
+ """
+ if relative_path.is_absolute():
+ raise ValueError(f"File path '{relative_path}' is not relative")
+ for a in task.artifacts or []:
+ if a.relative_path == str(relative_path):
+ logger.debug(f"Updating Artifact after writing to existing file: {a}")
+ if not a.agent_created:
+ await self.db.update_artifact(a.artifact_id, agent_created=True)
+ break
+ else:
+ logger.debug(f"Creating Artifact for new file '{relative_path}'")
+ await self.db.create_artifact(
+ task_id=step.task_id,
+ step_id=step.step_id,
+ file_name=relative_path.parts[-1],
+ agent_created=True,
+ relative_path=str(relative_path),
+ )
+
async def get_step(self, task_id: str, step_id: str) -> Step:
"""
Get a step by ID.
@@ -338,7 +406,6 @@ class AgentProtocolServer:
"""
Create an artifact for the task.
"""
- data = None
file_name = file.filename or str(uuid4())
data = b""
while contents := file.file.read(1024 * 1024):
@@ -349,7 +416,7 @@ class AgentProtocolServer:
else:
file_path = os.path.join(relative_path, file_name)
- workspace = self._get_task_agent_file_workspace(task_id, self.agent_manager)
+ workspace = self._get_task_agent_file_workspace(task_id)
await workspace.write_file(file_path, data)
artifact = await self.db.create_artifact(
@@ -365,12 +432,12 @@ class AgentProtocolServer:
Download a task artifact by ID.
"""
try:
+ workspace = self._get_task_agent_file_workspace(task_id)
artifact = await self.db.get_artifact(artifact_id)
if artifact.file_name not in artifact.relative_path:
file_path = os.path.join(artifact.relative_path, artifact.file_name)
else:
file_path = artifact.relative_path
- workspace = self._get_task_agent_file_workspace(task_id, self.agent_manager)
retrieved_artifact = workspace.read_file(file_path, binary=True)
except NotFoundError:
raise
@@ -385,28 +452,9 @@ class AgentProtocolServer:
},
)
- def _get_task_agent_file_workspace(
- self,
- task_id: str | int,
- agent_manager: AgentManager,
- ) -> FileWorkspace:
- use_local_ws = (
- self.app_config.workspace_backend == FileWorkspaceBackendName.LOCAL
- )
+ def _get_task_agent_file_workspace(self, task_id: str | int) -> FileStorage:
agent_id = task_agent_id(task_id)
- workspace = get_workspace(
- backend=self.app_config.workspace_backend,
- id=agent_id if not use_local_ws else "",
- root_path=agent_manager.get_agent_dir(
- agent_id=agent_id,
- must_exist=True,
- )
- / "workspace"
- if use_local_ws
- else None,
- )
- workspace.initialize()
- return workspace
+ return self.file_storage.clone_with_subroot(f"agents/{agent_id}/workspace")
def _get_task_llm_provider(
self, task: Task, step_id: str = ""
@@ -414,21 +462,31 @@ class AgentProtocolServer:
"""
Configures the LLM provider with headers to link outgoing requests to the task.
"""
- task_llm_provider = copy.deepcopy(self.llm_provider)
- _extra_request_headers = task_llm_provider._configuration.extra_request_headers
+ task_llm_budget = self._task_budgets[task.task_id]
+ task_llm_provider_config = self.llm_provider._configuration.copy(deep=True)
+ _extra_request_headers = task_llm_provider_config.extra_request_headers
_extra_request_headers["AP-TaskID"] = task.task_id
if step_id:
_extra_request_headers["AP-StepID"] = step_id
if task.additional_input and (user_id := task.additional_input.get("user_id")):
_extra_request_headers["AutoGPT-UserID"] = user_id
- return task_llm_provider
+ task_llm_provider = None
+ if isinstance(self.llm_provider, OpenAIProvider):
+ settings = self.llm_provider._settings.copy()
+ settings.budget = task_llm_budget
+ settings.configuration = task_llm_provider_config # type: ignore
+ task_llm_provider = OpenAIProvider(
+ settings=settings,
+ logger=logger.getChild(f"Task-{task.task_id}_OpenAIProvider"),
+ )
+ if task_llm_provider and task_llm_provider._budget:
+ self._task_budgets[task.task_id] = task_llm_provider._budget
-def task_agent_id(task_id: str | int) -> str:
- return f"AutoGPT-{task_id}"
+ return task_llm_provider or self.llm_provider
-def fmt_kwargs(kwargs: dict) -> str:
- return ", ".join(f"{n}={repr(v)}" for n, v in kwargs.items())
+def task_agent_id(task_id: str | int) -> str:
+ return f"AutoGPT-{task_id}"
diff --git a/autogpts/autogpt/autogpt/app/cli.py b/autogpts/autogpt/autogpt/app/cli.py
index ccfa9a8ae..e6ca0a783 100644
--- a/autogpts/autogpt/autogpt/app/cli.py
+++ b/autogpts/autogpt/autogpt/app/cli.py
@@ -7,10 +7,14 @@ import click
from autogpt.logs.config import LogFormatName
+from .telemetry import setup_telemetry
+
@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx: click.Context):
+ setup_telemetry()
+
# Invoke `run` by default
if ctx.invoked_subcommand is None:
ctx.invoke(run)
diff --git a/autogpts/autogpt/autogpt/app/configurator.py b/autogpts/autogpt/autogpt/app/configurator.py
index 292bf9753..06f976c83 100644
--- a/autogpts/autogpt/autogpt/app/configurator.py
+++ b/autogpts/autogpt/autogpt/app/configurator.py
@@ -3,7 +3,7 @@ from __future__ import annotations
import logging
from pathlib import Path
-from typing import TYPE_CHECKING, Literal, Optional
+from typing import Literal, Optional
import click
from colorama import Back, Fore, Style
@@ -11,29 +11,20 @@ from colorama import Back, Fore, Style
from autogpt import utils
from autogpt.config import Config
from autogpt.config.config import GPT_3_MODEL, GPT_4_MODEL
-from autogpt.llm.api_manager import ApiManager
-from autogpt.logs.config import LogFormatName
+from autogpt.core.resource.model_providers.openai import OpenAIModelName, OpenAIProvider
from autogpt.logs.helpers import request_user_double_check
from autogpt.memory.vector import get_supported_memory_backends
-if TYPE_CHECKING:
- from autogpt.core.resource.model_providers.openai import OpenAICredentials
-
logger = logging.getLogger(__name__)
-def apply_overrides_to_config(
+async def apply_overrides_to_config(
config: Config,
continuous: bool = False,
continuous_limit: Optional[int] = None,
ai_settings_file: Optional[Path] = None,
prompt_settings_file: Optional[Path] = None,
skip_reprompt: bool = False,
- speak: bool = False,
- debug: bool = False,
- log_level: Optional[str] = None,
- log_format: Optional[str] = None,
- log_file_format: Optional[str] = None,
gpt3only: bool = False,
gpt4only: bool = False,
memory_type: Optional[str] = None,
@@ -63,19 +54,6 @@ def apply_overrides_to_config(
skips_news (bool): Whether to suppress the output of latest news on startup.
"""
config.continuous_mode = False
- config.tts_config.speak_mode = False
-
- # Set log level
- if debug:
- config.logging.level = logging.DEBUG
- elif log_level and type(_level := logging.getLevelName(log_level.upper())) is int:
- config.logging.level = _level
-
- # Set log format
- if log_format and log_format in LogFormatName._value2member_map_:
- config.logging.log_format = LogFormatName(log_format)
- if log_file_format and log_file_format in LogFormatName._value2member_map_:
- config.logging.log_file_format = LogFormatName(log_file_format)
if continuous:
logger.warning(
@@ -92,9 +70,6 @@ def apply_overrides_to_config(
if continuous_limit and not continuous:
raise click.UsageError("--continuous-limit can only be used with --continuous")
- if speak:
- config.tts_config.speak_mode = True
-
# Set the default LLM models
if gpt3only:
# --gpt3only should always use gpt-3.5-turbo, despite user's FAST_LLM config
@@ -102,23 +77,14 @@ def apply_overrides_to_config(
config.smart_llm = GPT_3_MODEL
elif (
gpt4only
- and check_model(
- GPT_4_MODEL,
- model_type="smart_llm",
- api_credentials=config.openai_credentials,
- )
- == GPT_4_MODEL
+ and (await check_model(GPT_4_MODEL, model_type="smart_llm")) == GPT_4_MODEL
):
# --gpt4only should always use gpt-4, despite user's SMART_LLM config
config.fast_llm = GPT_4_MODEL
config.smart_llm = GPT_4_MODEL
else:
- config.fast_llm = check_model(
- config.fast_llm, "fast_llm", api_credentials=config.openai_credentials
- )
- config.smart_llm = check_model(
- config.smart_llm, "smart_llm", api_credentials=config.openai_credentials
- )
+ config.fast_llm = await check_model(config.fast_llm, "fast_llm")
+ config.smart_llm = await check_model(config.smart_llm, "smart_llm")
if memory_type:
supported_memory = get_supported_memory_backends()
@@ -183,19 +149,17 @@ def apply_overrides_to_config(
config.skip_news = True
-def check_model(
- model_name: str,
- model_type: Literal["smart_llm", "fast_llm"],
- api_credentials: OpenAICredentials,
-) -> str:
+async def check_model(
+ model_name: OpenAIModelName, model_type: Literal["smart_llm", "fast_llm"]
+) -> OpenAIModelName:
"""Check if model is available for use. If not, return gpt-3.5-turbo."""
- api_manager = ApiManager()
- models = api_manager.get_models(**api_credentials.get_api_access_kwargs(model_name))
+ openai = OpenAIProvider()
+ models = await openai.get_available_models()
- if any(model_name in m["id"] for m in models):
+ if any(model_name == m.name for m in models):
return model_name
logger.warning(
- f"You don't have access to {model_name}. Setting {model_type} to gpt-3.5-turbo."
+ f"You don't have access to {model_name}. Setting {model_type} to {GPT_3_MODEL}."
)
- return "gpt-3.5-turbo"
+ return GPT_3_MODEL
diff --git a/autogpts/autogpt/autogpt/app/main.py b/autogpts/autogpt/autogpt/app/main.py
index 290886c43..2ff737470 100644
--- a/autogpts/autogpt/autogpt/app/main.py
+++ b/autogpts/autogpt/autogpt/app/main.py
@@ -1,6 +1,7 @@
"""
The application entry point. Can be invoked by a CLI or any other front end application.
"""
+
import enum
import logging
import math
@@ -23,6 +24,11 @@ from autogpt.agent_factory.profile_generator import generate_agent_profile_for_t
from autogpt.agent_manager import AgentManager
from autogpt.agents import AgentThoughts, CommandArgs, CommandName
from autogpt.agents.utils.exceptions import AgentTerminated, InvalidAgentResponseError
+from autogpt.commands.execute_code import (
+ is_docker_available,
+ we_are_running_in_a_docker_container,
+)
+from autogpt.commands.system import finish
from autogpt.config import (
AIDirectives,
AIProfile,
@@ -32,8 +38,10 @@ from autogpt.config import (
)
from autogpt.core.resource.model_providers.openai import OpenAIProvider
from autogpt.core.runner.client_lib.utils import coroutine
+from autogpt.file_storage import FileStorageBackendName, get_storage
from autogpt.logs.config import configure_chat_plugins, configure_logging
from autogpt.logs.helpers import print_attribute, speak
+from autogpt.models.action_history import ActionInterruptedByHuman
from autogpt.plugins import scan_plugins
from scripts.install_plugin_deps import install_plugin_dependencies
@@ -76,23 +84,37 @@ async def run_auto_gpt(
best_practices: Optional[list[str]] = None,
override_directives: bool = False,
):
+ # Set up configuration
config = ConfigBuilder.build_config_from_env()
+ # Storage
+ local = config.file_storage_backend == FileStorageBackendName.LOCAL
+ restrict_to_root = not local or config.restrict_to_workspace
+ file_storage = get_storage(
+ config.file_storage_backend, root_path="data", restrict_to_root=restrict_to_root
+ )
+ file_storage.initialize()
+
+ # Set up logging module
+ if speak:
+ config.tts_config.speak_mode = True
+ configure_logging(
+ debug=debug,
+ level=log_level,
+ log_format=log_format,
+ log_file_format=log_file_format,
+ tts_config=config.tts_config,
+ )
# TODO: fill in llm values here
assert_config_has_openai_api_key(config)
- apply_overrides_to_config(
+ await apply_overrides_to_config(
config=config,
continuous=continuous,
continuous_limit=continuous_limit,
ai_settings_file=ai_settings,
prompt_settings_file=prompt_settings,
skip_reprompt=skip_reprompt,
- speak=speak,
- debug=debug,
- log_level=log_level,
- log_format=log_format,
- log_file_format=log_file_format,
gpt3only=gpt3only,
gpt4only=gpt4only,
browser_name=browser_name,
@@ -100,12 +122,6 @@ async def run_auto_gpt(
skip_news=skip_news,
)
- # Set up logging module
- configure_logging(
- **config.logging.dict(),
- tts_config=config.tts_config,
- )
-
llm_provider = _configure_openai_provider(config)
logger = logging.getLogger(__name__)
@@ -140,6 +156,14 @@ async def run_auto_gpt(
print_attribute("Using Prompt Settings File", prompt_settings)
if config.allow_downloads:
print_attribute("Native Downloading", "ENABLED")
+ if we_are_running_in_a_docker_container() or is_docker_available():
+ print_attribute("Code Execution", "ENABLED")
+ else:
+ print_attribute(
+ "Code Execution",
+ "DISABLED (Docker unavailable)",
+ title_color=Fore.YELLOW,
+ )
if install_plugin_deps:
install_plugin_dependencies()
@@ -148,7 +172,7 @@ async def run_auto_gpt(
configure_chat_plugins(config)
# Let user choose an existing agent to run
- agent_manager = AgentManager(config.app_data_dir)
+ agent_manager = AgentManager(file_storage)
existing_agents = agent_manager.list_agents()
load_existing_agent = ""
if existing_agents:
@@ -156,15 +180,23 @@ async def run_auto_gpt(
"Existing agents\n---------------\n"
+ "\n".join(f"{i} - {id}" for i, id in enumerate(existing_agents, 1))
)
- load_existing_agent = await clean_input(
+ load_existing_agent = clean_input(
config,
"Enter the number or name of the agent to run,"
" or hit enter to create a new one:",
)
- if re.match(r"^\d+$", load_existing_agent):
+ if re.match(r"^\d+$", load_existing_agent.strip()) and 0 < int(
+ load_existing_agent
+ ) <= len(existing_agents):
load_existing_agent = existing_agents[int(load_existing_agent) - 1]
- elif load_existing_agent and load_existing_agent not in existing_agents:
- raise ValueError(f"Unknown agent '{load_existing_agent}'")
+
+ if load_existing_agent not in existing_agents:
+ logger.info(
+ f"Unknown agent '{load_existing_agent}', "
+ f"creating a new one instead.",
+ extra={"color": Fore.YELLOW},
+ )
+ load_existing_agent = ""
# Either load existing or set up new agent state
agent = None
@@ -174,21 +206,20 @@ async def run_auto_gpt(
# Resume an Existing Agent #
############################
if load_existing_agent:
- agent_state = agent_manager.retrieve_state(load_existing_agent)
+ agent_state = None
while True:
- answer = await clean_input(config, "Resume? [Y/n]")
- if answer.lower() == "y":
+ answer = clean_input(config, "Resume? [Y/n]")
+ if answer == "" or answer.lower() == "y":
+ agent_state = agent_manager.load_agent_state(load_existing_agent)
break
elif answer.lower() == "n":
- agent_state = None
break
- else:
- print("Please respond with 'y' or 'n'")
if agent_state:
agent = configure_agent_with_state(
state=agent_state,
app_config=config,
+ file_storage=file_storage,
llm_provider=llm_provider,
)
apply_overrides_to_ai_settings(
@@ -202,6 +233,21 @@ async def run_auto_gpt(
replace_directives=override_directives,
)
+ if (
+ agent.event_history.current_episode
+ and agent.event_history.current_episode.action.name == finish.__name__
+ and not agent.event_history.current_episode.result
+ ):
+ # Agent was resumed after `finish` -> rewrite result of `finish` action
+ finish_reason = agent.event_history.current_episode.action.args["reason"]
+ print(f"Agent previously self-terminated; reason: '{finish_reason}'")
+ new_assignment = clean_input(
+ config, "Please give a follow-up question or assignment:"
+ )
+ agent.event_history.register_result(
+ ActionInterruptedByHuman(feedback=new_assignment)
+ )
+
# If any of these are specified as arguments,
# assume the user doesn't want to revise them
if not any(
@@ -225,11 +271,14 @@ async def run_auto_gpt(
# Set up a new Agent #
######################
if not agent:
- task = await clean_input(
- config,
- "Enter the task that you want AutoGPT to execute,"
- " with as much detail as possible:",
- )
+ task = ""
+ while task.strip() == "":
+ task = clean_input(
+ config,
+ "Enter the task that you want AutoGPT to execute,"
+ " with as much detail as possible:",
+ )
+
base_ai_directives = AIDirectives.from_file(config.prompt_settings_file)
ai_profile, task_oriented_ai_directives = await generate_agent_profile_for_task(
@@ -269,13 +318,14 @@ async def run_auto_gpt(
logger.info("AI config overrides specified through CLI; skipping revision")
agent = create_agent(
+ agent_id=agent_manager.generate_id(ai_profile.ai_name),
task=task,
ai_profile=ai_profile,
directives=ai_directives,
app_config=config,
+ file_storage=file_storage,
llm_provider=llm_provider,
)
- agent.attach_fs(agent_manager.get_agent_dir(agent.state.agent_id))
if not agent.config.allow_fs_access:
logger.info(
@@ -295,23 +345,13 @@ async def run_auto_gpt(
logger.info(f"Saving state of {agent_id}...")
# Allow user to Save As other ID
- save_as_id = (
- await clean_input(
- config,
- f"Press enter to save as '{agent_id}',"
- " or enter a different ID to save to:",
- )
- or agent_id
+ save_as_id = clean_input(
+ config,
+ f"Press enter to save as '{agent_id}',"
+ " or enter a different ID to save to:",
)
- if save_as_id and save_as_id != agent_id:
- agent.set_id(
- new_id=save_as_id,
- new_agent_dir=agent_manager.get_agent_dir(save_as_id),
- )
- # TODO: clone workspace if user wants that
- # TODO: ... OR allow many-to-one relations of agents and workspaces
-
- agent.state.save_to_json_file(agent.file_manager.state_file_path)
+ # TODO: allow many-to-one relations of agents and workspaces
+ await agent.save_state(save_as_id if not save_as_id.isspace() else None)
@coroutine
@@ -330,29 +370,35 @@ async def run_auto_gpt_server(
from .agent_protocol_server import AgentProtocolServer
config = ConfigBuilder.build_config_from_env()
+ # Storage
+ local = config.file_storage_backend == FileStorageBackendName.LOCAL
+ restrict_to_root = not local or config.restrict_to_workspace
+ file_storage = get_storage(
+ config.file_storage_backend, root_path="data", restrict_to_root=restrict_to_root
+ )
+ file_storage.initialize()
+
+ # Set up logging module
+ configure_logging(
+ debug=debug,
+ level=log_level,
+ log_format=log_format,
+ log_file_format=log_file_format,
+ tts_config=config.tts_config,
+ )
# TODO: fill in llm values here
assert_config_has_openai_api_key(config)
- apply_overrides_to_config(
+ await apply_overrides_to_config(
config=config,
prompt_settings_file=prompt_settings,
- debug=debug,
- log_level=log_level,
- log_format=log_format,
- log_file_format=log_file_format,
gpt3only=gpt3only,
gpt4only=gpt4only,
browser_name=browser_name,
allow_downloads=allow_downloads,
)
- # Set up logging module
- configure_logging(
- **config.logging.dict(),
- tts_config=config.tts_config,
- )
-
llm_provider = _configure_openai_provider(config)
if install_plugin_deps:
@@ -365,10 +411,19 @@ async def run_auto_gpt_server(
database_string=os.getenv("AP_SERVER_DB_URL", "sqlite:///data/ap_server.db"),
debug_enabled=debug,
)
+ port: int = int(os.getenv("AP_SERVER_PORT", default=8000))
server = AgentProtocolServer(
- app_config=config, database=database, llm_provider=llm_provider
+ app_config=config,
+ database=database,
+ file_storage=file_storage,
+ llm_provider=llm_provider,
+ )
+ await server.start(port=port)
+
+ logging.getLogger().info(
+ f"Total OpenAI session cost: "
+ f"${round(sum(b.total_cost for b in server._task_budgets.values()), 2)}"
)
- await server.start()
def _configure_openai_provider(config: Config) -> OpenAIProvider:
@@ -665,9 +720,9 @@ async def get_user_feedback(
while user_feedback is None:
# Get input from user
if config.chat_messages_enabled:
- console_input = await clean_input(config, "Waiting for your response...")
+ console_input = clean_input(config, "Waiting for your response...")
else:
- console_input = await clean_input(
+ console_input = clean_input(
config, Fore.MAGENTA + "Input:" + Style.RESET_ALL
)
diff --git a/autogpts/autogpt/autogpt/app/setup.py b/autogpts/autogpt/autogpt/app/setup.py
index 8a271d26f..94460e62f 100644
--- a/autogpts/autogpt/autogpt/app/setup.py
+++ b/autogpts/autogpt/autogpt/app/setup.py
@@ -69,44 +69,48 @@ async def interactively_revise_ai_settings(
)
if (
- await clean_input(app_config, "Continue with these settings? [Y/n]")
+ clean_input(app_config, "Continue with these settings? [Y/n]").lower()
or app_config.authorise_key
) == app_config.authorise_key:
break
# Ask for revised ai_profile
ai_profile.ai_name = (
- await clean_input(
- app_config, "Enter AI name (or press enter to keep current):"
- )
+ clean_input(app_config, "Enter AI name (or press enter to keep current):")
or ai_profile.ai_name
)
ai_profile.ai_role = (
- await clean_input(
+ clean_input(
app_config, "Enter new AI role (or press enter to keep current):"
)
or ai_profile.ai_role
)
# Revise constraints
- for i, constraint in enumerate(directives.constraints):
+ i = 0
+ while i < len(directives.constraints):
+ constraint = directives.constraints[i]
print_attribute(f"Constraint {i+1}:", f'"{constraint}"')
new_constraint = (
- await clean_input(
+ clean_input(
app_config,
f"Enter new constraint {i+1}"
" (press enter to keep current, or '-' to remove):",
)
or constraint
)
+
if new_constraint == "-":
directives.constraints.remove(constraint)
+ continue
elif new_constraint:
directives.constraints[i] = new_constraint
+ i += 1
+
# Add new constraints
while True:
- new_constraint = await clean_input(
+ new_constraint = clean_input(
app_config,
"Press enter to finish, or enter a constraint to add:",
)
@@ -115,10 +119,12 @@ async def interactively_revise_ai_settings(
directives.constraints.append(new_constraint)
# Revise resources
- for i, resource in enumerate(directives.resources):
+ i = 0
+ while i < len(directives.resources):
+ resource = directives.resources[i]
print_attribute(f"Resource {i+1}:", f'"{resource}"')
new_resource = (
- await clean_input(
+ clean_input(
app_config,
f"Enter new resource {i+1}"
" (press enter to keep current, or '-' to remove):",
@@ -127,12 +133,15 @@ async def interactively_revise_ai_settings(
)
if new_resource == "-":
directives.resources.remove(resource)
+ continue
elif new_resource:
directives.resources[i] = new_resource
+ i += 1
+
# Add new resources
while True:
- new_resource = await clean_input(
+ new_resource = clean_input(
app_config,
"Press enter to finish, or enter a resource to add:",
)
@@ -141,10 +150,12 @@ async def interactively_revise_ai_settings(
directives.resources.append(new_resource)
# Revise best practices
- for i, best_practice in enumerate(directives.best_practices):
+ i = 0
+ while i < len(directives.best_practices):
+ best_practice = directives.best_practices[i]
print_attribute(f"Best Practice {i+1}:", f'"{best_practice}"')
new_best_practice = (
- await clean_input(
+ clean_input(
app_config,
f"Enter new best practice {i+1}"
" (press enter to keep current, or '-' to remove):",
@@ -153,12 +164,15 @@ async def interactively_revise_ai_settings(
)
if new_best_practice == "-":
directives.best_practices.remove(best_practice)
+ continue
elif new_best_practice:
directives.best_practices[i] = new_best_practice
+ i += 1
+
# Add new best practices
while True:
- new_best_practice = await clean_input(
+ new_best_practice = clean_input(
app_config,
"Press enter to finish, or add a best practice to add:",
)
diff --git a/autogpts/autogpt/autogpt/app/telemetry.py b/autogpts/autogpt/autogpt/app/telemetry.py
new file mode 100644
index 000000000..9706781d7
--- /dev/null
+++ b/autogpts/autogpt/autogpt/app/telemetry.py
@@ -0,0 +1,64 @@
+import os
+
+import click
+from colorama import Fore, Style
+
+from .utils import (
+ env_file_exists,
+ get_git_user_email,
+ set_env_config_value,
+ vcs_state_diverges_from_master,
+)
+
+
+def setup_telemetry() -> None:
+ if os.getenv("TELEMETRY_OPT_IN") is None:
+ # If no .env file is present, don't bother asking to enable telemetry,
+ # to prevent repeated asking in non-persistent environments.
+ if not env_file_exists():
+ return
+
+ allow_telemetry = click.prompt(
+ f"""
+{Style.BRIGHT}❓ Do you want to enable telemetry? ❓{Style.NORMAL}
+This means AutoGPT will send diagnostic data to the core development team when something
+goes wrong, and will help us to diagnose and fix problems earlier and faster. It also
+allows us to collect basic performance data, which helps us find bottlenecks and other
+things that slow down the application.
+
+By entering 'yes', you confirm that you have read and agree to our Privacy Policy,
+which is available here:
+https://www.notion.so/auto-gpt/Privacy-Policy-ab11c9c20dbd4de1a15dcffe84d77984
+
+Please enter 'yes' or 'no'""",
+ type=bool,
+ )
+ set_env_config_value("TELEMETRY_OPT_IN", "true" if allow_telemetry else "false")
+ click.echo(
+ f"❤️ Thank you! Telemetry is {Fore.GREEN}enabled{Fore.RESET}."
+ if allow_telemetry
+ else f"👍 Telemetry is {Fore.RED}disabled{Fore.RESET}."
+ )
+ click.echo(
+ "💡 If you ever change your mind, you can change 'TELEMETRY_OPT_IN' in .env"
+ )
+ click.echo()
+
+ if os.getenv("TELEMETRY_OPT_IN", "").lower() == "true":
+ _setup_sentry()
+
+
+def _setup_sentry() -> None:
+ import sentry_sdk
+
+ sentry_sdk.init(
+ dsn="https://dc266f2f7a2381194d1c0fa36dff67d8@o4505260022104064.ingest.sentry.io/4506739844710400", # noqa
+ enable_tracing=True,
+ environment=os.getenv(
+ "TELEMETRY_ENVIRONMENT",
+ "production" if not vcs_state_diverges_from_master() else "dev",
+ ),
+ )
+
+ # Allow Sentry to distinguish between users
+ sentry_sdk.set_user({"email": get_git_user_email(), "ip_address": "{{auto}}"})
diff --git a/autogpts/autogpt/autogpt/app/utils.py b/autogpts/autogpt/autogpt/app/utils.py
index 6b21f180d..49a1e2a44 100644
--- a/autogpts/autogpt/autogpt/app/utils.py
+++ b/autogpts/autogpt/autogpt/app/utils.py
@@ -1,21 +1,24 @@
+import contextlib
import logging
import os
import re
+import socket
import sys
+from pathlib import Path
+from typing import TYPE_CHECKING
+import click
import requests
from colorama import Fore, Style
from git import InvalidGitRepositoryError, Repo
-from prompt_toolkit import ANSI, PromptSession
-from prompt_toolkit.history import InMemoryHistory
-from autogpt.config import Config
+if TYPE_CHECKING:
+ from autogpt.config import Config
logger = logging.getLogger(__name__)
-session = PromptSession(history=InMemoryHistory())
-async def clean_input(config: Config, prompt: str = ""):
+def clean_input(config: "Config", prompt: str = ""):
try:
if config.chat_messages_enabled:
for plugin in config.plugins:
@@ -48,11 +51,9 @@ async def clean_input(config: Config, prompt: str = ""):
# ask for input, default when just pressing Enter is y
logger.debug("Asking user via keyboard...")
- # handle_sigint must be set to False, so the signal handler in the
- # autogpt/main.py could be employed properly. This referes to
- # https://github.com/Significant-Gravitas/AutoGPT/pull/4799/files/3966cdfd694c2a80c0333823c3bc3da090f85ed3#r1264278776
- answer = await session.prompt_async(ANSI(prompt + " "), handle_sigint=False)
- return answer
+ return click.prompt(
+ text=prompt, prompt_suffix=" ", default="", show_default=False
+ )
except KeyboardInterrupt:
logger.info("You interrupted AutoGPT")
logger.info("Quitting...")
@@ -81,6 +82,58 @@ def get_current_git_branch() -> str:
return ""
+def vcs_state_diverges_from_master() -> bool:
+ """
+ Returns whether a git repo is present and contains changes that are not in `master`.
+ """
+ paths_we_care_about = "autogpts/autogpt/autogpt/**/*.py"
+ try:
+ repo = Repo(search_parent_directories=True)
+
+ # Check for uncommitted changes in the specified path
+ uncommitted_changes = repo.index.diff(None, paths=paths_we_care_about)
+ if uncommitted_changes:
+ return True
+
+ # Find OG AutoGPT remote
+ for remote in repo.remotes:
+ if remote.url.endswith(
+ tuple(
+ # All permutations of old/new repo name and HTTP(S)/Git URLs
+ f"{prefix}{path}"
+ for prefix in ("://github.com/", "git@github.com:")
+ for path in (
+ f"Significant-Gravitas/{n}.git" for n in ("AutoGPT", "Auto-GPT")
+ )
+ )
+ ):
+ og_remote = remote
+ break
+ else:
+ # Original AutoGPT remote is not configured: assume local codebase diverges
+ return True
+
+ master_branch = og_remote.refs.master
+ with contextlib.suppress(StopIteration):
+ next(repo.iter_commits(f"HEAD..{master_branch}", paths=paths_we_care_about))
+ # Local repo is one or more commits ahead of OG AutoGPT master branch
+ return True
+
+ # Relevant part of the codebase is on master
+ return False
+ except InvalidGitRepositoryError:
+ # No git repo present: assume codebase is a clean download
+ return False
+
+
+def get_git_user_email() -> str:
+ try:
+ repo = Repo(search_parent_directories=True)
+ return repo.config_reader().get_value("user", "email", default="")
+ except InvalidGitRepositoryError:
+ return ""
+
+
def get_latest_bulletin() -> tuple[str, bool]:
exists = os.path.exists("data/CURRENT_BULLETIN.md")
current_bulletin = ""
@@ -149,7 +202,7 @@ By using the System, you agree to indemnify, defend, and hold harmless the Proje
return legal_text
-def print_motd(config: Config, logger: logging.Logger):
+def print_motd(config: "Config", logger: logging.Logger):
motd, is_new_motd = get_latest_bulletin()
if motd:
motd = markdown_to_ansi_style(motd)
@@ -188,3 +241,40 @@ def print_python_version_info(logger: logging.Logger):
"parts of AutoGPT with this version. "
"Please consider upgrading to Python 3.10 or higher.",
)
+
+
+ENV_FILE_PATH = Path(__file__).parent.parent.parent / ".env"
+
+
+def env_file_exists() -> bool:
+ return ENV_FILE_PATH.is_file()
+
+
+def set_env_config_value(key: str, value: str) -> None:
+ """Sets the specified env variable and updates it in .env as well"""
+ os.environ[key] = value
+
+ with ENV_FILE_PATH.open("r+") as file:
+ lines = file.readlines()
+ file.seek(0)
+ key_already_in_file = False
+ for line in lines:
+ if re.match(rf"^(?:# )?{key}=.*$", line):
+ file.write(f"{key}={value}\n")
+ key_already_in_file = True
+ else:
+ file.write(line)
+
+ if not key_already_in_file:
+ file.write(f"{key}={value}\n")
+
+ file.truncate()
+
+
+def is_port_free(port: int, host: str = "127.0.0.1"):
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+ try:
+ s.bind((host, port)) # Try to bind to the port
+ return True # If successful, the port is free
+ except OSError:
+ return False # If failed, the port is likely in use
diff --git a/autogpts/autogpt/autogpt/command_decorator.py b/autogpts/autogpt/autogpt/command_decorator.py
index 70a519a42..f53c1ad85 100644
--- a/autogpts/autogpt/autogpt/command_decorator.py
+++ b/autogpts/autogpt/autogpt/command_decorator.py
@@ -25,7 +25,7 @@ def command(
enabled: Literal[True] | Callable[[Config], bool] = True,
disabled_reason: Optional[str] = None,
aliases: list[str] = [],
- available: Literal[True] | Callable[[BaseAgent], bool] = True,
+ available: bool | Callable[[BaseAgent], bool] = True,
) -> Callable[[Callable[P, CO]], Callable[P, CO]]:
"""
The command decorator is used to create Command objects from ordinary functions.
diff --git a/autogpts/autogpt/autogpt/commands/execute_code.py b/autogpts/autogpt/autogpt/commands/execute_code.py
index 93bfd53d4..a0ef57179 100644
--- a/autogpts/autogpt/autogpt/commands/execute_code.py
+++ b/autogpts/autogpt/autogpt/commands/execute_code.py
@@ -2,6 +2,7 @@
import logging
import os
+import shlex
import subprocess
from pathlib import Path
from tempfile import NamedTemporaryFile
@@ -33,6 +34,29 @@ ALLOWLIST_CONTROL = "allowlist"
DENYLIST_CONTROL = "denylist"
+def we_are_running_in_a_docker_container() -> bool:
+ """Check if we are running in a Docker container
+
+ Returns:
+ bool: True if we are running in a Docker container, False otherwise
+ """
+ return os.path.exists("/.dockerenv")
+
+
+def is_docker_available() -> bool:
+ """Check if Docker is available and supports Linux containers
+
+ Returns:
+ bool: True if Docker is available and supports Linux containers, False otherwise
+ """
+ try:
+ client = docker.from_env()
+ docker_info = client.info()
+ return docker_info["OSType"] == "linux"
+ except Exception:
+ return False
+
+
@command(
"execute_python_code",
"Executes the given Python code inside a single-use Docker container"
@@ -44,6 +68,10 @@ DENYLIST_CONTROL = "denylist"
required=True,
),
},
+ disabled_reason="To execute python code agent "
+ "must be running in a Docker container or "
+ "Docker must be available on the system.",
+ available=we_are_running_in_a_docker_container() or is_docker_available(),
)
def execute_python_code(code: str, agent: Agent) -> str:
"""
@@ -91,6 +119,10 @@ def execute_python_code(code: str, agent: Agent) -> str:
items=JSONSchema(type=JSONSchema.Type.STRING),
),
},
+ disabled_reason="To execute python code agent "
+ "must be running in a Docker container or "
+ "Docker must be available on the system.",
+ available=we_are_running_in_a_docker_container() or is_docker_available(),
)
@sanitize_path_arg("filename")
def execute_python_file(
@@ -224,25 +256,31 @@ def execute_python_file(
raise CommandExecutionError(f"Could not run the script in a container: {e}")
-def validate_command(command: str, config: Config) -> bool:
- """Validate a command to ensure it is allowed
+def validate_command(command_line: str, config: Config) -> tuple[bool, bool]:
+ """Check whether a command is allowed and whether it may be executed in a shell.
+
+ If shell command control is enabled, we disallow executing in a shell, because
+ otherwise the model could easily circumvent the command filter using shell features.
Args:
- command (str): The command to validate
- config (Config): The config to use to validate the command
+ command_line (str): The command line to validate
+ config (Config): The application config including shell command control settings
Returns:
bool: True if the command is allowed, False otherwise
+ bool: True if the command may be executed in a shell, False otherwise
"""
- if not command:
- return False
+ if not command_line:
+ return False, False
- command_name = command.split()[0]
+ command_name = shlex.split(command_line)[0]
if config.shell_command_control == ALLOWLIST_CONTROL:
- return command_name in config.shell_allowlist
+ return command_name in config.shell_allowlist, False
+ elif config.shell_command_control == DENYLIST_CONTROL:
+ return command_name not in config.shell_denylist, False
else:
- return command_name not in config.shell_denylist
+ return True, True
@command(
@@ -269,7 +307,8 @@ def execute_shell(command_line: str, agent: Agent) -> str:
Returns:
str: The output of the command
"""
- if not validate_command(command_line, agent.legacy_config):
+ allow_execute, allow_shell = validate_command(command_line, agent.legacy_config)
+ if not allow_execute:
logger.info(f"Command '{command_line}' not allowed")
raise OperationNotAllowedError("This shell command is not allowed.")
@@ -282,7 +321,11 @@ def execute_shell(command_line: str, agent: Agent) -> str:
f"Executing command '{command_line}' in working directory '{os.getcwd()}'"
)
- result = subprocess.run(command_line, capture_output=True, shell=True)
+ result = subprocess.run(
+ command_line if allow_shell else shlex.split(command_line),
+ capture_output=True,
+ shell=allow_shell,
+ )
output = f"STDOUT:\n{result.stdout.decode()}\nSTDERR:\n{result.stderr.decode()}"
# Change back to whatever the prior working dir was
@@ -316,7 +359,8 @@ def execute_shell_popen(command_line: str, agent: Agent) -> str:
Returns:
str: Description of the fact that the process started and its id
"""
- if not validate_command(command_line, agent.legacy_config):
+ allow_execute, allow_shell = validate_command(command_line, agent.legacy_config)
+ if not allow_execute:
logger.info(f"Command '{command_line}' not allowed")
raise OperationNotAllowedError("This shell command is not allowed.")
@@ -331,19 +375,13 @@ def execute_shell_popen(command_line: str, agent: Agent) -> str:
do_not_show_output = subprocess.DEVNULL
process = subprocess.Popen(
- command_line, shell=True, stdout=do_not_show_output, stderr=do_not_show_output
+ command_line if allow_shell else shlex.split(command_line),
+ shell=allow_shell,
+ stdout=do_not_show_output,
+ stderr=do_not_show_output,
)
# Change back to whatever the prior working dir was
os.chdir(current_dir)
return f"Subprocess started with PID:'{str(process.pid)}'"
-
-
-def we_are_running_in_a_docker_container() -> bool:
- """Check if we are running in a Docker container
-
- Returns:
- bool: True if we are running in a Docker container, False otherwise
- """
- return os.path.exists("/.dockerenv")
diff --git a/autogpts/autogpt/autogpt/commands/file_operations.py b/autogpts/autogpt/autogpt/commands/file_operations.py
index 9d70b3874..55149216f 100644
--- a/autogpts/autogpt/autogpt/commands/file_operations.py
+++ b/autogpts/autogpt/autogpt/commands/file_operations.py
@@ -35,17 +35,12 @@ def text_checksum(text: str) -> str:
def operations_from_log(
- log_path: str | Path,
+ logs: list[str],
) -> Iterator[
tuple[Literal["write", "append"], str, str] | tuple[Literal["delete"], str, None]
]:
- """Parse the file operations log and return a tuple containing the log entries"""
- try:
- log = open(log_path, "r", encoding="utf-8")
- except FileNotFoundError:
- return
-
- for line in log:
+ """Parse logs and return a tuple containing the log entries"""
+ for line in logs:
line = line.replace("File Operation Logger", "").strip()
if not line:
continue
@@ -57,14 +52,12 @@ def operations_from_log(
elif operation == "delete":
yield (operation, tail.strip(), None)
- log.close()
-
-def file_operations_state(log_path: str | Path) -> dict[str, str]:
- """Iterates over the operations log and returns the expected state.
+def file_operations_state(logs: list[str]) -> dict[str, str]:
+ """Iterates over the operations and returns the expected state.
- Parses a log file at file_manager.file_ops_log_path to construct a dictionary
- that maps each file path written or appended to its checksum. Deleted files are
+ Constructs a dictionary that maps each file path written
+ or appended to its checksum. Deleted files are
removed from the dictionary.
Returns:
@@ -75,7 +68,7 @@ def file_operations_state(log_path: str | Path) -> dict[str, str]:
ValueError: If the log file content is not in the expected format.
"""
state = {}
- for operation, path, checksum in operations_from_log(log_path):
+ for operation, path, checksum in operations_from_log(logs):
if operation in ("write", "append"):
state[path] = checksum
elif operation == "delete":
@@ -98,16 +91,16 @@ def is_duplicate_operation(
Returns:
True if the operation has already been performed on the file
"""
- state = file_operations_state(agent.file_manager.file_ops_log_path)
- if operation == "delete" and str(file_path) not in state:
+ state = file_operations_state(agent.get_file_operation_lines())
+ if operation == "delete" and file_path.as_posix() not in state:
return True
- if operation == "write" and state.get(str(file_path)) == checksum:
+ if operation == "write" and state.get(file_path.as_posix()) == checksum:
return True
return False
@sanitize_path_arg("file_path", make_relative=True)
-def log_operation(
+async def log_operation(
operation: Operation,
file_path: str | Path,
agent: Agent,
@@ -120,13 +113,14 @@ def log_operation(
file_path: The name of the file the operation was performed on
checksum: The checksum of the contents to be written
"""
- log_entry = f"{operation}: {file_path}"
+ log_entry = (
+ f"{operation}: "
+ f"{file_path.as_posix() if isinstance(file_path, Path) else file_path}"
+ )
if checksum is not None:
log_entry += f" #{checksum}"
logger.debug(f"Logging file operation: {log_entry}")
- append_to_file(
- agent.file_manager.file_ops_log_path, f"{log_entry}\n", agent, should_log=False
- )
+ await agent.log_file_operation(log_entry)
@command(
@@ -150,7 +144,7 @@ def read_file(filename: str | Path, agent: Agent) -> str:
str: The contents of the file
"""
file = agent.workspace.open_file(filename, binary=True)
- content = decode_textual_file(file, logger)
+ content = decode_textual_file(file, os.path.splitext(filename)[1], logger)
# # TODO: invalidate/update memory when file is edited
# file_memory = MemoryItem.from_text_file(content, str(filename), agent.config)
@@ -218,33 +212,12 @@ async def write_to_file(filename: str | Path, contents: str, agent: Agent) -> st
raise DuplicateOperationError(f"File {filename} has already been updated.")
if directory := os.path.dirname(filename):
- agent.workspace.get_path(directory).mkdir(exist_ok=True)
+ agent.workspace.make_dir(directory)
await agent.workspace.write_file(filename, contents)
- log_operation("write", filename, agent, checksum)
+ await log_operation("write", filename, agent, checksum)
return f"File {filename} has been written successfully."
-def append_to_file(
- filename: Path, text: str, agent: Agent, should_log: bool = True
-) -> None:
- """Append text to a file
-
- Args:
- filename (Path): The name of the file to append to
- text (str): The text to append to the file
- should_log (bool): Should log output
- """
- directory = os.path.dirname(filename)
- os.makedirs(directory, exist_ok=True)
- with open(filename, "a") as f:
- f.write(text)
-
- if should_log:
- with open(filename, "r") as f:
- checksum = text_checksum(f.read())
- log_operation("append", filename, agent, checksum=checksum)
-
-
@command(
"list_folder",
"List the items in a folder",
@@ -265,4 +238,4 @@ def list_folder(folder: str | Path, agent: Agent) -> list[str]:
Returns:
list[str]: A list of files found in the folder
"""
- return [str(p) for p in agent.workspace.list(folder)]
+ return [str(p) for p in agent.workspace.list_files(folder)]
diff --git a/autogpts/autogpt/autogpt/commands/file_operations_utils.py b/autogpts/autogpt/autogpt/commands/file_operations_utils.py
index e7c001e93..e9dcae41b 100644
--- a/autogpts/autogpt/autogpt/commands/file_operations_utils.py
+++ b/autogpts/autogpt/autogpt/commands/file_operations_utils.py
@@ -1,6 +1,5 @@
import json
import logging
-import os
from abc import ABC, abstractmethod
from typing import BinaryIO
@@ -24,7 +23,10 @@ class ParserStrategy(ABC):
class TXTParser(ParserStrategy):
def read(self, file: BinaryIO) -> str:
charset_match = charset_normalizer.from_bytes(file.read()).best()
- logger.debug(f"Reading '{file.name}' with encoding '{charset_match.encoding}'")
+ logger.debug(
+ f"Reading {getattr(file, 'name', 'file')} "
+ f"with encoding '{charset_match.encoding}'"
+ )
return str(charset_match)
@@ -66,7 +68,7 @@ class XMLParser(ParserStrategy):
# Reading as dictionary and returning string format
class YAMLParser(ParserStrategy):
def read(self, file: BinaryIO) -> str:
- data = yaml.load(file, Loader=yaml.FullLoader)
+ data = yaml.load(file, Loader=yaml.SafeLoader)
text = str(data)
return text
@@ -95,7 +97,9 @@ class FileContext:
self.parser = parser
def decode_file(self, file: BinaryIO) -> str:
- self.logger.debug(f"Reading file {file.name} with parser {self.parser}")
+ self.logger.debug(
+ f"Reading {getattr(file, 'name', 'file')} with parser {self.parser}"
+ )
return self.parser.read(file)
@@ -133,15 +137,14 @@ def is_file_binary_fn(file: BinaryIO):
return False
-def decode_textual_file(file: BinaryIO, logger: logging.Logger) -> str:
+def decode_textual_file(file: BinaryIO, ext: str, logger: logging.Logger) -> str:
if not file.readable():
- raise ValueError(f"read_file failed: {file.name} is not a file")
+ raise ValueError(f"{repr(file)} is not readable")
- file_extension = os.path.splitext(file.name)[1].lower()
- parser = extension_to_parser.get(file_extension)
+ parser = extension_to_parser.get(ext.lower())
if not parser:
if is_file_binary_fn(file):
- raise ValueError(f"Unsupported binary file format: {file_extension}")
+ raise ValueError(f"Unsupported binary file format: {ext}")
# fallback to txt file parser (to support script and code files loading)
parser = TXTParser()
file_context = FileContext(parser, logger)
diff --git a/autogpts/autogpt/autogpt/commands/image_gen.py b/autogpts/autogpt/autogpt/commands/image_gen.py
index 490557b04..957c2ac5a 100644
--- a/autogpts/autogpt/autogpt/commands/image_gen.py
+++ b/autogpts/autogpt/autogpt/commands/image_gen.py
@@ -8,8 +8,8 @@ import uuid
from base64 import b64decode
from pathlib import Path
-import openai
import requests
+from openai import OpenAI
from PIL import Image
from autogpt.agents.agent import Agent
@@ -142,17 +142,18 @@ def generate_image_with_dalle(
)
size = closest
- response = openai.Image.create(
+ response = OpenAI(
+ api_key=agent.legacy_config.openai_credentials.api_key.get_secret_value()
+ ).images.generate(
prompt=prompt,
n=1,
size=f"{size}x{size}",
response_format="b64_json",
- api_key=agent.legacy_config.openai_credentials.api_key.get_secret_value(),
)
logger.info(f"Image Generated for prompt:{prompt}")
- image_data = b64decode(response["data"][0]["b64_json"])
+ image_data = b64decode(response.data[0].b64_json)
with open(output_file, mode="wb") as png:
png.write(image_data)
diff --git a/autogpts/autogpt/autogpt/commands/system.py b/autogpts/autogpt/autogpt/commands/system.py
index bd184122f..2d547bd08 100644
--- a/autogpts/autogpt/autogpt/commands/system.py
+++ b/autogpts/autogpt/autogpt/commands/system.py
@@ -6,7 +6,7 @@ import logging
from typing import TYPE_CHECKING
from autogpt.agents.features.context import get_agent_context
-from autogpt.agents.utils.exceptions import AgentTerminated, InvalidArgumentError
+from autogpt.agents.utils.exceptions import AgentFinished, InvalidArgumentError
from autogpt.command_decorator import command
from autogpt.core.utils.json_schema import JSONSchema
@@ -44,7 +44,7 @@ def finish(reason: str, agent: Agent) -> None:
A result string from create chat completion. A list of suggestions to
improve the code.
"""
- raise AgentTerminated(reason)
+ raise AgentFinished(reason)
@command(
diff --git a/autogpts/autogpt/autogpt/commands/user_interaction.py b/autogpts/autogpt/autogpt/commands/user_interaction.py
index c53213c7f..bd4dd639c 100644
--- a/autogpts/autogpt/autogpt/commands/user_interaction.py
+++ b/autogpts/autogpt/autogpt/commands/user_interaction.py
@@ -28,5 +28,5 @@ COMMAND_CATEGORY_TITLE = "User Interaction"
)
async def ask_user(question: str, agent: Agent) -> str:
print(f"\nQ: {question}")
- resp = await clean_input(agent.legacy_config, "A:")
+ resp = clean_input(agent.legacy_config, "A:")
return f"The user's answer: '{resp}'"
diff --git a/autogpts/autogpt/autogpt/commands/web_search.py b/autogpts/autogpt/autogpt/commands/web_search.py
index e39bfffc6..dfcb38b3f 100644
--- a/autogpts/autogpt/autogpt/commands/web_search.py
+++ b/autogpts/autogpt/autogpt/commands/web_search.py
@@ -4,7 +4,6 @@ from __future__ import annotations
import json
import time
-from itertools import islice
from duckduckgo_search import DDGS
@@ -49,8 +48,7 @@ def web_search(query: str, agent: Agent, num_results: int = 8) -> str:
if not query:
return json.dumps(search_results)
- results = DDGS().text(query)
- search_results = list(islice(results, num_results))
+ search_results = DDGS().text(query, max_results=num_results)
if search_results:
break
diff --git a/autogpts/autogpt/autogpt/commands/web_selenium.py b/autogpts/autogpt/autogpt/commands/web_selenium.py
index 57f650fb9..59adb61b4 100644
--- a/autogpts/autogpt/autogpt/commands/web_selenium.py
+++ b/autogpts/autogpt/autogpt/commands/web_selenium.py
@@ -2,11 +2,13 @@
from __future__ import annotations
+import asyncio
import logging
import re
from pathlib import Path
from sys import platform
from typing import TYPE_CHECKING, Optional, Type
+from urllib.request import urlretrieve
from bs4 import BeautifulSoup
from selenium.common.exceptions import WebDriverException
@@ -30,11 +32,11 @@ from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.firefox import GeckoDriverManager
from webdriver_manager.microsoft import EdgeChromiumDriverManager as EdgeDriverManager
-from autogpt.agents.utils.exceptions import CommandExecutionError
+from autogpt.agents.utils.exceptions import CommandExecutionError, TooMuchOutputError
from autogpt.command_decorator import command
from autogpt.core.utils.json_schema import JSONSchema
from autogpt.processing.html import extract_hyperlinks, format_hyperlinks
-from autogpt.processing.text import summarize_text
+from autogpt.processing.text import extract_information, summarize_text
from autogpt.url_utils.validators import validate_url
COMMAND_CATEGORY = "web_browse"
@@ -49,7 +51,7 @@ if TYPE_CHECKING:
logger = logging.getLogger(__name__)
FILE_DIR = Path(__file__).parent.parent
-TOKENS_TO_TRIGGER_SUMMARY = 50
+MAX_RAW_CONTENT_LENGTH = 500
LINKS_TO_RETURN = 20
@@ -60,10 +62,8 @@ class BrowsingError(CommandExecutionError):
@command(
"read_webpage",
(
- "Read a webpage, and extract specific information from it"
- " if a question is specified."
- " If you are looking to extract specific information from the webpage,"
- " you should specify a question."
+ "Read a webpage, and extract specific information from it."
+ " You must specify either topics_of_interest, a question, or get_raw_content."
),
{
"url": JSONSchema(
@@ -71,6 +71,15 @@ class BrowsingError(CommandExecutionError):
description="The URL to visit",
required=True,
),
+ "topics_of_interest": JSONSchema(
+ type=JSONSchema.Type.ARRAY,
+ items=JSONSchema(type=JSONSchema.Type.STRING),
+ description=(
+ "A list of topics about which you want to extract information "
+ "from the page."
+ ),
+ required=False,
+ ),
"question": JSONSchema(
type=JSONSchema.Type.STRING,
description=(
@@ -78,10 +87,25 @@ class BrowsingError(CommandExecutionError):
),
required=False,
),
+ "get_raw_content": JSONSchema(
+ type=JSONSchema.Type.BOOLEAN,
+ description=(
+ "If true, the unprocessed content of the webpage will be returned. "
+ "This consumes a lot of tokens, so use it with caution."
+ ),
+ required=False,
+ ),
},
)
@validate_url
-async def read_webpage(url: str, agent: Agent, question: str = "") -> str:
+async def read_webpage(
+ url: str,
+ agent: Agent,
+ *,
+ topics_of_interest: list[str] = [],
+ get_raw_content: bool = False,
+ question: str = "",
+) -> str:
"""Browse a website and return the answer and links to the user
Args:
@@ -93,8 +117,7 @@ async def read_webpage(url: str, agent: Agent, question: str = "") -> str:
"""
driver = None
try:
- # FIXME: agent.config -> something else
- driver = open_page_in_browser(url, agent.legacy_config)
+ driver = await open_page_in_browser(url, agent.legacy_config)
text = scrape_text_with_selenium(driver)
links = scrape_links_with_selenium(driver, url)
@@ -103,12 +126,19 @@ async def read_webpage(url: str, agent: Agent, question: str = "") -> str:
summarized = False
if not text:
return f"Website did not contain any text.\n\nLinks: {links}"
- elif (
- agent.llm_provider.count_tokens(text, agent.llm.name)
- > TOKENS_TO_TRIGGER_SUMMARY
- ):
+ elif get_raw_content:
+ if (
+ output_tokens := agent.llm_provider.count_tokens(text, agent.llm.name)
+ ) > MAX_RAW_CONTENT_LENGTH:
+ oversize_factor = round(output_tokens / MAX_RAW_CONTENT_LENGTH, 1)
+ raise TooMuchOutputError(
+ f"Page content is {oversize_factor}x the allowed length "
+ "for `get_raw_content=true`"
+ )
+ return text + (f"\n\nLinks: {links}" if links else "")
+ else:
text = await summarize_memorize_webpage(
- url, text, question or None, agent, driver
+ url, text, question or None, topics_of_interest, agent, driver
)
return_literal_content = bool(question)
summarized = True
@@ -185,7 +215,7 @@ def scrape_links_with_selenium(driver: WebDriver, base_url: str) -> list[str]:
return format_hyperlinks(hyperlinks)
-def open_page_in_browser(url: str, config: Config) -> WebDriver:
+async def open_page_in_browser(url: str, config: Config) -> WebDriver:
"""Open a browser window and load a web page using Selenium
Params:
@@ -207,22 +237,22 @@ def open_page_in_browser(url: str, config: Config) -> WebDriver:
options: BrowserOptions = options_available[config.selenium_web_browser]()
options.add_argument(f"user-agent={config.user_agent}")
- if config.selenium_web_browser == "firefox":
+ if isinstance(options, FirefoxOptions):
if config.selenium_headless:
options.headless = True
options.add_argument("--disable-gpu")
driver = FirefoxDriver(
service=GeckoDriverService(GeckoDriverManager().install()), options=options
)
- elif config.selenium_web_browser == "edge":
+ elif isinstance(options, EdgeOptions):
driver = EdgeDriver(
service=EdgeDriverService(EdgeDriverManager().install()), options=options
)
- elif config.selenium_web_browser == "safari":
+ elif isinstance(options, SafariOptions):
# Requires a bit more setup on the users end.
# See https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari # noqa: E501
driver = SafariDriver(options=options)
- else:
+ elif isinstance(options, ChromeOptions):
if platform == "linux" or platform == "linux2":
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--remote-debugging-port=9222")
@@ -232,16 +262,31 @@ def open_page_in_browser(url: str, config: Config) -> WebDriver:
options.add_argument("--headless=new")
options.add_argument("--disable-gpu")
- chromium_driver_path = Path("/usr/bin/chromedriver")
+ _sideload_chrome_extensions(options, config.app_data_dir / "assets" / "crx")
+
+ if (chromium_driver_path := Path("/usr/bin/chromedriver")).exists():
+ chrome_service = ChromeDriverService(str(chromium_driver_path))
+ else:
+ try:
+ chrome_driver = ChromeDriverManager().install()
+ except AttributeError as e:
+ if "'NoneType' object has no attribute 'split'" in str(e):
+ # https://github.com/SergeyPirogov/webdriver_manager/issues/649
+ logger.critical(
+ "Connecting to browser failed: is Chrome or Chromium installed?"
+ )
+ raise
+ chrome_service = ChromeDriverService(chrome_driver)
+ driver = ChromeDriver(service=chrome_service, options=options)
- driver = ChromeDriver(
- service=ChromeDriverService(str(chromium_driver_path))
- if chromium_driver_path.exists()
- else ChromeDriverService(ChromeDriverManager().install()),
- options=options,
- )
driver.get(url)
+ # Wait for page to be ready, sleep 2 seconds, wait again until page ready.
+ # This allows the cookiewall squasher time to get rid of cookie walls.
+ WebDriverWait(driver, 10).until(
+ EC.presence_of_element_located((By.TAG_NAME, "body"))
+ )
+ await asyncio.sleep(2)
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.TAG_NAME, "body"))
)
@@ -249,6 +294,24 @@ def open_page_in_browser(url: str, config: Config) -> WebDriver:
return driver
+def _sideload_chrome_extensions(options: ChromeOptions, dl_folder: Path) -> None:
+ crx_download_url_template = "https://clients2.google.com/service/update2/crx?response=redirect&prodversion=49.0&acceptformat=crx3&x=id%3D{crx_id}%26installsource%3Dondemand%26uc" # noqa
+ cookiewall_squasher_crx_id = "edibdbjcniadpccecjdfdjjppcpchdlm"
+ adblocker_crx_id = "cjpalhdlnbpafiamejdnhcphjbkeiagm"
+
+ # Make sure the target folder exists
+ dl_folder.mkdir(parents=True, exist_ok=True)
+
+ for crx_id in (cookiewall_squasher_crx_id, adblocker_crx_id):
+ crx_path = dl_folder / f"{crx_id}.crx"
+ if not crx_path.exists():
+ logger.debug(f"Downloading CRX {crx_id}...")
+ crx_download_url = crx_download_url_template.format(crx_id=crx_id)
+ urlretrieve(crx_download_url, crx_path)
+ logger.debug(f"Downloaded {crx_path.name}")
+ options.add_extension(str(crx_path))
+
+
def close_browser(driver: WebDriver) -> None:
"""Close the browser
@@ -265,6 +328,7 @@ async def summarize_memorize_webpage(
url: str,
text: str,
question: str | None,
+ topics_of_interest: list[str],
agent: Agent,
driver: Optional[WebDriver] = None,
) -> str:
@@ -283,7 +347,7 @@ async def summarize_memorize_webpage(
raise ValueError("No text to summarize")
text_length = len(text)
- logger.info(f"Text length: {text_length} characters")
+ logger.debug(f"Web page content length: {text_length} characters")
# memory = get_memory(agent.legacy_config)
@@ -295,10 +359,21 @@ async def summarize_memorize_webpage(
# )
# memory.add(new_memory)
- summary, _ = await summarize_text(
- text,
- question=question,
- llm_provider=agent.llm_provider,
- config=agent.legacy_config, # FIXME
- )
- return summary
+ result = None
+ information = None
+ if topics_of_interest:
+ information = await extract_information(
+ text,
+ topics_of_interest=topics_of_interest,
+ llm_provider=agent.llm_provider,
+ config=agent.legacy_config,
+ )
+ return "\n".join(f"* {i}" for i in information)
+ else:
+ result, _ = await summarize_text(
+ text,
+ question=question,
+ llm_provider=agent.llm_provider,
+ config=agent.legacy_config,
+ )
+ return result
diff --git a/autogpts/autogpt/autogpt/config/ai_directives.py b/autogpts/autogpt/autogpt/config/ai_directives.py
index 6b5aa4375..5e2957ef3 100644
--- a/autogpts/autogpt/autogpt/config/ai_directives.py
+++ b/autogpts/autogpt/autogpt/config/ai_directives.py
@@ -32,7 +32,7 @@ class AIDirectives(BaseModel):
raise RuntimeError(f"File validation failed: {message}")
with open(prompt_settings_file, encoding="utf-8") as file:
- config_params = yaml.load(file, Loader=yaml.FullLoader)
+ config_params = yaml.load(file, Loader=yaml.SafeLoader)
return AIDirectives(
constraints=config_params.get("constraints", []),
diff --git a/autogpts/autogpt/autogpt/config/ai_profile.py b/autogpts/autogpt/autogpt/config/ai_profile.py
index 970f8278c..3f0043c79 100644
--- a/autogpts/autogpt/autogpt/config/ai_profile.py
+++ b/autogpts/autogpt/autogpt/config/ai_profile.py
@@ -35,7 +35,7 @@ class AIProfile(BaseModel):
try:
with open(ai_settings_file, encoding="utf-8") as file:
- config_params = yaml.load(file, Loader=yaml.FullLoader) or {}
+ config_params = yaml.load(file, Loader=yaml.SafeLoader) or {}
except FileNotFoundError:
config_params = {}
diff --git a/autogpts/autogpt/autogpt/config/config.py b/autogpts/autogpt/autogpt/config/config.py
index ff0053a76..409a4256c 100644
--- a/autogpts/autogpt/autogpt/config/config.py
+++ b/autogpts/autogpt/autogpt/config/config.py
@@ -1,6 +1,7 @@
"""Configuration class to store the state of bools for different scripts access."""
from __future__ import annotations
+import logging
import os
import re
from pathlib import Path
@@ -11,6 +12,7 @@ from colorama import Fore
from pydantic import Field, SecretStr, validator
import autogpt
+from autogpt.app.utils import clean_input
from autogpt.core.configuration.schema import (
Configurable,
SystemSettings,
@@ -19,20 +21,22 @@ from autogpt.core.configuration.schema import (
from autogpt.core.resource.model_providers.openai import (
OPEN_AI_CHAT_MODELS,
OpenAICredentials,
+ OpenAIModelName,
)
-from autogpt.file_workspace import FileWorkspaceBackendName
-from autogpt.logs.config import LoggingConfig
+from autogpt.file_storage import FileStorageBackendName
from autogpt.plugins.plugins_config import PluginsConfig
from autogpt.speech import TTSConfig
+logger = logging.getLogger(__name__)
+
PROJECT_ROOT = Path(autogpt.__file__).parent.parent
AI_SETTINGS_FILE = Path("ai_settings.yaml")
AZURE_CONFIG_FILE = Path("azure.yaml")
PLUGINS_CONFIG_FILE = Path("plugins_config.yaml")
PROMPT_SETTINGS_FILE = Path("prompt_settings.yaml")
-GPT_4_MODEL = "gpt-4"
-GPT_3_MODEL = "gpt-3.5-turbo"
+GPT_4_MODEL = OpenAIModelName.GPT4
+GPT_3_MODEL = OpenAIModelName.GPT3
class Config(SystemSettings, arbitrary_types_allowed=True):
@@ -55,14 +59,10 @@ class Config(SystemSettings, arbitrary_types_allowed=True):
# TTS configuration
tts_config: TTSConfig = TTSConfig()
- logging: LoggingConfig = LoggingConfig()
-
- # Workspace
- workspace_backend: FileWorkspaceBackendName = UserConfigurable(
- default=FileWorkspaceBackendName.LOCAL,
- from_env=lambda: FileWorkspaceBackendName(v)
- if (v := os.getenv("WORKSPACE_BACKEND"))
- else None,
+
+ # File storage
+ file_storage_backend: FileStorageBackendName = UserConfigurable(
+ default=FileStorageBackendName.LOCAL, from_env="FILE_STORAGE_BACKEND"
)
##########################
@@ -70,32 +70,28 @@ class Config(SystemSettings, arbitrary_types_allowed=True):
##########################
# Paths
ai_settings_file: Path = UserConfigurable(
- default=AI_SETTINGS_FILE,
- from_env=lambda: Path(f) if (f := os.getenv("AI_SETTINGS_FILE")) else None,
+ default=AI_SETTINGS_FILE, from_env="AI_SETTINGS_FILE"
)
prompt_settings_file: Path = UserConfigurable(
default=PROMPT_SETTINGS_FILE,
- from_env=lambda: Path(f) if (f := os.getenv("PROMPT_SETTINGS_FILE")) else None,
+ from_env="PROMPT_SETTINGS_FILE",
)
# Model configuration
- fast_llm: str = UserConfigurable(
- default="gpt-3.5-turbo-16k",
- from_env=lambda: os.getenv("FAST_LLM"),
- )
- smart_llm: str = UserConfigurable(
- default="gpt-4",
- from_env=lambda: os.getenv("SMART_LLM"),
+ fast_llm: OpenAIModelName = UserConfigurable(
+ default=OpenAIModelName.GPT3,
+ from_env="FAST_LLM",
)
- temperature: float = UserConfigurable(
- default=0,
- from_env=lambda: float(v) if (v := os.getenv("TEMPERATURE")) else None,
+ smart_llm: OpenAIModelName = UserConfigurable(
+ default=OpenAIModelName.GPT4_TURBO,
+ from_env="SMART_LLM",
)
+ temperature: float = UserConfigurable(default=0, from_env="TEMPERATURE")
openai_functions: bool = UserConfigurable(
default=False, from_env=lambda: os.getenv("OPENAI_FUNCTIONS", "False") == "True"
)
embedding_model: str = UserConfigurable(
- default="text-embedding-ada-002", from_env="EMBEDDING_MODEL"
+ default="text-embedding-3-small", from_env="EMBEDDING_MODEL"
)
browse_spacy_language_model: str = UserConfigurable(
default="en_core_web_sm", from_env="BROWSE_SPACY_LANGUAGE_MODEL"
@@ -111,10 +107,7 @@ class Config(SystemSettings, arbitrary_types_allowed=True):
memory_backend: str = UserConfigurable("json_file", from_env="MEMORY_BACKEND")
memory_index: str = UserConfigurable("auto-gpt-memory", from_env="MEMORY_INDEX")
redis_host: str = UserConfigurable("localhost", from_env="REDIS_HOST")
- redis_port: int = UserConfigurable(
- default=6379,
- from_env=lambda: int(v) if (v := os.getenv("REDIS_PORT")) else None,
- )
+ redis_port: int = UserConfigurable(default=6379, from_env="REDIS_PORT")
redis_password: str = UserConfigurable("", from_env="REDIS_PASSWORD")
wipe_redis_on_start: bool = UserConfigurable(
default=True,
@@ -166,10 +159,7 @@ class Config(SystemSettings, arbitrary_types_allowed=True):
sd_webui_url: Optional[str] = UserConfigurable(
default="http://localhost:7860", from_env="SD_WEBUI_URL"
)
- image_size: int = UserConfigurable(
- default=256,
- from_env=lambda: int(v) if (v := os.getenv("IMAGE_SIZE")) else None,
- )
+ image_size: int = UserConfigurable(default=256, from_env="IMAGE_SIZE")
# Audio to text
audio_to_text_provider: str = UserConfigurable(
@@ -194,8 +184,7 @@ class Config(SystemSettings, arbitrary_types_allowed=True):
###################
plugins_dir: str = UserConfigurable("plugins", from_env="PLUGINS_DIR")
plugins_config_file: Path = UserConfigurable(
- default=PLUGINS_CONFIG_FILE,
- from_env=lambda: Path(f) if (f := os.getenv("PLUGINS_CONFIG_FILE")) else None,
+ default=PLUGINS_CONFIG_FILE, from_env="PLUGINS_CONFIG_FILE"
)
plugins_config: PluginsConfig = Field(
default_factory=lambda: PluginsConfig(plugins={})
@@ -219,8 +208,7 @@ class Config(SystemSettings, arbitrary_types_allowed=True):
# OpenAI
openai_credentials: Optional[OpenAICredentials] = None
azure_config_file: Optional[Path] = UserConfigurable(
- default=AZURE_CONFIG_FILE,
- from_env=lambda: Path(f) if (f := os.getenv("AZURE_CONFIG_FILE")) else None,
+ default=AZURE_CONFIG_FILE, from_env="AZURE_CONFIG_FILE"
)
# Github
@@ -230,7 +218,7 @@ class Config(SystemSettings, arbitrary_types_allowed=True):
# Google
google_api_key: Optional[str] = UserConfigurable(from_env="GOOGLE_API_KEY")
google_custom_search_engine_id: Optional[str] = UserConfigurable(
- from_env=lambda: os.getenv("GOOGLE_CUSTOM_SEARCH_ENGINE_ID"),
+ from_env="GOOGLE_CUSTOM_SEARCH_ENGINE_ID",
)
# Huggingface
@@ -299,34 +287,51 @@ class ConfigBuilder(Configurable[Config]):
def assert_config_has_openai_api_key(config: Config) -> None:
"""Check if the OpenAI API key is set in config.py or as an environment variable."""
- if not config.openai_credentials:
- print(
- Fore.RED
- + "Please set your OpenAI API key in .env or as an environment variable."
- + Fore.RESET
+ key_pattern = r"^sk-\w{48}"
+ openai_api_key = (
+ config.openai_credentials.api_key.get_secret_value()
+ if config.openai_credentials
+ else ""
+ )
+
+ # If there's no credentials or empty API key, prompt the user to set it
+ if not openai_api_key:
+ logger.error(
+ "Please set your OpenAI API key in .env or as an environment variable."
+ )
+ logger.info(
+ "You can get your key from https://platform.openai.com/account/api-keys"
)
- print("You can get your key from https://platform.openai.com/account/api-keys")
- openai_api_key = input(
- "If you do have the key, please enter your OpenAI API key now:\n"
+ openai_api_key = clean_input(
+ config, "Please enter your OpenAI API key if you have it:"
)
- key_pattern = r"^sk-\w{48}"
openai_api_key = openai_api_key.strip()
if re.search(key_pattern, openai_api_key):
os.environ["OPENAI_API_KEY"] = openai_api_key
- config.openai_credentials = OpenAICredentials(
- api_key=SecretStr(openai_api_key)
- )
+ if config.openai_credentials:
+ config.openai_credentials.api_key = SecretStr(openai_api_key)
+ else:
+ config.openai_credentials = OpenAICredentials(
+ api_key=SecretStr(openai_api_key)
+ )
+ print("OpenAI API key successfully set!")
print(
- Fore.GREEN
- + "OpenAI API key successfully set!\n"
- + Fore.YELLOW
- + "NOTE: The API key you've set is only temporary.\n"
- + "For longer sessions, please set it in .env file"
- + Fore.RESET
+ f"{Fore.YELLOW}NOTE: The API key you've set is only temporary. "
+ f"For longer sessions, please set it in the .env file{Fore.RESET}"
)
else:
- print("Invalid OpenAI API key!")
+ print(f"{Fore.RED}Invalid OpenAI API key{Fore.RESET}")
exit(1)
+ # If key is set, but it looks invalid
+ elif not re.search(key_pattern, openai_api_key):
+ logger.error(
+ "Invalid OpenAI API key! "
+ "Please set your OpenAI API key in .env or as an environment variable."
+ )
+ logger.info(
+ "You can get your key from https://platform.openai.com/account/api-keys"
+ )
+ exit(1)
def _safe_split(s: Union[str, None], sep: str = ",") -> list[str]:
diff --git a/autogpts/autogpt/autogpt/core/ability/builtins/query_language_model.py b/autogpts/autogpt/autogpt/core/ability/builtins/query_language_model.py
index 63dd5cfb3..7a6ae68ee 100644
--- a/autogpts/autogpt/autogpt/core/ability/builtins/query_language_model.py
+++ b/autogpts/autogpt/autogpt/core/ability/builtins/query_language_model.py
@@ -62,5 +62,5 @@ class QueryLanguageModel(Ability):
ability_name=self.name(),
ability_args={"query": query},
success=True,
- message=model_response.response["content"],
+ message=model_response.response.content or "",
)
diff --git a/autogpts/autogpt/autogpt/core/planning/prompt_strategies/initial_plan.py b/autogpts/autogpt/autogpt/core/planning/prompt_strategies/initial_plan.py
index 5a689c9ff..ae137a985 100644
--- a/autogpts/autogpt/autogpt/core/planning/prompt_strategies/initial_plan.py
+++ b/autogpts/autogpt/autogpt/core/planning/prompt_strategies/initial_plan.py
@@ -4,9 +4,9 @@ from autogpt.core.configuration import SystemConfiguration, UserConfigurable
from autogpt.core.planning.schema import Task, TaskType
from autogpt.core.prompting import PromptStrategy
from autogpt.core.prompting.schema import ChatPrompt, LanguageModelClassification
-from autogpt.core.prompting.utils import json_loads, to_numbered_list
+from autogpt.core.prompting.utils import to_numbered_list
from autogpt.core.resource.model_providers import (
- AssistantChatMessageDict,
+ AssistantChatMessage,
ChatMessage,
CompletionModelFunction,
)
@@ -178,7 +178,7 @@ class InitialPlan(PromptStrategy):
def parse_response_content(
self,
- response_content: AssistantChatMessageDict,
+ response_content: AssistantChatMessage,
) -> dict:
"""Parse the actual text response from the objective model.
@@ -189,9 +189,12 @@ class InitialPlan(PromptStrategy):
The parsed response.
"""
try:
- parsed_response = json_loads(
- response_content["tool_calls"][0]["function"]["arguments"]
- )
+ if not response_content.tool_calls:
+ raise ValueError(
+ f"LLM did not call {self._create_plan_function.name} function; "
+ "plan creation failed"
+ )
+ parsed_response: object = response_content.tool_calls[0].function.arguments
parsed_response["task_list"] = [
Task.parse_obj(task) for task in parsed_response["task_list"]
]
diff --git a/autogpts/autogpt/autogpt/core/planning/prompt_strategies/name_and_goals.py b/autogpts/autogpt/autogpt/core/planning/prompt_strategies/name_and_goals.py
index 3f1d84b10..133b4590d 100644
--- a/autogpts/autogpt/autogpt/core/planning/prompt_strategies/name_and_goals.py
+++ b/autogpts/autogpt/autogpt/core/planning/prompt_strategies/name_and_goals.py
@@ -3,9 +3,8 @@ import logging
from autogpt.core.configuration import SystemConfiguration, UserConfigurable
from autogpt.core.prompting import PromptStrategy
from autogpt.core.prompting.schema import ChatPrompt, LanguageModelClassification
-from autogpt.core.prompting.utils import json_loads
from autogpt.core.resource.model_providers import (
- AssistantChatMessageDict,
+ AssistantChatMessage,
ChatMessage,
CompletionModelFunction,
)
@@ -124,7 +123,7 @@ class NameAndGoals(PromptStrategy):
def parse_response_content(
self,
- response_content: AssistantChatMessageDict,
+ response_content: AssistantChatMessage,
) -> dict:
"""Parse the actual text response from the objective model.
@@ -136,9 +135,12 @@ class NameAndGoals(PromptStrategy):
"""
try:
- parsed_response = json_loads(
- response_content["tool_calls"][0]["function"]["arguments"]
- )
+ if not response_content.tool_calls:
+ raise ValueError(
+ f"LLM did not call {self._create_agent_function} function; "
+ "agent profile creation failed"
+ )
+ parsed_response = response_content.tool_calls[0].function.arguments
except KeyError:
logger.debug(f"Failed to parse this response content: {response_content}")
raise
diff --git a/autogpts/autogpt/autogpt/core/planning/prompt_strategies/next_ability.py b/autogpts/autogpt/autogpt/core/planning/prompt_strategies/next_ability.py
index f4bade1fa..0d6daad2e 100644
--- a/autogpts/autogpt/autogpt/core/planning/prompt_strategies/next_ability.py
+++ b/autogpts/autogpt/autogpt/core/planning/prompt_strategies/next_ability.py
@@ -4,9 +4,9 @@ from autogpt.core.configuration import SystemConfiguration, UserConfigurable
from autogpt.core.planning.schema import Task
from autogpt.core.prompting import PromptStrategy
from autogpt.core.prompting.schema import ChatPrompt, LanguageModelClassification
-from autogpt.core.prompting.utils import json_loads, to_numbered_list
+from autogpt.core.prompting.utils import to_numbered_list
from autogpt.core.resource.model_providers import (
- AssistantChatMessageDict,
+ AssistantChatMessage,
ChatMessage,
CompletionModelFunction,
)
@@ -171,7 +171,7 @@ class NextAbility(PromptStrategy):
def parse_response_content(
self,
- response_content: AssistantChatMessageDict,
+ response_content: AssistantChatMessage,
) -> dict:
"""Parse the actual text response from the objective model.
@@ -183,10 +183,11 @@ class NextAbility(PromptStrategy):
"""
try:
- function_name = response_content["tool_calls"][0]["function"]["name"]
- function_arguments = json_loads(
- response_content["tool_calls"][0]["function"]["arguments"]
- )
+ if not response_content.tool_calls:
+ raise ValueError("LLM did not call any function")
+
+ function_name = response_content.tool_calls[0].function.name
+ function_arguments = response_content.tool_calls[0].function.arguments
parsed_response = {
"motivation": function_arguments.pop("motivation"),
"self_criticism": function_arguments.pop("self_criticism"),
diff --git a/autogpts/autogpt/autogpt/core/prompting/base.py b/autogpts/autogpt/autogpt/core/prompting/base.py
index c983be987..19e315f69 100644
--- a/autogpts/autogpt/autogpt/core/prompting/base.py
+++ b/autogpts/autogpt/autogpt/core/prompting/base.py
@@ -1,7 +1,7 @@
import abc
from autogpt.core.configuration import SystemConfiguration
-from autogpt.core.resource.model_providers import AssistantChatMessageDict
+from autogpt.core.resource.model_providers import AssistantChatMessage
from .schema import ChatPrompt, LanguageModelClassification
@@ -19,5 +19,5 @@ class PromptStrategy(abc.ABC):
...
@abc.abstractmethod
- def parse_response_content(self, response_content: AssistantChatMessageDict):
+ def parse_response_content(self, response_content: AssistantChatMessage):
...
diff --git a/autogpts/autogpt/autogpt/core/prompting/utils.py b/autogpts/autogpt/autogpt/core/prompting/utils.py
index 4b1be47f4..865b3fc08 100644
--- a/autogpts/autogpt/autogpt/core/prompting/utils.py
+++ b/autogpts/autogpt/autogpt/core/prompting/utils.py
@@ -1,7 +1,3 @@
-import ast
-import json
-
-
def to_numbered_list(
items: list[str], no_items_response: str = "", **template_args
) -> str:
@@ -11,19 +7,3 @@ def to_numbered_list(
)
else:
return no_items_response
-
-
-def json_loads(json_str: str):
- # TODO: this is a hack function for now. We'll see what errors show up in testing.
- # Can hopefully just replace with a call to ast.literal_eval.
- # Can't use json.loads because the function API still sometimes returns json strings
- # with minor issues like trailing commas.
- try:
- json_str = json_str[json_str.index("{") : json_str.rindex("}") + 1]
- return ast.literal_eval(json_str)
- except json.decoder.JSONDecodeError as e:
- try:
- print(f"json decode error {e}. trying literal eval")
- return ast.literal_eval(json_str)
- except Exception:
- breakpoint()
diff --git a/autogpts/autogpt/autogpt/core/resource/model_providers/openai.py b/autogpts/autogpt/autogpt/core/resource/model_providers/openai.py
index 3aad03fb1..cc6acd7df 100644
--- a/autogpts/autogpt/autogpt/core/resource/model_providers/openai.py
+++ b/autogpts/autogpt/autogpt/core/resource/model_providers/openai.py
@@ -1,21 +1,27 @@
import enum
-import functools
import logging
-import math
import os
-import time
from pathlib import Path
-from typing import Callable, Optional, ParamSpec, TypeVar
+from typing import Any, Callable, Coroutine, Iterator, Optional, ParamSpec, TypeVar
-import openai
+import sentry_sdk
+import tenacity
import tiktoken
import yaml
-from openai.error import APIError, RateLimitError
+from openai._exceptions import APIStatusError, RateLimitError
+from openai.types import CreateEmbeddingResponse
+from openai.types.chat import (
+ ChatCompletion,
+ ChatCompletionMessage,
+ ChatCompletionMessageParam,
+)
from pydantic import SecretStr
from autogpt.core.configuration import Configurable, UserConfigurable
from autogpt.core.resource.model_providers.schema import (
- AssistantChatMessageDict,
+ AssistantChatMessage,
+ AssistantFunctionCall,
+ AssistantToolCall,
AssistantToolCallDict,
ChatMessage,
ChatModelInfo,
@@ -30,27 +36,28 @@ from autogpt.core.resource.model_providers.schema import (
ModelProviderConfiguration,
ModelProviderCredentials,
ModelProviderName,
- ModelProviderService,
ModelProviderSettings,
- ModelProviderUsage,
ModelTokenizer,
)
from autogpt.core.utils.json_schema import JSONSchema
+from autogpt.core.utils.json_utils import json_loads
_T = TypeVar("_T")
_P = ParamSpec("_P")
OpenAIEmbeddingParser = Callable[[Embedding], Embedding]
-OpenAIChatParser = Callable[[str], dict]
class OpenAIModelName(str, enum.Enum):
- ADA = "text-embedding-ada-002"
+ EMBEDDING_v2 = "text-embedding-ada-002"
+ EMBEDDING_v3_S = "text-embedding-3-small"
+ EMBEDDING_v3_L = "text-embedding-3-large"
GPT3_v1 = "gpt-3.5-turbo-0301"
GPT3_v2 = "gpt-3.5-turbo-0613"
GPT3_v2_16k = "gpt-3.5-turbo-16k-0613"
GPT3_v3 = "gpt-3.5-turbo-1106"
+ GPT3_v4 = "gpt-3.5-turbo-0125"
GPT3_ROLLING = "gpt-3.5-turbo"
GPT3_ROLLING_16k = "gpt-3.5-turbo-16k"
GPT3 = GPT3_ROLLING
@@ -61,22 +68,41 @@ class OpenAIModelName(str, enum.Enum):
GPT4_v2 = "gpt-4-0613"
GPT4_v2_32k = "gpt-4-32k-0613"
GPT4_v3 = "gpt-4-1106-preview"
+ GPT4_v3_VISION = "gpt-4-1106-vision-preview"
+ GPT4_v4 = "gpt-4-0125-preview"
GPT4_ROLLING = "gpt-4"
GPT4_ROLLING_32k = "gpt-4-32k"
+ GPT4_TURBO = "gpt-4-turbo-preview"
GPT4_VISION = "gpt-4-vision-preview"
GPT4 = GPT4_ROLLING
GPT4_32k = GPT4_ROLLING_32k
OPEN_AI_EMBEDDING_MODELS = {
- OpenAIModelName.ADA: EmbeddingModelInfo(
- name=OpenAIModelName.ADA,
- service=ModelProviderService.EMBEDDING,
- provider_name=ModelProviderName.OPENAI,
- prompt_token_cost=0.0001 / 1000,
- max_tokens=8191,
- embedding_dimensions=1536,
- ),
+ info.name: info
+ for info in [
+ EmbeddingModelInfo(
+ name=OpenAIModelName.EMBEDDING_v2,
+ provider_name=ModelProviderName.OPENAI,
+ prompt_token_cost=0.0001 / 1000,
+ max_tokens=8191,
+ embedding_dimensions=1536,
+ ),
+ EmbeddingModelInfo(
+ name=OpenAIModelName.EMBEDDING_v3_S,
+ provider_name=ModelProviderName.OPENAI,
+ prompt_token_cost=0.00002 / 1000,
+ max_tokens=8191,
+ embedding_dimensions=1536,
+ ),
+ EmbeddingModelInfo(
+ name=OpenAIModelName.EMBEDDING_v3_L,
+ provider_name=ModelProviderName.OPENAI,
+ prompt_token_cost=0.00013 / 1000,
+ max_tokens=8191,
+ embedding_dimensions=3072,
+ ),
+ ]
}
@@ -84,8 +110,7 @@ OPEN_AI_CHAT_MODELS = {
info.name: info
for info in [
ChatModelInfo(
- name=OpenAIModelName.GPT3,
- service=ModelProviderService.CHAT,
+ name=OpenAIModelName.GPT3_v1,
provider_name=ModelProviderName.OPENAI,
prompt_token_cost=0.0015 / 1000,
completion_token_cost=0.002 / 1000,
@@ -93,8 +118,7 @@ OPEN_AI_CHAT_MODELS = {
has_function_call_api=True,
),
ChatModelInfo(
- name=OpenAIModelName.GPT3_16k,
- service=ModelProviderService.CHAT,
+ name=OpenAIModelName.GPT3_v2_16k,
provider_name=ModelProviderName.OPENAI,
prompt_token_cost=0.003 / 1000,
completion_token_cost=0.004 / 1000,
@@ -103,7 +127,6 @@ OPEN_AI_CHAT_MODELS = {
),
ChatModelInfo(
name=OpenAIModelName.GPT3_v3,
- service=ModelProviderService.CHAT,
provider_name=ModelProviderName.OPENAI,
prompt_token_cost=0.001 / 1000,
completion_token_cost=0.002 / 1000,
@@ -111,8 +134,15 @@ OPEN_AI_CHAT_MODELS = {
has_function_call_api=True,
),
ChatModelInfo(
- name=OpenAIModelName.GPT4,
- service=ModelProviderService.CHAT,
+ name=OpenAIModelName.GPT3_v4,
+ provider_name=ModelProviderName.OPENAI,
+ prompt_token_cost=0.0005 / 1000,
+ completion_token_cost=0.0015 / 1000,
+ max_tokens=16384,
+ has_function_call_api=True,
+ ),
+ ChatModelInfo(
+ name=OpenAIModelName.GPT4_v1,
provider_name=ModelProviderName.OPENAI,
prompt_token_cost=0.03 / 1000,
completion_token_cost=0.06 / 1000,
@@ -120,8 +150,7 @@ OPEN_AI_CHAT_MODELS = {
has_function_call_api=True,
),
ChatModelInfo(
- name=OpenAIModelName.GPT4_32k,
- service=ModelProviderService.CHAT,
+ name=OpenAIModelName.GPT4_v1_32k,
provider_name=ModelProviderName.OPENAI,
prompt_token_cost=0.06 / 1000,
completion_token_cost=0.12 / 1000,
@@ -129,8 +158,7 @@ OPEN_AI_CHAT_MODELS = {
has_function_call_api=True,
),
ChatModelInfo(
- name=OpenAIModelName.GPT4_v3,
- service=ModelProviderService.CHAT,
+ name=OpenAIModelName.GPT4_TURBO,
provider_name=ModelProviderName.OPENAI,
prompt_token_cost=0.01 / 1000,
completion_token_cost=0.03 / 1000,
@@ -141,18 +169,24 @@ OPEN_AI_CHAT_MODELS = {
}
# Copy entries for models with equivalent specs
chat_model_mapping = {
- OpenAIModelName.GPT3: [OpenAIModelName.GPT3_v1, OpenAIModelName.GPT3_v2],
- OpenAIModelName.GPT3_16k: [OpenAIModelName.GPT3_v2_16k],
- OpenAIModelName.GPT4: [OpenAIModelName.GPT4_v1, OpenAIModelName.GPT4_v2],
- OpenAIModelName.GPT4_32k: [
- OpenAIModelName.GPT4_v1_32k,
+ OpenAIModelName.GPT3_v1: [OpenAIModelName.GPT3_v2],
+ OpenAIModelName.GPT3_v2_16k: [OpenAIModelName.GPT3_16k],
+ OpenAIModelName.GPT3_v4: [OpenAIModelName.GPT3_ROLLING],
+ OpenAIModelName.GPT4_v1: [OpenAIModelName.GPT4_v2, OpenAIModelName.GPT4_ROLLING],
+ OpenAIModelName.GPT4_v1_32k: [
OpenAIModelName.GPT4_v2_32k,
+ OpenAIModelName.GPT4_32k,
+ ],
+ OpenAIModelName.GPT4_TURBO: [
+ OpenAIModelName.GPT4_v3,
+ OpenAIModelName.GPT4_v3_VISION,
+ OpenAIModelName.GPT4_v4,
+ OpenAIModelName.GPT4_VISION,
],
}
for base, copies in chat_model_mapping.items():
for copy in copies:
- copy_info = ChatModelInfo(**OPEN_AI_CHAT_MODELS[base].__dict__)
- copy_info.name = copy
+ copy_info = OPEN_AI_CHAT_MODELS[base].copy(update={"name": copy})
OPEN_AI_CHAT_MODELS[copy] = copy_info
if copy.endswith(("-0301", "-0314")):
copy_info.has_function_call_api = False
@@ -165,7 +199,7 @@ OPEN_AI_MODELS = {
class OpenAIConfiguration(ModelProviderConfiguration):
- pass
+ fix_failed_parse_tries: int = UserConfigurable(3)
class OpenAICredentials(ModelProviderCredentials):
@@ -186,32 +220,46 @@ class OpenAICredentials(ModelProviderCredentials):
),
)
api_version: str = UserConfigurable("", from_env="OPENAI_API_VERSION")
+ azure_endpoint: Optional[SecretStr] = None
azure_model_to_deploy_id_map: Optional[dict[str, str]] = None
- def get_api_access_kwargs(self, model: str = "") -> dict[str, str]:
- credentials = {k: v for k, v in self.unmasked().items() if type(v) is str}
+ def get_api_access_kwargs(self) -> dict[str, str]:
+ kwargs = {
+ k: (v.get_secret_value() if type(v) is SecretStr else v)
+ for k, v in {
+ "api_key": self.api_key,
+ "base_url": self.api_base,
+ "organization": self.organization,
+ }.items()
+ if v is not None
+ }
+ if self.api_type == "azure":
+ kwargs["api_version"] = self.api_version
+ assert self.azure_endpoint, "Azure endpoint not configured"
+ kwargs["azure_endpoint"] = self.azure_endpoint.get_secret_value()
+ return kwargs
+
+ def get_model_access_kwargs(self, model: str) -> dict[str, str]:
+ kwargs = {"model": model}
if self.api_type == "azure" and model:
- azure_credentials = self._get_azure_access_kwargs(model)
- credentials.update(azure_credentials)
- return credentials
+ azure_kwargs = self._get_azure_access_kwargs(model)
+ kwargs.update(azure_kwargs)
+ return kwargs
def load_azure_config(self, config_file: Path) -> None:
with open(config_file) as file:
- config_params = yaml.load(file, Loader=yaml.FullLoader) or {}
+ config_params = yaml.load(file, Loader=yaml.SafeLoader) or {}
try:
- assert (
- azure_api_base := config_params.get("azure_api_base", "")
- ) != "", "Azure API base URL not set"
assert config_params.get(
"azure_model_map", {}
), "Azure model->deployment_id map is empty"
except AssertionError as e:
raise ValueError(*e.args)
- self.api_base = SecretStr(azure_api_base)
self.api_type = config_params.get("azure_api_type", "azure")
self.api_version = config_params.get("azure_api_version", "")
+ self.azure_endpoint = config_params.get("azure_endpoint")
self.azure_model_to_deploy_id_map = config_params.get("azure_model_map")
def _get_azure_access_kwargs(self, model: str) -> dict[str, str]:
@@ -224,21 +272,13 @@ class OpenAICredentials(ModelProviderCredentials):
raise ValueError(f"No Azure deployment ID configured for model '{model}'")
deployment_id = self.azure_model_to_deploy_id_map[model]
- if model in OPEN_AI_EMBEDDING_MODELS:
- return {"engine": deployment_id}
- else:
- return {"deployment_id": deployment_id}
-
-
-class OpenAIModelProviderBudget(ModelProviderBudget):
- graceful_shutdown_threshold: float = UserConfigurable()
- warning_threshold: float = UserConfigurable()
+ return {"model": deployment_id}
class OpenAISettings(ModelProviderSettings):
configuration: OpenAIConfiguration
credentials: Optional[OpenAICredentials]
- budget: OpenAIModelProviderBudget
+ budget: ModelProviderBudget
class OpenAIProvider(
@@ -248,53 +288,53 @@ class OpenAIProvider(
name="openai_provider",
description="Provides access to OpenAI's API.",
configuration=OpenAIConfiguration(
- retries_per_request=10,
+ retries_per_request=7,
),
credentials=None,
- budget=OpenAIModelProviderBudget(
- total_budget=math.inf,
- total_cost=0.0,
- remaining_budget=math.inf,
- usage=ModelProviderUsage(
- prompt_tokens=0,
- completion_tokens=0,
- total_tokens=0,
- ),
- graceful_shutdown_threshold=0.005,
- warning_threshold=0.01,
- ),
+ budget=ModelProviderBudget(),
)
_configuration: OpenAIConfiguration
+ _credentials: OpenAICredentials
+ _budget: ModelProviderBudget
def __init__(
self,
- settings: OpenAISettings,
- logger: logging.Logger,
+ settings: Optional[OpenAISettings] = None,
+ logger: Optional[logging.Logger] = None,
):
- assert settings.credentials, "Cannot create OpenAIProvider without credentials"
+ if not settings:
+ settings = self.default_settings.copy(deep=True)
+ if not settings.credentials:
+ settings.credentials = OpenAICredentials.from_env()
+
+ self._settings = settings
+
self._configuration = settings.configuration
self._credentials = settings.credentials
self._budget = settings.budget
- self._logger = logger
+ if self._credentials.api_type == "azure":
+ from openai import AsyncAzureOpenAI
- retry_handler = _OpenAIRetryHandler(
- logger=self._logger,
- num_retries=self._configuration.retries_per_request,
- )
+ # API key and org (if configured) are passed, the rest of the required
+ # credentials is loaded from the environment by the AzureOpenAI client.
+ self._client = AsyncAzureOpenAI(**self._credentials.get_api_access_kwargs())
+ else:
+ from openai import AsyncOpenAI
+
+ self._client = AsyncOpenAI(**self._credentials.get_api_access_kwargs())
+
+ self._logger = logger or logging.getLogger(__name__)
- self._create_chat_completion = retry_handler(_create_chat_completion)
- self._create_embedding = retry_handler(_create_embedding)
+ async def get_available_models(self) -> list[ChatModelInfo]:
+ _models = (await self._client.models.list()).data
+ return [OPEN_AI_MODELS[m.id] for m in _models if m.id in OPEN_AI_MODELS]
def get_token_limit(self, model_name: str) -> int:
"""Get the token limit for a given model."""
return OPEN_AI_MODELS[model_name].max_tokens
- def get_remaining_budget(self) -> float:
- """Get the remaining budget."""
- return self._budget.remaining_budget
-
@classmethod
def get_tokenizer(cls, model_name: OpenAIModelName) -> ModelTokenizer:
return tiktoken.encoding_for_model(model_name)
@@ -332,7 +372,7 @@ class OpenAIProvider(
try:
encoding = tiktoken.encoding_for_model(encoding_model)
except KeyError:
- cls._logger.warning(
+ logging.getLogger(__class__.__name__).warning(
f"Model {model_name} not found. Defaulting to cl100k_base encoding."
)
encoding = tiktoken.get_encoding("cl100k_base")
@@ -351,40 +391,101 @@ class OpenAIProvider(
self,
model_prompt: list[ChatMessage],
model_name: OpenAIModelName,
- completion_parser: Callable[[AssistantChatMessageDict], _T] = lambda _: None,
+ completion_parser: Callable[[AssistantChatMessage], _T] = lambda _: None,
functions: Optional[list[CompletionModelFunction]] = None,
+ max_output_tokens: Optional[int] = None,
**kwargs,
) -> ChatModelResponse[_T]:
"""Create a completion using the OpenAI API."""
- completion_kwargs = self._get_completion_kwargs(model_name, functions, **kwargs)
- tool_calls_compat_mode = functions and "tools" not in completion_kwargs
- if "messages" in completion_kwargs:
- model_prompt += completion_kwargs["messages"]
- del completion_kwargs["messages"]
-
- response = await self._create_chat_completion(
- messages=model_prompt,
- **completion_kwargs,
+ openai_messages, completion_kwargs = self._get_chat_completion_args(
+ model_prompt=model_prompt,
+ model_name=model_name,
+ functions=functions,
+ max_tokens=max_output_tokens,
+ **kwargs,
)
- response_args = {
- "model_info": OPEN_AI_CHAT_MODELS[model_name],
- "prompt_tokens_used": response.usage.prompt_tokens,
- "completion_tokens_used": response.usage.completion_tokens,
- }
+ tool_calls_compat_mode = bool(functions and "tools" not in completion_kwargs)
+
+ total_cost = 0.0
+ attempts = 0
+ while True:
+ _response, _cost, t_input, t_output = await self._create_chat_completion(
+ messages=openai_messages,
+ **completion_kwargs,
+ )
+ total_cost += _cost
+
+ # If parsing the response fails, append the error to the prompt, and let the
+ # LLM fix its mistake(s).
+ attempts += 1
+ parse_errors: list[Exception] = []
- response_message = response.choices[0].message.to_dict_recursive()
- if tool_calls_compat_mode:
- response_message["tool_calls"] = _tool_calls_compat_extract_calls(
- response_message["content"]
+ _assistant_msg = _response.choices[0].message
+
+ tool_calls, _errors = self._parse_assistant_tool_calls(
+ _assistant_msg, tool_calls_compat_mode
+ )
+ parse_errors += _errors
+
+ assistant_msg = AssistantChatMessage(
+ content=_assistant_msg.content,
+ tool_calls=tool_calls or None,
)
- response = ChatModelResponse(
- response=response_message,
- parsed_result=completion_parser(response_message),
- **response_args,
- )
- self._budget.update_usage_and_cost(response)
- return response
+
+ parsed_result: _T = None # type: ignore
+ if not parse_errors:
+ try:
+ parsed_result = completion_parser(assistant_msg)
+ except Exception as e:
+ parse_errors.append(e)
+
+ if not parse_errors:
+ if attempts > 1:
+ self._logger.debug(
+ f"Total cost for {attempts} attempts: ${round(total_cost, 5)}"
+ )
+
+ return ChatModelResponse(
+ response=AssistantChatMessage(
+ content=_assistant_msg.content,
+ tool_calls=tool_calls or None,
+ ),
+ parsed_result=parsed_result,
+ model_info=OPEN_AI_CHAT_MODELS[model_name],
+ prompt_tokens_used=t_input,
+ completion_tokens_used=t_output,
+ )
+
+ else:
+ self._logger.debug(
+ f"Parsing failed on response: '''{_assistant_msg}'''"
+ )
+ self._logger.warning(
+ f"Parsing attempt #{attempts} failed: {parse_errors}"
+ )
+ for e in parse_errors:
+ sentry_sdk.capture_exception(
+ error=e,
+ extras={"assistant_msg": _assistant_msg, "i_attempt": attempts},
+ )
+
+ if attempts < self._configuration.fix_failed_parse_tries:
+ openai_messages.append(_assistant_msg.dict(exclude_none=True))
+ openai_messages.append(
+ {
+ "role": "system",
+ "content": (
+ "ERROR PARSING YOUR RESPONSE:\n\n"
+ + "\n\n".join(
+ f"{e.__class__.__name__}: {e}" for e in parse_errors
+ )
+ ),
+ }
+ )
+ continue
+ else:
+ raise parse_errors[0]
async def create_embedding(
self,
@@ -397,62 +498,68 @@ class OpenAIProvider(
embedding_kwargs = self._get_embedding_kwargs(model_name, **kwargs)
response = await self._create_embedding(text=text, **embedding_kwargs)
- response_args = {
- "model_info": OPEN_AI_EMBEDDING_MODELS[model_name],
- "prompt_tokens_used": response.usage.prompt_tokens,
- "completion_tokens_used": response.usage.completion_tokens,
- }
response = EmbeddingModelResponse(
- **response_args,
- embedding=embedding_parser(response.embeddings[0]),
+ embedding=embedding_parser(response.data[0].embedding),
+ model_info=OPEN_AI_EMBEDDING_MODELS[model_name],
+ prompt_tokens_used=response.usage.prompt_tokens,
+ completion_tokens_used=0,
)
self._budget.update_usage_and_cost(response)
return response
- def _get_completion_kwargs(
+ def _get_chat_completion_args(
self,
+ model_prompt: list[ChatMessage],
model_name: OpenAIModelName,
functions: Optional[list[CompletionModelFunction]] = None,
**kwargs,
- ) -> dict:
- """Get kwargs for completion API call.
+ ) -> tuple[list[ChatCompletionMessageParam], dict[str, Any]]:
+ """Prepare chat completion arguments and keyword arguments for API call.
Args:
- model: The model to use.
- kwargs: Keyword arguments to override the default values.
+ model_prompt: List of ChatMessages.
+ model_name: The model to use.
+ functions: Optional list of functions available to the LLM.
+ kwargs: Additional keyword arguments.
Returns:
- The kwargs for the chat API call.
-
+ list[ChatCompletionMessageParam]: Prompt messages for the OpenAI call
+ dict[str, Any]: Any other kwargs for the OpenAI call
"""
- completion_kwargs = {
- "model": model_name,
- **kwargs,
- **self._credentials.get_api_access_kwargs(model_name),
- }
+ kwargs.update(self._credentials.get_model_access_kwargs(model_name))
if functions:
if OPEN_AI_CHAT_MODELS[model_name].has_function_call_api:
- completion_kwargs["tools"] = [
+ kwargs["tools"] = [
{"type": "function", "function": f.schema} for f in functions
]
if len(functions) == 1:
# force the model to call the only specified function
- completion_kwargs["tool_choice"] = {
+ kwargs["tool_choice"] = {
"type": "function",
"function": {"name": functions[0].name},
}
else:
# Provide compatibility with older models
- _functions_compat_fix_kwargs(functions, completion_kwargs)
+ _functions_compat_fix_kwargs(functions, kwargs)
if extra_headers := self._configuration.extra_request_headers:
- if completion_kwargs.get("headers"):
- completion_kwargs["headers"].update(extra_headers)
- else:
- completion_kwargs["headers"] = extra_headers.copy()
+ kwargs["extra_headers"] = kwargs.get("extra_headers", {})
+ kwargs["extra_headers"].update(extra_headers.copy())
+
+ if "messages" in kwargs:
+ model_prompt += kwargs["messages"]
+ del kwargs["messages"]
+
+ openai_messages: list[ChatCompletionMessageParam] = [
+ message.dict(
+ include={"role", "content", "tool_calls", "name"},
+ exclude_none=True,
+ )
+ for message in model_prompt
+ ]
- return completion_kwargs
+ return openai_messages, kwargs
def _get_embedding_kwargs(
self,
@@ -469,120 +576,159 @@ class OpenAIProvider(
The kwargs for the embedding API call.
"""
- embedding_kwargs = {
- "model": model_name,
- **kwargs,
- **self._credentials.unmasked(),
- }
+ kwargs.update(self._credentials.get_model_access_kwargs(model_name))
if extra_headers := self._configuration.extra_request_headers:
- if embedding_kwargs.get("headers"):
- embedding_kwargs["headers"].update(extra_headers)
- else:
- embedding_kwargs["headers"] = extra_headers.copy()
-
- return embedding_kwargs
-
- def __repr__(self):
- return "OpenAIProvider()"
+ kwargs["extra_headers"] = kwargs.get("extra_headers", {})
+ kwargs["extra_headers"].update(extra_headers.copy())
+ return kwargs
-async def _create_embedding(text: str, *_, **kwargs) -> openai.Embedding:
- """Embed text using the OpenAI API.
-
- Args:
- text str: The text to embed.
- model str: The name of the model to use.
-
- Returns:
- str: The embedding.
- """
- return await openai.Embedding.acreate(
- input=[text],
+ async def _create_chat_completion(
+ self,
+ messages: list[ChatCompletionMessageParam],
+ model: OpenAIModelName,
+ *_,
**kwargs,
- )
-
-
-async def _create_chat_completion(
- messages: list[ChatMessage], *_, **kwargs
-) -> openai.Completion:
- """Create a chat completion using the OpenAI API.
+ ) -> tuple[ChatCompletion, float, int, int]:
+ """
+ Create a chat completion using the OpenAI API with retry handling.
- Args:
- messages: The prompt to use.
+ Params:
+ openai_messages: List of OpenAI-consumable message dict objects
+ model: The model to use for the completion
- Returns:
- The completion.
- """
- raw_messages = [
- message.dict(include={"role", "content", "tool_calls", "name"})
- for message in messages
- ]
- return await openai.ChatCompletion.acreate(
- messages=raw_messages,
- **kwargs,
- )
+ Returns:
+ ChatCompletion: The chat completion response object
+ float: The cost ($) of this completion
+ int: Number of prompt tokens used
+ int: Number of completion tokens used
+ """
+ @self._retry_api_request
+ async def _create_chat_completion_with_retry(
+ messages: list[ChatCompletionMessageParam], **kwargs
+ ) -> ChatCompletion:
+ return await self._client.chat.completions.create(
+ messages=messages, # type: ignore
+ **kwargs,
+ )
-class _OpenAIRetryHandler:
- """Retry Handler for OpenAI API call.
+ completion = await _create_chat_completion_with_retry(
+ messages, model=model, **kwargs
+ )
- Args:
- num_retries int: Number of retries. Defaults to 10.
- backoff_base float: Base for exponential backoff. Defaults to 2.
- warn_user bool: Whether to warn the user. Defaults to True.
- """
+ if completion.usage:
+ prompt_tokens_used = completion.usage.prompt_tokens
+ completion_tokens_used = completion.usage.completion_tokens
+ else:
+ prompt_tokens_used = completion_tokens_used = 0
- _retry_limit_msg = "Error: Reached rate limit, passing..."
- _api_key_error_msg = (
- "Please double check that you have setup a PAID OpenAI API Account. You can "
- "read more here: https://docs.agpt.co/setup/#getting-an-openai-api-key"
- )
- _backoff_msg = "Error: API Bad gateway. Waiting {backoff} seconds..."
+ cost = self._budget.update_usage_and_cost(
+ model_info=OPEN_AI_CHAT_MODELS[model],
+ input_tokens_used=prompt_tokens_used,
+ output_tokens_used=completion_tokens_used,
+ )
+ self._logger.debug(
+ f"Completion usage: {prompt_tokens_used} input, "
+ f"{completion_tokens_used} output - ${round(cost, 5)}"
+ )
+ return completion, cost, prompt_tokens_used, completion_tokens_used
- def __init__(
- self,
- logger: logging.Logger,
- num_retries: int = 10,
- backoff_base: float = 2.0,
- warn_user: bool = True,
+ def _parse_assistant_tool_calls(
+ self, assistant_message: ChatCompletionMessage, compat_mode: bool = False
):
- self._logger = logger
- self._num_retries = num_retries
- self._backoff_base = backoff_base
- self._warn_user = warn_user
-
- def _log_rate_limit_error(self) -> None:
- self._logger.debug(self._retry_limit_msg)
- if self._warn_user:
- self._logger.warning(self._api_key_error_msg)
- self._warn_user = False
-
- def _backoff(self, attempt: int) -> None:
- backoff = self._backoff_base ** (attempt + 2)
- self._logger.debug(self._backoff_msg.format(backoff=backoff))
- time.sleep(backoff)
-
- def __call__(self, func: Callable[_P, _T]) -> Callable[_P, _T]:
- @functools.wraps(func)
- async def _wrapped(*args: _P.args, **kwargs: _P.kwargs) -> _T:
- num_attempts = self._num_retries + 1 # +1 for the first attempt
- for attempt in range(1, num_attempts + 1):
- try:
- return await func(*args, **kwargs)
+ tool_calls: list[AssistantToolCall] = []
+ parse_errors: list[Exception] = []
- except RateLimitError:
- if attempt == num_attempts:
- raise
- self._log_rate_limit_error()
-
- except APIError as e:
- if (e.http_status != 502) or (attempt == num_attempts):
- raise
+ if assistant_message.tool_calls:
+ for _tc in assistant_message.tool_calls:
+ try:
+ parsed_arguments = json_loads(_tc.function.arguments)
+ except Exception as e:
+ err_message = (
+ f"Decoding arguments for {_tc.function.name} failed: "
+ + str(e.args[0])
+ )
+ parse_errors.append(
+ type(e)(err_message, *e.args[1:]).with_traceback(
+ e.__traceback__
+ )
+ )
+ continue
+
+ tool_calls.append(
+ AssistantToolCall(
+ id=_tc.id,
+ type=_tc.type,
+ function=AssistantFunctionCall(
+ name=_tc.function.name,
+ arguments=parsed_arguments,
+ ),
+ )
+ )
+
+ # If parsing of all tool calls succeeds in the end, we ignore any issues
+ if len(tool_calls) == len(assistant_message.tool_calls):
+ parse_errors = []
+
+ elif compat_mode and assistant_message.content:
+ try:
+ tool_calls = list(
+ _tool_calls_compat_extract_calls(assistant_message.content)
+ )
+ except Exception as e:
+ parse_errors.append(e)
+
+ return tool_calls, parse_errors
+
+ def _create_embedding(
+ self, text: str, *_, **kwargs
+ ) -> Coroutine[None, None, CreateEmbeddingResponse]:
+ """Create an embedding using the OpenAI API with retry handling."""
+
+ @self._retry_api_request
+ async def _create_embedding_with_retry(
+ text: str, *_, **kwargs
+ ) -> CreateEmbeddingResponse:
+ return await self._client.embeddings.create(
+ input=[text],
+ **kwargs,
+ )
- self._backoff(attempt)
+ return _create_embedding_with_retry(text, *_, **kwargs)
+
+ def _retry_api_request(self, func: Callable[_P, _T]) -> Callable[_P, _T]:
+ _log_retry_debug_message = tenacity.after_log(self._logger, logging.DEBUG)
+
+ def _log_on_fail(retry_state: tenacity.RetryCallState) -> None:
+ _log_retry_debug_message(retry_state)
+
+ if (
+ retry_state.attempt_number == 0
+ and retry_state.outcome
+ and isinstance(retry_state.outcome.exception(), RateLimitError)
+ ):
+ self._logger.warning(
+ "Please double check that you have setup a PAID OpenAI API Account."
+ " You can read more here: "
+ "https://docs.agpt.co/setup/#getting-an-openai-api-key"
+ )
+
+ return tenacity.retry(
+ retry=(
+ tenacity.retry_if_exception_type(RateLimitError)
+ | tenacity.retry_if_exception(
+ lambda e: isinstance(e, APIStatusError) and e.status_code == 502
+ )
+ ),
+ wait=tenacity.wait_exponential(),
+ stop=tenacity.stop_after_attempt(self._configuration.retries_per_request),
+ after=_log_on_fail,
+ )(func)
- return _wrapped
+ def __repr__(self):
+ return "OpenAIProvider()"
def format_function_specs_as_typescript_ns(
@@ -708,21 +854,22 @@ def _functions_compat_fix_kwargs(
]
-def _tool_calls_compat_extract_calls(response: str) -> list[AssistantToolCallDict]:
- import json
+def _tool_calls_compat_extract_calls(response: str) -> Iterator[AssistantToolCall]:
import re
+ import uuid
logging.debug(f"Trying to extract tool calls from response:\n{response}")
if response[0] == "[":
- tool_calls: list[AssistantToolCallDict] = json.loads(response)
+ tool_calls: list[AssistantToolCallDict] = json_loads(response)
else:
block = re.search(r"```(?:tool_calls)?\n(.*)\n```\s*$", response, re.DOTALL)
if not block:
- raise ValueError("Could not find tool calls block in response")
- tool_calls: list[AssistantToolCallDict] = json.loads(block.group(1))
+ raise ValueError("Could not find tool_calls block in response")
+ tool_calls: list[AssistantToolCallDict] = json_loads(block.group(1))
for t in tool_calls:
+ t["id"] = str(uuid.uuid4())
t["function"]["arguments"] = str(t["function"]["arguments"]) # HACK
- return tool_calls
+ yield AssistantToolCall.parse_obj(t)
diff --git a/autogpts/autogpt/autogpt/core/resource/model_providers/schema.py b/autogpts/autogpt/autogpt/core/resource/model_providers/schema.py
index cebb84df0..dd69b526e 100644
--- a/autogpts/autogpt/autogpt/core/resource/model_providers/schema.py
+++ b/autogpts/autogpt/autogpt/core/resource/model_providers/schema.py
@@ -1,6 +1,9 @@
import abc
import enum
+import math
+from collections import defaultdict
from typing import (
+ Any,
Callable,
ClassVar,
Generic,
@@ -43,6 +46,8 @@ class ChatMessage(BaseModel):
SYSTEM = "system"
ASSISTANT = "assistant"
+ TOOL = "tool"
+ """May be used for the result of tool calls"""
FUNCTION = "function"
"""May be used for the return value of function calls"""
@@ -50,10 +55,6 @@ class ChatMessage(BaseModel):
content: str
@staticmethod
- def assistant(content: str) -> "ChatMessage":
- return ChatMessage(role=ChatMessage.Role.ASSISTANT, content=content)
-
- @staticmethod
def user(content: str) -> "ChatMessage":
return ChatMessage(role=ChatMessage.Role.USER, content=content)
@@ -69,30 +70,30 @@ class ChatMessageDict(TypedDict):
class AssistantFunctionCall(BaseModel):
name: str
- arguments: str
+ arguments: dict[str, Any]
class AssistantFunctionCallDict(TypedDict):
name: str
- arguments: str
+ arguments: dict[str, Any]
class AssistantToolCall(BaseModel):
- # id: str
+ id: str
type: Literal["function"]
function: AssistantFunctionCall
class AssistantToolCallDict(TypedDict):
- # id: str
+ id: str
type: Literal["function"]
function: AssistantFunctionCallDict
class AssistantChatMessage(ChatMessage):
- role: Literal["assistant"]
+ role: Literal[ChatMessage.Role.ASSISTANT] = ChatMessage.Role.ASSISTANT
content: Optional[str]
- tool_calls: Optional[list[AssistantToolCall]]
+ tool_calls: Optional[list[AssistantToolCall]] = None
class AssistantChatMessageDict(TypedDict, total=False):
@@ -136,7 +137,8 @@ class CompletionModelFunction(BaseModel):
def fmt_line(self) -> str:
params = ", ".join(
- f"{name}: {p.type.value}" for name, p in self.parameters.items()
+ f"{name}{'?' if not p.required else ''}: " f"{p.typescript_type}"
+ for name, p in self.parameters.items()
)
return f"{self.name}: {self.description}. Params: ({params})"
@@ -186,45 +188,45 @@ class ModelProviderUsage(ProviderUsage):
completion_tokens: int = 0
prompt_tokens: int = 0
- total_tokens: int = 0
def update_usage(
self,
- model_response: ModelResponse,
+ input_tokens_used: int,
+ output_tokens_used: int = 0,
) -> None:
- self.completion_tokens += model_response.completion_tokens_used
- self.prompt_tokens += model_response.prompt_tokens_used
- self.total_tokens += (
- model_response.completion_tokens_used + model_response.prompt_tokens_used
- )
+ self.prompt_tokens += input_tokens_used
+ self.completion_tokens += output_tokens_used
class ModelProviderBudget(ProviderBudget):
- total_budget: float = UserConfigurable()
- total_cost: float
- remaining_budget: float
- usage: ModelProviderUsage
+ usage: defaultdict[str, ModelProviderUsage] = defaultdict(ModelProviderUsage)
def update_usage_and_cost(
self,
- model_response: ModelResponse,
- ) -> None:
- """Update the usage and cost of the provider."""
- model_info = model_response.model_info
- self.usage.update_usage(model_response)
+ model_info: ModelInfo,
+ input_tokens_used: int,
+ output_tokens_used: int = 0,
+ ) -> float:
+ """Update the usage and cost of the provider.
+
+ Returns:
+ float: The (calculated) cost of the given model response.
+ """
+ self.usage[model_info.name].update_usage(input_tokens_used, output_tokens_used)
incurred_cost = (
- model_response.completion_tokens_used * model_info.completion_token_cost
- + model_response.prompt_tokens_used * model_info.prompt_token_cost
+ output_tokens_used * model_info.completion_token_cost
+ + input_tokens_used * model_info.prompt_token_cost
)
self.total_cost += incurred_cost
self.remaining_budget -= incurred_cost
+ return incurred_cost
class ModelProviderSettings(ProviderSettings):
resource_type: ResourceType = ResourceType.MODEL
configuration: ModelProviderConfiguration
credentials: ModelProviderCredentials
- budget: ModelProviderBudget
+ budget: Optional[ModelProviderBudget] = None
class ModelProvider(abc.ABC):
@@ -233,6 +235,7 @@ class ModelProvider(abc.ABC):
default_settings: ClassVar[ModelProviderSettings]
_configuration: ModelProviderConfiguration
+ _budget: Optional[ModelProviderBudget] = None
@abc.abstractmethod
def count_tokens(self, text: str, model_name: str) -> int:
@@ -246,9 +249,15 @@ class ModelProvider(abc.ABC):
def get_token_limit(self, model_name: str) -> int:
...
- @abc.abstractmethod
+ def get_incurred_cost(self) -> float:
+ if self._budget:
+ return self._budget.total_cost
+ return 0
+
def get_remaining_budget(self) -> float:
- ...
+ if self._budget:
+ return self._budget.remaining_budget
+ return math.inf
class ModelTokenizer(Protocol):
@@ -271,7 +280,7 @@ class ModelTokenizer(Protocol):
class EmbeddingModelInfo(ModelInfo):
"""Struct for embedding model information."""
- llm_service = ModelProviderService.EMBEDDING
+ service: Literal[ModelProviderService.EMBEDDING] = ModelProviderService.EMBEDDING
max_tokens: int
embedding_dimensions: int
@@ -309,7 +318,7 @@ class EmbeddingModelProvider(ModelProvider):
class ChatModelInfo(ModelInfo):
"""Struct for language model information."""
- llm_service = ModelProviderService.CHAT
+ service: Literal[ModelProviderService.CHAT] = ModelProviderService.CHAT
max_tokens: int
has_function_call_api: bool = False
@@ -320,12 +329,16 @@ _T = TypeVar("_T")
class ChatModelResponse(ModelResponse, Generic[_T]):
"""Standard response struct for a response from a language model."""
- response: AssistantChatMessageDict
+ response: AssistantChatMessage
parsed_result: _T = None
class ChatModelProvider(ModelProvider):
@abc.abstractmethod
+ async def get_available_models(self) -> list[ChatModelInfo]:
+ ...
+
+ @abc.abstractmethod
def count_message_tokens(
self,
messages: ChatMessage | list[ChatMessage],
@@ -338,8 +351,9 @@ class ChatModelProvider(ModelProvider):
self,
model_prompt: list[ChatMessage],
model_name: str,
- completion_parser: Callable[[AssistantChatMessageDict], _T] = lambda _: None,
+ completion_parser: Callable[[AssistantChatMessage], _T] = lambda _: None,
functions: Optional[list[CompletionModelFunction]] = None,
+ max_output_tokens: Optional[int] = None,
**kwargs,
) -> ChatModelResponse[_T]:
...
diff --git a/autogpts/autogpt/autogpt/core/resource/schema.py b/autogpts/autogpt/autogpt/core/resource/schema.py
index ed7a94d02..0da275ee2 100644
--- a/autogpts/autogpt/autogpt/core/resource/schema.py
+++ b/autogpts/autogpt/autogpt/core/resource/schema.py
@@ -1,5 +1,6 @@
import abc
import enum
+import math
from pydantic import BaseModel, SecretBytes, SecretField, SecretStr
@@ -25,14 +26,18 @@ class ProviderUsage(SystemConfiguration, abc.ABC):
class ProviderBudget(SystemConfiguration):
- total_budget: float = UserConfigurable()
- total_cost: float
- remaining_budget: float
+ total_budget: float = UserConfigurable(math.inf)
+ total_cost: float = 0
+ remaining_budget: float = math.inf
usage: ProviderUsage
@abc.abstractmethod
- def update_usage_and_cost(self, *args, **kwargs) -> None:
- """Update the usage and cost of the resource."""
+ def update_usage_and_cost(self, *args, **kwargs) -> float:
+ """Update the usage and cost of the provider.
+
+ Returns:
+ float: The (calculated) cost of the given model response.
+ """
...
diff --git a/autogpts/autogpt/autogpt/core/runner/cli_web_app/server/api.py b/autogpts/autogpt/autogpt/core/runner/cli_web_app/server/api.py
index 047cfd868..eadb20e58 100644
--- a/autogpts/autogpt/autogpt/core/runner/cli_web_app/server/api.py
+++ b/autogpts/autogpt/autogpt/core/runner/cli_web_app/server/api.py
@@ -89,9 +89,11 @@ def bootstrap_agent(task, continuous_mode) -> Agent:
ai_role="a multi-purpose AI assistant.",
ai_goals=[task],
)
+ # FIXME this won't work - ai_profile and triggering_prompt is not a valid argument,
+ # lacks file_storage, settings and llm_provider
return Agent(
command_registry=command_registry,
ai_profile=ai_profile,
- config=config,
+ legacy_config=config,
triggering_prompt=DEFAULT_TRIGGERING_PROMPT,
)
diff --git a/autogpts/autogpt/autogpt/core/runner/client_lib/logging/config.py b/autogpts/autogpt/autogpt/core/runner/client_lib/logging/config.py
index 191f8a1b8..56f79f5fe 100644
--- a/autogpts/autogpt/autogpt/core/runner/client_lib/logging/config.py
+++ b/autogpts/autogpt/autogpt/core/runner/client_lib/logging/config.py
@@ -2,7 +2,7 @@ import logging
import sys
from colorama import Fore, Style
-from openai.util import logger as openai_logger
+from openai._base_client import log as openai_logger
SIMPLE_LOG_FORMAT = "%(asctime)s %(levelname)s %(message)s"
DEBUG_LOG_FORMAT = (
diff --git a/autogpts/autogpt/autogpt/core/utils/json_schema.py b/autogpts/autogpt/autogpt/core/utils/json_schema.py
index a28286f17..d72b509dd 100644
--- a/autogpts/autogpt/autogpt/core/utils/json_schema.py
+++ b/autogpts/autogpt/autogpt/core/utils/json_schema.py
@@ -1,10 +1,8 @@
import enum
-import json
-from logging import Logger
from textwrap import indent
-from typing import Literal, Optional
+from typing import Optional
-from jsonschema import Draft7Validator
+from jsonschema import Draft7Validator, ValidationError
from pydantic import BaseModel
@@ -85,37 +83,24 @@ class JSONSchema(BaseModel):
v.required = k in schema_node["required"]
return properties
- def validate_object(
- self, object: object, logger: Logger
- ) -> tuple[Literal[True], None] | tuple[Literal[False], list]:
+ def validate_object(self, object: object) -> tuple[bool, list[ValidationError]]:
"""
- Validates a dictionary object against the JSONSchema.
+ Validates an object or a value against the JSONSchema.
Params:
- object: The dictionary object to validate.
+ object: The value/object to validate.
schema (JSONSchema): The JSONSchema to validate against.
Returns:
- tuple: A tuple where the first element is a boolean indicating whether the
- object is valid or not, and the second element is a list of errors found
- in the object, or None if the object is valid.
+ bool: Indicates whether the given value or object is valid for the schema.
+ list[ValidationError]: The issues with the value or object (if any).
"""
validator = Draft7Validator(self.to_dict())
if errors := sorted(validator.iter_errors(object), key=lambda e: e.path):
- for error in errors:
- logger.debug(f"JSON Validation Error: {error}")
-
- logger.error(json.dumps(object, indent=4))
- logger.error("The following issues were found:")
-
- for error in errors:
- logger.error(f"Error: {error.message}")
return False, errors
- logger.debug("The JSON object is valid.")
-
- return True, None
+ return True, []
def to_typescript_object_interface(self, interface_name: str = "") -> str:
if self.type != JSONSchema.Type.OBJECT:
diff --git a/autogpts/autogpt/autogpt/core/utils/json_utils.py b/autogpts/autogpt/autogpt/core/utils/json_utils.py
new file mode 100644
index 000000000..0374a85c1
--- /dev/null
+++ b/autogpts/autogpt/autogpt/core/utils/json_utils.py
@@ -0,0 +1,93 @@
+import logging
+import re
+from typing import Any
+
+import demjson3
+
+logger = logging.getLogger(__name__)
+
+
+def json_loads(json_str: str) -> Any:
+ """Parse a JSON string, tolerating minor syntax issues:
+ - Missing, extra and trailing commas
+ - Extraneous newlines and whitespace outside of string literals
+ - Inconsistent spacing after colons and commas
+ - Missing closing brackets or braces
+ - Numbers: binary, hex, octal, trailing and prefixed decimal points
+ - Different encodings
+ - Surrounding markdown code block
+ - Comments
+
+ Args:
+ json_str: The JSON string to parse.
+
+ Returns:
+ The parsed JSON object, same as built-in json.loads.
+ """
+ # Remove possible code block
+ pattern = r"```(?:json|JSON)*([\s\S]*?)```"
+ match = re.search(pattern, json_str)
+
+ if match:
+ json_str = match.group(1).strip()
+
+ json_result = demjson3.decode(json_str, return_errors=True)
+ assert json_result is not None # by virtue of return_errors=True
+
+ if json_result.errors:
+ logger.debug(
+ "JSON parse errors:\n" + "\n".join(str(e) for e in json_result.errors)
+ )
+
+ if json_result.object is demjson3.undefined:
+ raise ValueError(
+ f"Failed to parse JSON string: {json_str}", *json_result.errors
+ )
+
+ return json_result.object
+
+
+def extract_dict_from_json(json_str: str) -> dict[str, Any]:
+ # Sometimes the response includes the JSON in a code block with ```
+ pattern = r"```(?:json|JSON)*([\s\S]*?)```"
+ match = re.search(pattern, json_str)
+
+ if match:
+ json_str = match.group(1).strip()
+ else:
+ # The string may contain JSON.
+ json_pattern = r"{[\s\S]*}"
+ match = re.search(json_pattern, json_str)
+
+ if match:
+ json_str = match.group()
+
+ result = json_loads(json_str)
+ if not isinstance(result, dict):
+ raise ValueError(
+ f"Response '''{json_str}''' evaluated to non-dict value {repr(result)}"
+ )
+ return result
+
+
+def extract_list_from_json(json_str: str) -> list[Any]:
+ # Sometimes the response includes the JSON in a code block with ```
+ pattern = r"```(?:json|JSON)*([\s\S]*?)```"
+ match = re.search(pattern, json_str)
+
+ if match:
+ json_str = match.group(1).strip()
+ else:
+ # The string may contain JSON.
+ json_pattern = r"\[[\s\S]*\]"
+ match = re.search(json_pattern, json_str)
+
+ if match:
+ json_str = match.group()
+
+ result = json_loads(json_str)
+ if not isinstance(result, list):
+ raise ValueError(
+ f"Response '''{json_str}''' evaluated to non-list value {repr(result)}"
+ )
+ return result
diff --git a/autogpts/autogpt/autogpt/file_storage/__init__.py b/autogpts/autogpt/autogpt/file_storage/__init__.py
new file mode 100644
index 000000000..8e4116f39
--- /dev/null
+++ b/autogpts/autogpt/autogpt/file_storage/__init__.py
@@ -0,0 +1,44 @@
+import enum
+from pathlib import Path
+
+from .base import FileStorage
+
+
+class FileStorageBackendName(str, enum.Enum):
+ LOCAL = "local"
+ GCS = "gcs"
+ S3 = "s3"
+
+
+def get_storage(
+ backend: FileStorageBackendName,
+ root_path: Path = ".",
+ restrict_to_root: bool = True,
+) -> FileStorage:
+ match backend:
+ case FileStorageBackendName.LOCAL:
+ from .local import FileStorageConfiguration, LocalFileStorage
+
+ config = FileStorageConfiguration.from_env()
+ config.root = root_path
+ config.restrict_to_root = restrict_to_root
+ return LocalFileStorage(config)
+ case FileStorageBackendName.S3:
+ from .s3 import S3FileStorage, S3FileStorageConfiguration
+
+ config = S3FileStorageConfiguration.from_env()
+ config.root = root_path
+ return S3FileStorage(config)
+ case FileStorageBackendName.GCS:
+ from .gcs import GCSFileStorage, GCSFileStorageConfiguration
+
+ config = GCSFileStorageConfiguration.from_env()
+ config.root = root_path
+ return GCSFileStorage(config)
+
+
+__all__ = [
+ "FileStorage",
+ "FileStorageBackendName",
+ "get_storage",
+]
diff --git a/autogpts/autogpt/autogpt/file_storage/base.py b/autogpts/autogpt/autogpt/file_storage/base.py
new file mode 100644
index 000000000..62521bb4a
--- /dev/null
+++ b/autogpts/autogpt/autogpt/file_storage/base.py
@@ -0,0 +1,204 @@
+"""
+The FileStorage class provides an interface for interacting with a file storage.
+"""
+
+from __future__ import annotations
+
+import logging
+import os
+from abc import ABC, abstractmethod
+from io import IOBase, TextIOBase
+from pathlib import Path
+from typing import IO, Any, BinaryIO, Callable, Literal, TextIO, overload
+
+from autogpt.core.configuration.schema import SystemConfiguration
+
+logger = logging.getLogger(__name__)
+
+
+class FileStorageConfiguration(SystemConfiguration):
+ restrict_to_root: bool = True
+ root: Path = Path("/")
+
+
+class FileStorage(ABC):
+ """A class that represents a file storage."""
+
+ on_write_file: Callable[[Path], Any] | None = None
+ """
+ Event hook, executed after writing a file.
+
+ Params:
+ Path: The path of the file that was written, relative to the storage root.
+ """
+
+ @property
+ @abstractmethod
+ def root(self) -> Path:
+ """The root path of the file storage."""
+
+ @property
+ @abstractmethod
+ def restrict_to_root(self) -> bool:
+ """Whether to restrict file access to within the storage's root path."""
+
+ @property
+ @abstractmethod
+ def is_local(self) -> bool:
+ """Whether the storage is local (i.e. on the same machine, not cloud-based)."""
+
+ @abstractmethod
+ def initialize(self) -> None:
+ """
+ Calling `initialize()` should bring the storage to a ready-to-use state.
+ For example, it can create the resource in which files will be stored, if it
+ doesn't exist yet. E.g. a folder on disk, or an S3 Bucket.
+ """
+
+ @overload
+ @abstractmethod
+ def open_file(
+ self,
+ path: str | Path,
+ mode: Literal["w", "r"] = "r",
+ binary: Literal[False] = False,
+ ) -> TextIO | TextIOBase:
+ """Returns a readable text file-like object representing the file."""
+
+ @overload
+ @abstractmethod
+ def open_file(
+ self,
+ path: str | Path,
+ mode: Literal["w", "r"] = "r",
+ binary: Literal[True] = True,
+ ) -> BinaryIO | IOBase:
+ """Returns a readable binary file-like object representing the file."""
+
+ @abstractmethod
+ def open_file(
+ self, path: str | Path, mode: Literal["w", "r"] = "r", binary: bool = False
+ ) -> IO | IOBase:
+ """Returns a readable file-like object representing the file."""
+
+ @overload
+ @abstractmethod
+ def read_file(self, path: str | Path, binary: Literal[False] = False) -> str:
+ """Read a file in the storage as text."""
+ ...
+
+ @overload
+ @abstractmethod
+ def read_file(self, path: str | Path, binary: Literal[True] = True) -> bytes:
+ """Read a file in the storage as binary."""
+ ...
+
+ @abstractmethod
+ def read_file(self, path: str | Path, binary: bool = False) -> str | bytes:
+ """Read a file in the storage."""
+
+ @abstractmethod
+ async def write_file(self, path: str | Path, content: str | bytes) -> None:
+ """Write to a file in the storage."""
+
+ @abstractmethod
+ def list_files(self, path: str | Path = ".") -> list[Path]:
+ """List all files (recursively) in a directory in the storage."""
+
+ @abstractmethod
+ def list_folders(
+ self, path: str | Path = ".", recursive: bool = False
+ ) -> list[Path]:
+ """List all folders in a directory in the storage."""
+
+ @abstractmethod
+ def delete_file(self, path: str | Path) -> None:
+ """Delete a file in the storage."""
+
+ @abstractmethod
+ def delete_dir(self, path: str | Path) -> None:
+ """Delete an empty folder in the storage."""
+
+ @abstractmethod
+ def exists(self, path: str | Path) -> bool:
+ """Check if a file or folder exists in the storage."""
+
+ @abstractmethod
+ def rename(self, old_path: str | Path, new_path: str | Path) -> None:
+ """Rename a file or folder in the storage."""
+
+ @abstractmethod
+ def copy(self, source: str | Path, destination: str | Path) -> None:
+ """Copy a file or folder with all contents in the storage."""
+
+ @abstractmethod
+ def make_dir(self, path: str | Path) -> None:
+ """Create a directory in the storage if doesn't exist."""
+
+ @abstractmethod
+ def clone_with_subroot(self, subroot: str | Path) -> FileStorage:
+ """Create a new FileStorage with a subroot of the current storage."""
+
+ def get_path(self, relative_path: str | Path) -> Path:
+ """Get the full path for an item in the storage.
+
+ Parameters:
+ relative_path: The relative path to resolve in the storage.
+
+ Returns:
+ Path: The resolved path relative to the storage.
+ """
+ return self._sanitize_path(relative_path)
+
+ def _sanitize_path(
+ self,
+ path: str | Path,
+ ) -> Path:
+ """Resolve the relative path within the given root if possible.
+
+ Parameters:
+ relative_path: The relative path to resolve.
+
+ Returns:
+ Path: The resolved path.
+
+ Raises:
+ ValueError: If the path is absolute and a root is provided.
+ ValueError: If the path is outside the root and the root is restricted.
+ """
+
+ # Posix systems disallow null bytes in paths. Windows is agnostic about it.
+ # Do an explicit check here for all sorts of null byte representations.
+ if "\0" in str(path):
+ raise ValueError("Embedded null byte")
+
+ logger.debug(f"Resolving path '{path}' in storage '{self.root}'")
+
+ relative_path = Path(path)
+
+ # Allow absolute paths if they are contained in the storage.
+ if (
+ relative_path.is_absolute()
+ and self.restrict_to_root
+ and not relative_path.is_relative_to(self.root)
+ ):
+ raise ValueError(
+ f"Attempted to access absolute path '{relative_path}' "
+ f"in storage '{self.root}'"
+ )
+
+ full_path = self.root / relative_path
+ if self.is_local:
+ full_path = full_path.resolve()
+ else:
+ full_path = Path(os.path.normpath(full_path))
+
+ logger.debug(f"Joined paths as '{full_path}'")
+
+ if self.restrict_to_root and not full_path.is_relative_to(self.root):
+ raise ValueError(
+ f"Attempted to access path '{full_path}' "
+ f"outside of storage '{self.root}'."
+ )
+
+ return full_path
diff --git a/autogpts/autogpt/autogpt/file_storage/gcs.py b/autogpts/autogpt/autogpt/file_storage/gcs.py
new file mode 100644
index 000000000..45545d449
--- /dev/null
+++ b/autogpts/autogpt/autogpt/file_storage/gcs.py
@@ -0,0 +1,213 @@
+"""
+The GCSWorkspace class provides an interface for interacting with a file workspace, and
+stores the files in a Google Cloud Storage bucket.
+"""
+
+from __future__ import annotations
+
+import inspect
+import logging
+from io import IOBase
+from pathlib import Path
+from typing import Literal
+
+from google.cloud import storage
+from google.cloud.exceptions import NotFound
+
+from autogpt.core.configuration.schema import UserConfigurable
+
+from .base import FileStorage, FileStorageConfiguration
+
+logger = logging.getLogger(__name__)
+
+
+class GCSFileStorageConfiguration(FileStorageConfiguration):
+ bucket: str = UserConfigurable("autogpt", from_env="STORAGE_BUCKET")
+
+
+class GCSFileStorage(FileStorage):
+ """A class that represents a Google Cloud Storage."""
+
+ _bucket: storage.Bucket
+
+ def __init__(self, config: GCSFileStorageConfiguration):
+ self._bucket_name = config.bucket
+ self._root = config.root
+ # Add / at the beginning of the root path
+ if not self._root.is_absolute():
+ self._root = Path("/").joinpath(self._root)
+
+ self._gcs = storage.Client()
+ super().__init__()
+
+ @property
+ def root(self) -> Path:
+ """The root directory of the file storage."""
+ return self._root
+
+ @property
+ def restrict_to_root(self) -> bool:
+ """Whether to restrict generated paths to the root."""
+ return True
+
+ @property
+ def is_local(self) -> bool:
+ """Whether the storage is local (i.e. on the same machine, not cloud-based)."""
+ return False
+
+ def initialize(self) -> None:
+ logger.debug(f"Initializing {repr(self)}...")
+ try:
+ self._bucket = self._gcs.get_bucket(self._bucket_name)
+ except NotFound:
+ logger.info(f"Bucket '{self._bucket_name}' does not exist; creating it...")
+ self._bucket = self._gcs.create_bucket(self._bucket_name)
+
+ def get_path(self, relative_path: str | Path) -> Path:
+ # We set GCS root with "/" at the beginning
+ # but relative_to("/") will remove it
+ # because we don't actually want it in the storage filenames
+ return super().get_path(relative_path).relative_to("/")
+
+ def _get_blob(self, path: str | Path) -> storage.Blob:
+ path = self.get_path(path)
+ return self._bucket.blob(str(path))
+
+ def open_file(
+ self, path: str | Path, mode: Literal["w", "r"] = "r", binary: bool = False
+ ) -> IOBase:
+ """Open a file in the storage."""
+ blob = self._get_blob(path)
+ blob.reload() # pin revision number to prevent version mixing while reading
+ return blob.open(f"{mode}b" if binary else mode)
+
+ def read_file(self, path: str | Path, binary: bool = False) -> str | bytes:
+ """Read a file in the storage."""
+ return self.open_file(path, "r", binary).read()
+
+ async def write_file(self, path: str | Path, content: str | bytes) -> None:
+ """Write to a file in the storage."""
+ blob = self._get_blob(path)
+
+ blob.upload_from_string(
+ data=content,
+ content_type=(
+ "text/plain"
+ if type(content) is str
+ # TODO: get MIME type from file extension or binary content
+ else "application/octet-stream"
+ ),
+ )
+
+ if self.on_write_file:
+ path = Path(path)
+ if path.is_absolute():
+ path = path.relative_to(self.root)
+ res = self.on_write_file(path)
+ if inspect.isawaitable(res):
+ await res
+
+ def list_files(self, path: str | Path = ".") -> list[Path]:
+ """List all files (recursively) in a directory in the storage."""
+ path = self.get_path(path)
+ return [
+ Path(blob.name).relative_to(path)
+ for blob in self._bucket.list_blobs(
+ prefix=f"{path}/" if path != Path(".") else None
+ )
+ ]
+
+ def list_folders(
+ self, path: str | Path = ".", recursive: bool = False
+ ) -> list[Path]:
+ """List 'directories' directly in a given path or recursively in the storage."""
+ path = self.get_path(path)
+ folder_names = set()
+
+ # List objects with the specified prefix and delimiter
+ for blob in self._bucket.list_blobs(prefix=path):
+ # Remove path prefix and the object name (last part)
+ folder = Path(blob.name).relative_to(path).parent
+ if not folder or folder == Path("."):
+ continue
+ # For non-recursive, only add the first level of folders
+ if not recursive:
+ folder_names.add(folder.parts[0])
+ else:
+ # For recursive, need to add all nested folders
+ for i in range(len(folder.parts)):
+ folder_names.add("/".join(folder.parts[: i + 1]))
+
+ return [Path(f) for f in folder_names]
+
+ def delete_file(self, path: str | Path) -> None:
+ """Delete a file in the storage."""
+ path = self.get_path(path)
+ blob = self._bucket.blob(str(path))
+ blob.delete()
+
+ def delete_dir(self, path: str | Path) -> None:
+ """Delete an empty folder in the storage."""
+ # Since GCS does not have directories, we don't need to do anything
+ pass
+
+ def exists(self, path: str | Path) -> bool:
+ """Check if a file or folder exists in GCS storage."""
+ path = self.get_path(path)
+ # Check for exact blob match (file)
+ blob = self._bucket.blob(str(path))
+ if blob.exists():
+ return True
+ # Check for any blobs with prefix (folder)
+ prefix = f"{str(path).rstrip('/')}/"
+ blobs = self._bucket.list_blobs(prefix=prefix, max_results=1)
+ return next(blobs, None) is not None
+
+ def make_dir(self, path: str | Path) -> None:
+ """Create a directory in the storage if doesn't exist."""
+ # GCS does not have directories, so we don't need to do anything
+ pass
+
+ def rename(self, old_path: str | Path, new_path: str | Path) -> None:
+ """Rename a file or folder in the storage."""
+ old_path = self.get_path(old_path)
+ new_path = self.get_path(new_path)
+ blob = self._bucket.blob(str(old_path))
+ # If the blob with exact name exists, rename it
+ if blob.exists():
+ self._bucket.rename_blob(blob, new_name=str(new_path))
+ return
+ # Otherwise, rename all blobs with the prefix (folder)
+ for blob in self._bucket.list_blobs(prefix=f"{old_path}/"):
+ new_name = str(blob.name).replace(str(old_path), str(new_path), 1)
+ self._bucket.rename_blob(blob, new_name=new_name)
+
+ def copy(self, source: str | Path, destination: str | Path) -> None:
+ """Copy a file or folder with all contents in the storage."""
+ source = self.get_path(source)
+ destination = self.get_path(destination)
+ # If the source is a file, copy it
+ if self._bucket.blob(str(source)).exists():
+ self._bucket.copy_blob(
+ self._bucket.blob(str(source)), self._bucket, str(destination)
+ )
+ return
+ # Otherwise, copy all blobs with the prefix (folder)
+ for blob in self._bucket.list_blobs(prefix=f"{source}/"):
+ new_name = str(blob.name).replace(str(source), str(destination), 1)
+ self._bucket.copy_blob(blob, self._bucket, new_name)
+
+ def clone_with_subroot(self, subroot: str | Path) -> GCSFileStorage:
+ """Create a new GCSFileStorage with a subroot of the current storage."""
+ file_storage = GCSFileStorage(
+ GCSFileStorageConfiguration(
+ root=Path("/").joinpath(self.get_path(subroot)),
+ bucket=self._bucket_name,
+ )
+ )
+ file_storage._gcs = self._gcs
+ file_storage._bucket = self._bucket
+ return file_storage
+
+ def __repr__(self) -> str:
+ return f"{__class__.__name__}(bucket='{self._bucket_name}', root={self._root})"
diff --git a/autogpts/autogpt/autogpt/file_storage/local.py b/autogpts/autogpt/autogpt/file_storage/local.py
new file mode 100644
index 000000000..3a52bd572
--- /dev/null
+++ b/autogpts/autogpt/autogpt/file_storage/local.py
@@ -0,0 +1,139 @@
+"""
+The LocalFileStorage class implements a FileStorage that works with local files.
+"""
+
+from __future__ import annotations
+
+import inspect
+import logging
+from pathlib import Path
+from typing import IO, Literal
+
+from .base import FileStorage, FileStorageConfiguration
+
+logger = logging.getLogger(__name__)
+
+
+class LocalFileStorage(FileStorage):
+ """A class that represents a file storage."""
+
+ def __init__(self, config: FileStorageConfiguration):
+ self._root = config.root.resolve()
+ self._restrict_to_root = config.restrict_to_root
+ self.make_dir(self.root)
+ super().__init__()
+
+ @property
+ def root(self) -> Path:
+ """The root directory of the file storage."""
+ return self._root
+
+ @property
+ def restrict_to_root(self) -> bool:
+ """Whether to restrict generated paths to the root."""
+ return self._restrict_to_root
+
+ @property
+ def is_local(self) -> bool:
+ """Whether the storage is local (i.e. on the same machine, not cloud-based)."""
+ return True
+
+ def initialize(self) -> None:
+ self.root.mkdir(exist_ok=True, parents=True)
+
+ def open_file(
+ self, path: str | Path, mode: Literal["w", "r"] = "r", binary: bool = False
+ ) -> IO:
+ """Open a file in the storage."""
+ return self._open_file(path, f"{mode}b" if binary else mode)
+
+ def _open_file(self, path: str | Path, mode: str) -> IO:
+ full_path = self.get_path(path)
+ return open(full_path, mode) # type: ignore
+
+ def read_file(self, path: str | Path, binary: bool = False) -> str | bytes:
+ """Read a file in the storage."""
+ with self._open_file(path, "rb" if binary else "r") as file:
+ return file.read()
+
+ async def write_file(self, path: str | Path, content: str | bytes) -> None:
+ """Write to a file in the storage."""
+ with self._open_file(path, "wb" if type(content) is bytes else "w") as file:
+ file.write(content)
+
+ if self.on_write_file:
+ path = Path(path)
+ if path.is_absolute():
+ path = path.relative_to(self.root)
+ res = self.on_write_file(path)
+ if inspect.isawaitable(res):
+ await res
+
+ def list_files(self, path: str | Path = ".") -> list[Path]:
+ """List all files (recursively) in a directory in the storage."""
+ path = self.get_path(path)
+ return [file.relative_to(path) for file in path.rglob("*") if file.is_file()]
+
+ def list_folders(
+ self, path: str | Path = ".", recursive: bool = False
+ ) -> list[Path]:
+ """List directories directly in a given path or recursively."""
+ path = self.get_path(path)
+ if recursive:
+ return [
+ folder.relative_to(path)
+ for folder in path.rglob("*")
+ if folder.is_dir()
+ ]
+ else:
+ return [
+ folder.relative_to(path) for folder in path.iterdir() if folder.is_dir()
+ ]
+
+ def delete_file(self, path: str | Path) -> None:
+ """Delete a file in the storage."""
+ full_path = self.get_path(path)
+ full_path.unlink()
+
+ def delete_dir(self, path: str | Path) -> None:
+ """Delete an empty folder in the storage."""
+ full_path = self.get_path(path)
+ full_path.rmdir()
+
+ def exists(self, path: str | Path) -> bool:
+ """Check if a file or folder exists in the storage."""
+ return self.get_path(path).exists()
+
+ def make_dir(self, path: str | Path) -> None:
+ """Create a directory in the storage if doesn't exist."""
+ full_path = self.get_path(path)
+ full_path.mkdir(exist_ok=True, parents=True)
+
+ def rename(self, old_path: str | Path, new_path: str | Path) -> None:
+ """Rename a file or folder in the storage."""
+ old_path = self.get_path(old_path)
+ new_path = self.get_path(new_path)
+ old_path.rename(new_path)
+
+ def copy(self, source: str | Path, destination: str | Path) -> None:
+ """Copy a file or folder with all contents in the storage."""
+ source = self.get_path(source)
+ destination = self.get_path(destination)
+ if source.is_file():
+ destination.write_bytes(source.read_bytes())
+ else:
+ destination.mkdir(exist_ok=True, parents=True)
+ for file in source.rglob("*"):
+ if file.is_file():
+ target = destination / file.relative_to(source)
+ target.parent.mkdir(exist_ok=True, parents=True)
+ target.write_bytes(file.read_bytes())
+
+ def clone_with_subroot(self, subroot: str | Path) -> FileStorage:
+ """Create a new LocalFileStorage with a subroot of the current storage."""
+ return LocalFileStorage(
+ FileStorageConfiguration(
+ root=self.get_path(subroot),
+ restrict_to_root=self.restrict_to_root,
+ )
+ )
diff --git a/autogpts/autogpt/autogpt/file_storage/s3.py b/autogpts/autogpt/autogpt/file_storage/s3.py
new file mode 100644
index 000000000..f8ac15fe7
--- /dev/null
+++ b/autogpts/autogpt/autogpt/file_storage/s3.py
@@ -0,0 +1,265 @@
+"""
+The S3Workspace class provides an interface for interacting with a file workspace, and
+stores the files in an S3 bucket.
+"""
+
+from __future__ import annotations
+
+import contextlib
+import inspect
+import logging
+from io import IOBase, TextIOWrapper
+from pathlib import Path
+from typing import TYPE_CHECKING, Literal, Optional
+
+import boto3
+import botocore.exceptions
+from pydantic import SecretStr
+
+from autogpt.core.configuration.schema import UserConfigurable
+
+from .base import FileStorage, FileStorageConfiguration
+
+if TYPE_CHECKING:
+ import mypy_boto3_s3
+
+logger = logging.getLogger(__name__)
+
+
+class S3FileStorageConfiguration(FileStorageConfiguration):
+ bucket: str = UserConfigurable("autogpt", from_env="STORAGE_BUCKET")
+ s3_endpoint_url: Optional[SecretStr] = UserConfigurable(from_env="S3_ENDPOINT_URL")
+
+
+class S3FileStorage(FileStorage):
+ """A class that represents an S3 storage."""
+
+ _bucket: mypy_boto3_s3.service_resource.Bucket
+
+ def __init__(self, config: S3FileStorageConfiguration):
+ self._bucket_name = config.bucket
+ self._root = config.root
+ # Add / at the beginning of the root path
+ if not self._root.is_absolute():
+ self._root = Path("/").joinpath(self._root)
+
+ # https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html
+ self._s3 = boto3.resource(
+ "s3",
+ endpoint_url=(
+ config.s3_endpoint_url.get_secret_value()
+ if config.s3_endpoint_url
+ else None
+ ),
+ )
+
+ super().__init__()
+
+ @property
+ def root(self) -> Path:
+ """The root directory of the file storage."""
+ return self._root
+
+ @property
+ def restrict_to_root(self):
+ """Whether to restrict generated paths to the root."""
+ return True
+
+ @property
+ def is_local(self) -> bool:
+ """Whether the storage is local (i.e. on the same machine, not cloud-based)."""
+ return False
+
+ def initialize(self) -> None:
+ logger.debug(f"Initializing {repr(self)}...")
+ try:
+ self._s3.meta.client.head_bucket(Bucket=self._bucket_name)
+ self._bucket = self._s3.Bucket(self._bucket_name)
+ except botocore.exceptions.ClientError as e:
+ if "(404)" not in str(e):
+ raise
+ logger.info(f"Bucket '{self._bucket_name}' does not exist; creating it...")
+ self._bucket = self._s3.create_bucket(Bucket=self._bucket_name)
+
+ def get_path(self, relative_path: str | Path) -> Path:
+ # We set S3 root with "/" at the beginning
+ # but relative_to("/") will remove it
+ # because we don't actually want it in the storage filenames
+ return super().get_path(relative_path).relative_to("/")
+
+ def _get_obj(self, path: str | Path) -> mypy_boto3_s3.service_resource.Object:
+ """Get an S3 object."""
+ path = self.get_path(path)
+ obj = self._bucket.Object(str(path))
+ with contextlib.suppress(botocore.exceptions.ClientError):
+ obj.load()
+ return obj
+
+ def open_file(
+ self, path: str | Path, mode: Literal["w", "r"] = "r", binary: bool = False
+ ) -> IOBase:
+ """Open a file in the storage."""
+ obj = self._get_obj(path)
+ return obj.get()["Body"] if binary else TextIOWrapper(obj.get()["Body"])
+
+ def read_file(self, path: str | Path, binary: bool = False) -> str | bytes:
+ """Read a file in the storage."""
+ return self.open_file(path, binary=binary).read()
+
+ async def write_file(self, path: str | Path, content: str | bytes) -> None:
+ """Write to a file in the storage."""
+ obj = self._get_obj(path)
+ obj.put(Body=content)
+
+ if self.on_write_file:
+ path = Path(path)
+ if path.is_absolute():
+ path = path.relative_to(self.root)
+ res = self.on_write_file(path)
+ if inspect.isawaitable(res):
+ await res
+
+ def list_files(self, path: str | Path = ".") -> list[Path]:
+ """List all files (recursively) in a directory in the storage."""
+ path = self.get_path(path)
+ if path == Path("."): # root level of bucket
+ return [Path(obj.key) for obj in self._bucket.objects.all()]
+ else:
+ return [
+ Path(obj.key).relative_to(path)
+ for obj in self._bucket.objects.filter(Prefix=f"{path}/")
+ ]
+
+ def list_folders(
+ self, path: str | Path = ".", recursive: bool = False
+ ) -> list[Path]:
+ """List 'directories' directly in a given path or recursively in the storage."""
+ path = self.get_path(path)
+ folder_names = set()
+
+ # List objects with the specified prefix and delimiter
+ for obj_summary in self._bucket.objects.filter(Prefix=str(path)):
+ # Remove path prefix and the object name (last part)
+ folder = Path(obj_summary.key).relative_to(path).parent
+ if not folder or folder == Path("."):
+ continue
+ # For non-recursive, only add the first level of folders
+ if not recursive:
+ folder_names.add(folder.parts[0])
+ else:
+ # For recursive, need to add all nested folders
+ for i in range(len(folder.parts)):
+ folder_names.add("/".join(folder.parts[: i + 1]))
+
+ return [Path(f) for f in folder_names]
+
+ def delete_file(self, path: str | Path) -> None:
+ """Delete a file in the storage."""
+ path = self.get_path(path)
+ obj = self._s3.Object(self._bucket_name, str(path))
+ obj.delete()
+
+ def delete_dir(self, path: str | Path) -> None:
+ """Delete an empty folder in the storage."""
+ # S3 does not have directories, so we don't need to do anything
+ pass
+
+ def exists(self, path: str | Path) -> bool:
+ """Check if a file or folder exists in S3 storage."""
+ path = self.get_path(path)
+ try:
+ # Check for exact object match (file)
+ self._s3.meta.client.head_object(Bucket=self._bucket_name, Key=str(path))
+ return True
+ except botocore.exceptions.ClientError as e:
+ if int(e.response["ResponseMetadata"]["HTTPStatusCode"]) == 404:
+ # If the object does not exist,
+ # check for objects with the prefix (folder)
+ prefix = f"{str(path).rstrip('/')}/"
+ objs = list(self._bucket.objects.filter(Prefix=prefix, MaxKeys=1))
+ return len(objs) > 0 # True if any objects exist with the prefix
+ else:
+ raise # Re-raise for any other client errors
+
+ def make_dir(self, path: str | Path) -> None:
+ """Create a directory in the storage if doesn't exist."""
+ # S3 does not have directories, so we don't need to do anything
+ pass
+
+ def rename(self, old_path: str | Path, new_path: str | Path) -> None:
+ """Rename a file or folder in the storage."""
+ old_path = str(self.get_path(old_path))
+ new_path = str(self.get_path(new_path))
+
+ try:
+ # If file exists, rename it
+ self._s3.meta.client.head_object(Bucket=self._bucket_name, Key=old_path)
+ self._s3.meta.client.copy_object(
+ CopySource={"Bucket": self._bucket_name, "Key": old_path},
+ Bucket=self._bucket_name,
+ Key=new_path,
+ )
+ self._s3.meta.client.delete_object(Bucket=self._bucket_name, Key=old_path)
+ except botocore.exceptions.ClientError as e:
+ if int(e.response["ResponseMetadata"]["HTTPStatusCode"]) == 404:
+ # If the object does not exist,
+ # it may be a folder
+ prefix = f"{old_path.rstrip('/')}/"
+ objs = list(self._bucket.objects.filter(Prefix=prefix))
+ for obj in objs:
+ new_key = new_path + obj.key[len(old_path) :]
+ self._s3.meta.client.copy_object(
+ CopySource={"Bucket": self._bucket_name, "Key": obj.key},
+ Bucket=self._bucket_name,
+ Key=new_key,
+ )
+ self._s3.meta.client.delete_object(
+ Bucket=self._bucket_name, Key=obj.key
+ )
+ else:
+ raise # Re-raise for any other client errors
+
+ def copy(self, source: str | Path, destination: str | Path) -> None:
+ """Copy a file or folder with all contents in the storage."""
+ source = str(self.get_path(source))
+ destination = str(self.get_path(destination))
+
+ try:
+ # If source is a file, copy it
+ self._s3.meta.client.head_object(Bucket=self._bucket_name, Key=source)
+ self._s3.meta.client.copy_object(
+ CopySource={"Bucket": self._bucket_name, "Key": source},
+ Bucket=self._bucket_name,
+ Key=destination,
+ )
+ except botocore.exceptions.ClientError as e:
+ if int(e.response["ResponseMetadata"]["HTTPStatusCode"]) == 404:
+ # If the object does not exist,
+ # it may be a folder
+ prefix = f"{source.rstrip('/')}/"
+ objs = list(self._bucket.objects.filter(Prefix=prefix))
+ for obj in objs:
+ new_key = destination + obj.key[len(source) :]
+ self._s3.meta.client.copy_object(
+ CopySource={"Bucket": self._bucket_name, "Key": obj.key},
+ Bucket=self._bucket_name,
+ Key=new_key,
+ )
+ else:
+ raise
+
+ def clone_with_subroot(self, subroot: str | Path) -> S3FileStorage:
+ """Create a new S3FileStorage with a subroot of the current storage."""
+ file_storage = S3FileStorage(
+ S3FileStorageConfiguration(
+ bucket=self._bucket_name,
+ root=Path("/").joinpath(self.get_path(subroot)),
+ s3_endpoint_url=self._s3.meta.client.meta.endpoint_url,
+ )
+ )
+ file_storage._s3 = self._s3
+ file_storage._bucket = self._bucket
+ return file_storage
+
+ def __repr__(self) -> str:
+ return f"{__class__.__name__}(bucket='{self._bucket_name}', root={self._root})"
diff --git a/autogpts/autogpt/autogpt/file_workspace/__init__.py b/autogpts/autogpt/autogpt/file_workspace/__init__.py
deleted file mode 100644
index a0e06e38f..000000000
--- a/autogpts/autogpt/autogpt/file_workspace/__init__.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import enum
-from pathlib import Path
-from typing import Optional
-
-from .base import FileWorkspace
-
-
-class FileWorkspaceBackendName(str, enum.Enum):
- LOCAL = "local"
- GCS = "gcs"
- S3 = "s3"
-
-
-def get_workspace(
- backend: FileWorkspaceBackendName, *, id: str = "", root_path: Optional[Path] = None
-) -> FileWorkspace:
- assert bool(root_path) != bool(id), "Specify root_path or id to get workspace"
- if root_path is None:
- root_path = Path(f"/workspaces/{id}")
-
- match backend:
- case FileWorkspaceBackendName.LOCAL:
- from .local import FileWorkspaceConfiguration, LocalFileWorkspace
-
- config = FileWorkspaceConfiguration.from_env()
- config.root = root_path
- return LocalFileWorkspace(config)
- case FileWorkspaceBackendName.S3:
- from .s3 import S3FileWorkspace, S3FileWorkspaceConfiguration
-
- config = S3FileWorkspaceConfiguration.from_env()
- config.root = root_path
- return S3FileWorkspace(config)
- case FileWorkspaceBackendName.GCS:
- from .gcs import GCSFileWorkspace, GCSFileWorkspaceConfiguration
-
- config = GCSFileWorkspaceConfiguration.from_env()
- config.root = root_path
- return GCSFileWorkspace(config)
-
-
-__all__ = [
- "FileWorkspace",
- "FileWorkspaceBackendName",
- "get_workspace",
-]
diff --git a/autogpts/autogpt/autogpt/file_workspace/base.py b/autogpts/autogpt/autogpt/file_workspace/base.py
deleted file mode 100644
index 865b34dd5..000000000
--- a/autogpts/autogpt/autogpt/file_workspace/base.py
+++ /dev/null
@@ -1,164 +0,0 @@
-"""
-The FileWorkspace class provides an interface for interacting with a file workspace.
-"""
-from __future__ import annotations
-
-import logging
-from abc import ABC, abstractmethod
-from io import IOBase, TextIOBase
-from pathlib import Path
-from typing import IO, Any, BinaryIO, Callable, Literal, Optional, TextIO, overload
-
-from autogpt.core.configuration.schema import SystemConfiguration
-
-logger = logging.getLogger(__name__)
-
-
-class FileWorkspaceConfiguration(SystemConfiguration):
- restrict_to_root: bool = True
- root: Path = Path("/")
-
-
-class FileWorkspace(ABC):
- """A class that represents a file workspace."""
-
- on_write_file: Callable[[Path], Any] | None = None
- """
- Event hook, executed after writing a file.
-
- Params:
- Path: The path of the file that was written, relative to the workspace root.
- """
-
- @property
- @abstractmethod
- def root(self) -> Path:
- """The root path of the file workspace."""
-
- @property
- @abstractmethod
- def restrict_to_root(self) -> bool:
- """Whether to restrict file access to within the workspace's root path."""
-
- @abstractmethod
- def initialize(self) -> None:
- """
- Calling `initialize()` should bring the workspace to a ready-to-use state.
- For example, it can create the resource in which files will be stored, if it
- doesn't exist yet. E.g. a folder on disk, or an S3 Bucket.
- """
-
- @overload
- @abstractmethod
- def open_file(
- self, path: str | Path, binary: Literal[False] = False
- ) -> TextIO | TextIOBase:
- """Returns a readable text file-like object representing the file."""
-
- @overload
- @abstractmethod
- def open_file(
- self, path: str | Path, binary: Literal[True] = True
- ) -> BinaryIO | IOBase:
- """Returns a readable binary file-like object representing the file."""
-
- @abstractmethod
- def open_file(self, path: str | Path, binary: bool = False) -> IO | IOBase:
- """Returns a readable file-like object representing the file."""
-
- @overload
- @abstractmethod
- def read_file(self, path: str | Path, binary: Literal[False] = False) -> str:
- """Read a file in the workspace as text."""
- ...
-
- @overload
- @abstractmethod
- def read_file(self, path: str | Path, binary: Literal[True] = True) -> bytes:
- """Read a file in the workspace as binary."""
- ...
-
- @abstractmethod
- def read_file(self, path: str | Path, binary: bool = False) -> str | bytes:
- """Read a file in the workspace."""
-
- @abstractmethod
- async def write_file(self, path: str | Path, content: str | bytes) -> None:
- """Write to a file in the workspace."""
-
- @abstractmethod
- def list(self, path: str | Path = ".") -> list[Path]:
- """List all files (recursively) in a directory in the workspace."""
-
- @abstractmethod
- def delete_file(self, path: str | Path) -> None:
- """Delete a file in the workspace."""
-
- def get_path(self, relative_path: str | Path) -> Path:
- """Get the full path for an item in the workspace.
-
- Parameters:
- relative_path: The relative path to resolve in the workspace.
-
- Returns:
- Path: The resolved path relative to the workspace.
- """
- return self._sanitize_path(relative_path, self.root)
-
- @staticmethod
- def _sanitize_path(
- relative_path: str | Path,
- root: Optional[str | Path] = None,
- restrict_to_root: bool = True,
- ) -> Path:
- """Resolve the relative path within the given root if possible.
-
- Parameters:
- relative_path: The relative path to resolve.
- root: The root path to resolve the relative path within.
- restrict_to_root: Whether to restrict the path to the root.
-
- Returns:
- Path: The resolved path.
-
- Raises:
- ValueError: If the path is absolute and a root is provided.
- ValueError: If the path is outside the root and the root is restricted.
- """
-
- # Posix systems disallow null bytes in paths. Windows is agnostic about it.
- # Do an explicit check here for all sorts of null byte representations.
-
- if "\0" in str(relative_path) or "\0" in str(root):
- raise ValueError("embedded null byte")
-
- if root is None:
- return Path(relative_path).resolve()
-
- logger.debug(f"Resolving path '{relative_path}' in workspace '{root}'")
-
- root, relative_path = Path(root).resolve(), Path(relative_path)
-
- logger.debug(f"Resolved root as '{root}'")
-
- # Allow absolute paths if they are contained in the workspace.
- if (
- relative_path.is_absolute()
- and restrict_to_root
- and not relative_path.is_relative_to(root)
- ):
- raise ValueError(
- f"Attempted to access absolute path '{relative_path}' "
- f"in workspace '{root}'."
- )
-
- full_path = root.joinpath(relative_path).resolve()
-
- logger.debug(f"Joined paths as '{full_path}'")
-
- if restrict_to_root and not full_path.is_relative_to(root):
- raise ValueError(
- f"Attempted to access path '{full_path}' outside of workspace '{root}'."
- )
-
- return full_path
diff --git a/autogpts/autogpt/autogpt/file_workspace/gcs.py b/autogpts/autogpt/autogpt/file_workspace/gcs.py
deleted file mode 100644
index c6ff3fc97..000000000
--- a/autogpts/autogpt/autogpt/file_workspace/gcs.py
+++ /dev/null
@@ -1,108 +0,0 @@
-"""
-The GCSWorkspace class provides an interface for interacting with a file workspace, and
-stores the files in a Google Cloud Storage bucket.
-"""
-from __future__ import annotations
-
-import inspect
-import logging
-from io import IOBase
-from pathlib import Path
-
-from google.cloud import storage
-from google.cloud.exceptions import NotFound
-
-from autogpt.core.configuration.schema import UserConfigurable
-
-from .base import FileWorkspace, FileWorkspaceConfiguration
-
-logger = logging.getLogger(__name__)
-
-
-class GCSFileWorkspaceConfiguration(FileWorkspaceConfiguration):
- bucket: str = UserConfigurable("autogpt", from_env="WORKSPACE_STORAGE_BUCKET")
-
-
-class GCSFileWorkspace(FileWorkspace):
- """A class that represents a Google Cloud Storage workspace."""
-
- _bucket: storage.Bucket
-
- def __init__(self, config: GCSFileWorkspaceConfiguration):
- self._bucket_name = config.bucket
- self._root = config.root
- assert self._root.is_absolute()
-
- self._gcs = storage.Client()
- super().__init__()
-
- @property
- def root(self) -> Path:
- """The root directory of the file workspace."""
- return self._root
-
- @property
- def restrict_to_root(self) -> bool:
- """Whether to restrict generated paths to the root."""
- return True
-
- def initialize(self) -> None:
- logger.debug(f"Initializing {repr(self)}...")
- try:
- self._bucket = self._gcs.get_bucket(self._bucket_name)
- except NotFound:
- logger.info(f"Bucket '{self._bucket_name}' does not exist; creating it...")
- self._bucket = self._gcs.create_bucket(self._bucket_name)
-
- def get_path(self, relative_path: str | Path) -> Path:
- return super().get_path(relative_path).relative_to("/")
-
- def _get_blob(self, path: str | Path) -> storage.Blob:
- path = self.get_path(path)
- return self._bucket.blob(str(path))
-
- def open_file(self, path: str | Path, binary: bool = False) -> IOBase:
- """Open a file in the workspace."""
- blob = self._get_blob(path)
- blob.reload() # pin revision number to prevent version mixing while reading
- return blob.open("rb" if binary else "r")
-
- def read_file(self, path: str | Path, binary: bool = False) -> str | bytes:
- """Read a file in the workspace."""
- return self.open_file(path, binary).read()
-
- async def write_file(self, path: str | Path, content: str | bytes) -> None:
- """Write to a file in the workspace."""
- blob = self._get_blob(path)
-
- if isinstance(content, str):
- blob.upload_from_string(content)
- else:
- blob.upload_from_file(content)
-
- if self.on_write_file:
- path = Path(path)
- if path.is_absolute():
- path = path.relative_to(self.root)
- res = self.on_write_file(path)
- if inspect.isawaitable(res):
- await res
-
- def list(self, path: str | Path = ".") -> list[Path]:
- """List all files (recursively) in a directory in the workspace."""
- path = self.get_path(path)
- return [
- Path(blob.name).relative_to(path)
- for blob in self._bucket.list_blobs(
- prefix=f"{path}/" if path != Path(".") else None
- )
- ]
-
- def delete_file(self, path: str | Path) -> None:
- """Delete a file in the workspace."""
- path = self.get_path(path)
- blob = self._bucket.blob(str(path))
- blob.delete()
-
- def __repr__(self) -> str:
- return f"{__class__.__name__}(bucket='{self._bucket_name}', root={self._root})"
diff --git a/autogpts/autogpt/autogpt/file_workspace/local.py b/autogpts/autogpt/autogpt/file_workspace/local.py
deleted file mode 100644
index 8c2aa6521..000000000
--- a/autogpts/autogpt/autogpt/file_workspace/local.py
+++ /dev/null
@@ -1,71 +0,0 @@
-"""
-The LocalFileWorkspace class implements a FileWorkspace that works with local files.
-"""
-from __future__ import annotations
-
-import inspect
-import logging
-from pathlib import Path
-from typing import IO
-
-from .base import FileWorkspace, FileWorkspaceConfiguration
-
-logger = logging.getLogger(__name__)
-
-
-class LocalFileWorkspace(FileWorkspace):
- """A class that represents a file workspace."""
-
- def __init__(self, config: FileWorkspaceConfiguration):
- self._root = self._sanitize_path(config.root)
- self._restrict_to_root = config.restrict_to_root
- super().__init__()
-
- @property
- def root(self) -> Path:
- """The root directory of the file workspace."""
- return self._root
-
- @property
- def restrict_to_root(self) -> bool:
- """Whether to restrict generated paths to the root."""
- return self._restrict_to_root
-
- def initialize(self) -> None:
- self.root.mkdir(exist_ok=True, parents=True)
-
- def open_file(self, path: str | Path, binary: bool = False) -> IO:
- """Open a file in the workspace."""
- return self._open_file(path, "rb" if binary else "r")
-
- def _open_file(self, path: str | Path, mode: str = "r") -> IO:
- full_path = self.get_path(path)
- return open(full_path, mode) # type: ignore
-
- def read_file(self, path: str | Path, binary: bool = False) -> str | bytes:
- """Read a file in the workspace."""
- with self._open_file(path, "rb" if binary else "r") as file:
- return file.read()
-
- async def write_file(self, path: str | Path, content: str | bytes) -> None:
- """Write to a file in the workspace."""
- with self._open_file(path, "wb" if type(content) is bytes else "w") as file:
- file.write(content)
-
- if self.on_write_file:
- path = Path(path)
- if path.is_absolute():
- path = path.relative_to(self.root)
- res = self.on_write_file(path)
- if inspect.isawaitable(res):
- await res
-
- def list(self, path: str | Path = ".") -> list[Path]:
- """List all files (recursively) in a directory in the workspace."""
- path = self.get_path(path)
- return [file.relative_to(path) for file in path.rglob("*") if file.is_file()]
-
- def delete_file(self, path: str | Path) -> None:
- """Delete a file in the workspace."""
- full_path = self.get_path(path)
- full_path.unlink()
diff --git a/autogpts/autogpt/autogpt/file_workspace/s3.py b/autogpts/autogpt/autogpt/file_workspace/s3.py
deleted file mode 100644
index a60291374..000000000
--- a/autogpts/autogpt/autogpt/file_workspace/s3.py
+++ /dev/null
@@ -1,128 +0,0 @@
-"""
-The S3Workspace class provides an interface for interacting with a file workspace, and
-stores the files in an S3 bucket.
-"""
-from __future__ import annotations
-
-import contextlib
-import inspect
-import logging
-import os
-from io import IOBase, TextIOWrapper
-from pathlib import Path
-from typing import TYPE_CHECKING, Optional
-
-import boto3
-import botocore.exceptions
-from pydantic import SecretStr
-
-from autogpt.core.configuration.schema import UserConfigurable
-
-from .base import FileWorkspace, FileWorkspaceConfiguration
-
-if TYPE_CHECKING:
- import mypy_boto3_s3
-
-logger = logging.getLogger(__name__)
-
-
-class S3FileWorkspaceConfiguration(FileWorkspaceConfiguration):
- bucket: str = UserConfigurable("autogpt", from_env="WORKSPACE_STORAGE_BUCKET")
- s3_endpoint_url: Optional[SecretStr] = UserConfigurable(
- from_env=lambda: SecretStr(v) if (v := os.getenv("S3_ENDPOINT_URL")) else None
- )
-
-
-class S3FileWorkspace(FileWorkspace):
- """A class that represents an S3 workspace."""
-
- _bucket: mypy_boto3_s3.service_resource.Bucket
-
- def __init__(self, config: S3FileWorkspaceConfiguration):
- self._bucket_name = config.bucket
- self._root = config.root
- assert self._root.is_absolute()
-
- # https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html
- self._s3 = boto3.resource(
- "s3",
- endpoint_url=config.s3_endpoint_url.get_secret_value()
- if config.s3_endpoint_url
- else None,
- )
-
- super().__init__()
-
- @property
- def root(self) -> Path:
- """The root directory of the file workspace."""
- return self._root
-
- @property
- def restrict_to_root(self):
- """Whether to restrict generated paths to the root."""
- return True
-
- def initialize(self) -> None:
- logger.debug(f"Initializing {repr(self)}...")
- try:
- self._s3.meta.client.head_bucket(Bucket=self._bucket_name)
- self._bucket = self._s3.Bucket(self._bucket_name)
- except botocore.exceptions.ClientError as e:
- if "(404)" not in str(e):
- raise
- logger.info(f"Bucket '{self._bucket_name}' does not exist; creating it...")
- self._bucket = self._s3.create_bucket(Bucket=self._bucket_name)
-
- def get_path(self, relative_path: str | Path) -> Path:
- return super().get_path(relative_path).relative_to("/")
-
- def _get_obj(self, path: str | Path) -> mypy_boto3_s3.service_resource.Object:
- """Get an S3 object."""
- path = self.get_path(path)
- obj = self._bucket.Object(str(path))
- with contextlib.suppress(botocore.exceptions.ClientError):
- obj.load()
- return obj
-
- def open_file(self, path: str | Path, binary: bool = False) -> IOBase:
- """Open a file in the workspace."""
- obj = self._get_obj(path)
- return obj.get()["Body"] if binary else TextIOWrapper(obj.get()["Body"])
-
- def read_file(self, path: str | Path, binary: bool = False) -> str | bytes:
- """Read a file in the workspace."""
- return self.open_file(path, binary).read()
-
- async def write_file(self, path: str | Path, content: str | bytes) -> None:
- """Write to a file in the workspace."""
- obj = self._get_obj(path)
- obj.put(Body=content)
-
- if self.on_write_file:
- path = Path(path)
- if path.is_absolute():
- path = path.relative_to(self.root)
- res = self.on_write_file(path)
- if inspect.isawaitable(res):
- await res
-
- def list(self, path: str | Path = ".") -> list[Path]:
- """List all files (recursively) in a directory in the workspace."""
- path = self.get_path(path)
- if path == Path("."): # root level of bucket
- return [Path(obj.key) for obj in self._bucket.objects.all()]
- else:
- return [
- Path(obj.key).relative_to(path)
- for obj in self._bucket.objects.filter(Prefix=f"{path}/")
- ]
-
- def delete_file(self, path: str | Path) -> None:
- """Delete a file in the workspace."""
- path = self.get_path(path)
- obj = self._s3.Object(self._bucket_name, str(path))
- obj.delete()
-
- def __repr__(self) -> str:
- return f"{__class__.__name__}(bucket='{self._bucket_name}', root={self._root})"
diff --git a/autogpts/autogpt/autogpt/json_utils/__init__.py b/autogpts/autogpt/autogpt/json_utils/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/autogpts/autogpt/autogpt/json_utils/__init__.py
+++ /dev/null
diff --git a/autogpts/autogpt/autogpt/json_utils/utilities.py b/autogpts/autogpt/autogpt/json_utils/utilities.py
deleted file mode 100644
index 80ef8cee3..000000000
--- a/autogpts/autogpt/autogpt/json_utils/utilities.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""Utilities for the json_fixes package."""
-import ast
-import logging
-import re
-from typing import Any
-
-logger = logging.getLogger(__name__)
-
-
-def extract_dict_from_response(response_content: str) -> dict[str, Any]:
- # Sometimes the response includes the JSON in a code block with ```
- pattern = r"```([\s\S]*?)```"
- match = re.search(pattern, response_content)
-
- if match:
- response_content = match.group(1).strip()
- # Remove language names in code blocks
- response_content = response_content.lstrip("json")
- else:
- # The string may contain JSON.
- json_pattern = r"{.*}"
- match = re.search(json_pattern, response_content)
-
- if match:
- response_content = match.group()
-
- # Response content comes from OpenAI as a Python `str(content_dict)`.
- # `literal_eval` does the reverse of `str(dict)`.
- try:
- return ast.literal_eval(response_content)
- except BaseException as e:
- logger.info(f"Error parsing JSON response with literal_eval {e}")
- logger.debug(f"Invalid JSON received in response:\n{response_content}")
- # TODO: How to raise an error here without causing the program to exit?
- return {}
diff --git a/autogpts/autogpt/autogpt/llm/api_manager.py b/autogpts/autogpt/autogpt/llm/api_manager.py
deleted file mode 100644
index 146263626..000000000
--- a/autogpts/autogpt/autogpt/llm/api_manager.py
+++ /dev/null
@@ -1,111 +0,0 @@
-from __future__ import annotations
-
-import logging
-from typing import List, Optional
-
-import openai
-from openai import Model
-
-from autogpt.core.resource.model_providers.openai import OPEN_AI_MODELS
-from autogpt.core.resource.model_providers.schema import ChatModelInfo
-from autogpt.singleton import Singleton
-
-logger = logging.getLogger(__name__)
-
-
-class ApiManager(metaclass=Singleton):
- def __init__(self):
- self.total_prompt_tokens = 0
- self.total_completion_tokens = 0
- self.total_cost = 0
- self.total_budget = 0
- self.models: Optional[list[Model]] = None
-
- def reset(self):
- self.total_prompt_tokens = 0
- self.total_completion_tokens = 0
- self.total_cost = 0
- self.total_budget = 0.0
- self.models = None
-
- def update_cost(self, prompt_tokens, completion_tokens, model):
- """
- Update the total cost, prompt tokens, and completion tokens.
-
- Args:
- prompt_tokens (int): The number of tokens used in the prompt.
- completion_tokens (int): The number of tokens used in the completion.
- model (str): The model used for the API call.
- """
- # the .model property in API responses can contain version suffixes like -v2
- model = model[:-3] if model.endswith("-v2") else model
- model_info = OPEN_AI_MODELS[model]
-
- self.total_prompt_tokens += prompt_tokens
- self.total_completion_tokens += completion_tokens
- self.total_cost += prompt_tokens * model_info.prompt_token_cost / 1000
- if isinstance(model_info, ChatModelInfo):
- self.total_cost += (
- completion_tokens * model_info.completion_token_cost / 1000
- )
-
- logger.debug(f"Total running cost: ${self.total_cost:.3f}")
-
- def set_total_budget(self, total_budget):
- """
- Sets the total user-defined budget for API calls.
-
- Args:
- total_budget (float): The total budget for API calls.
- """
- self.total_budget = total_budget
-
- def get_total_prompt_tokens(self):
- """
- Get the total number of prompt tokens.
-
- Returns:
- int: The total number of prompt tokens.
- """
- return self.total_prompt_tokens
-
- def get_total_completion_tokens(self):
- """
- Get the total number of completion tokens.
-
- Returns:
- int: The total number of completion tokens.
- """
- return self.total_completion_tokens
-
- def get_total_cost(self):
- """
- Get the total cost of API calls.
-
- Returns:
- float: The total cost of API calls.
- """
- return self.total_cost
-
- def get_total_budget(self):
- """
- Get the total user-defined budget for API calls.
-
- Returns:
- float: The total budget for API calls.
- """
- return self.total_budget
-
- def get_models(self, **openai_credentials) -> List[Model]:
- """
- Get list of available GPT models.
-
- Returns:
- list: List of available GPT models.
-
- """
- if self.models is None:
- all_models = openai.Model.list(**openai_credentials)["data"]
- self.models = [model for model in all_models if "gpt" in model["id"]]
-
- return self.models
diff --git a/autogpts/autogpt/autogpt/logs/config.py b/autogpts/autogpt/autogpt/logs/config.py
index 2cd5877fc..4a849736a 100644
--- a/autogpts/autogpt/autogpt/logs/config.py
+++ b/autogpts/autogpt/autogpt/logs/config.py
@@ -9,7 +9,7 @@ from pathlib import Path
from typing import TYPE_CHECKING, Optional
from auto_gpt_plugin_template import AutoGPTPluginTemplate
-from openai.util import logger as openai_logger
+from openai._base_client import log as openai_logger
if TYPE_CHECKING:
from autogpt.config import Config
@@ -57,8 +57,7 @@ class LoggingConfig(SystemConfiguration):
# Console output
log_format: LogFormatName = UserConfigurable(
- default=LogFormatName.SIMPLE,
- from_env=lambda: LogFormatName(os.getenv("LOG_FORMAT", "simple")),
+ default=LogFormatName.SIMPLE, from_env="LOG_FORMAT"
)
plain_console_output: bool = UserConfigurable(
default=False,
@@ -69,35 +68,65 @@ class LoggingConfig(SystemConfiguration):
log_dir: Path = LOG_DIR
log_file_format: Optional[LogFormatName] = UserConfigurable(
default=LogFormatName.SIMPLE,
- from_env=lambda: LogFormatName(
- os.getenv("LOG_FILE_FORMAT", os.getenv("LOG_FORMAT", "simple"))
+ from_env=lambda: os.getenv(
+ "LOG_FILE_FORMAT", os.getenv("LOG_FORMAT", "simple")
),
)
def configure_logging(
- level: int = logging.INFO,
- log_dir: Path = LOG_DIR,
- log_format: Optional[LogFormatName] = None,
- log_file_format: Optional[LogFormatName] = None,
- plain_console_output: bool = False,
+ debug: bool = False,
+ level: Optional[int | str] = None,
+ log_dir: Optional[Path] = None,
+ log_format: Optional[LogFormatName | str] = None,
+ log_file_format: Optional[LogFormatName | str] = None,
+ plain_console_output: Optional[bool] = None,
tts_config: Optional[TTSConfig] = None,
) -> None:
- """Configure the native logging module.
+ """Configure the native logging module, based on the environment config and any
+ specified overrides.
+
+ Arguments override values specified in the environment.
Should be usable as `configure_logging(**config.logging.dict())`, where
`config.logging` is a `LoggingConfig` object.
"""
-
- # Auto-adjust default log format based on log level
- log_format = log_format or (
- LogFormatName.SIMPLE if level != logging.DEBUG else LogFormatName.DEBUG
+ if debug and level:
+ raise ValueError("Only one of either 'debug' and 'level' arguments may be set")
+
+ # Parse arguments
+ if isinstance(level, str):
+ if type(_level := logging.getLevelName(level.upper())) is int:
+ level = _level
+ else:
+ raise ValueError(f"Unknown log level '{level}'")
+ if isinstance(log_format, str):
+ if log_format in LogFormatName._value2member_map_:
+ log_format = LogFormatName(log_format)
+ elif not isinstance(log_format, LogFormatName):
+ raise ValueError(f"Unknown log format '{log_format}'")
+ if isinstance(log_file_format, str):
+ if log_file_format in LogFormatName._value2member_map_:
+ log_file_format = LogFormatName(log_file_format)
+ elif not isinstance(log_file_format, LogFormatName):
+ raise ValueError(f"Unknown log format '{log_format}'")
+
+ config = LoggingConfig.from_env()
+
+ # Aggregate arguments + env config
+ level = logging.DEBUG if debug else level or config.level
+ log_dir = log_dir or config.log_dir
+ log_format = log_format or (LogFormatName.DEBUG if debug else config.log_format)
+ log_file_format = log_file_format or log_format or config.log_file_format
+ plain_console_output = (
+ plain_console_output
+ if plain_console_output is not None
+ else config.plain_console_output
)
- log_file_format = log_file_format or log_format
-
- structured_logging = log_format == LogFormatName.STRUCTURED
- if structured_logging:
+ # Structured logging is used for cloud environments,
+ # where logging to a file makes no sense.
+ if log_format == LogFormatName.STRUCTURED:
plain_console_output = True
log_file_format = None
@@ -184,7 +213,7 @@ def configure_logging(
json_logger.propagate = False
# Disable debug logging from OpenAI library
- openai_logger.setLevel(logging.INFO)
+ openai_logger.setLevel(logging.WARNING)
def configure_chat_plugins(config: Config) -> None:
diff --git a/autogpts/autogpt/autogpt/logs/utils.py b/autogpts/autogpt/autogpt/logs/utils.py
index 0b92e2967..d9f39af30 100644
--- a/autogpts/autogpt/autogpt/logs/utils.py
+++ b/autogpts/autogpt/autogpt/logs/utils.py
@@ -3,3 +3,7 @@ import re
def remove_color_codes(s: str) -> str:
return re.sub(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])", "", s)
+
+
+def fmt_kwargs(kwargs: dict) -> str:
+ return ", ".join(f"{n}={repr(v)}" for n, v in kwargs.items())
diff --git a/autogpts/autogpt/autogpt/models/action_history.py b/autogpts/autogpt/autogpt/models/action_history.py
index b36d7e540..51806fb03 100644
--- a/autogpts/autogpt/autogpt/models/action_history.py
+++ b/autogpts/autogpt/autogpt/models/action_history.py
@@ -1,11 +1,18 @@
from __future__ import annotations
-from typing import Any, Iterator, Literal, Optional
+import asyncio
+from typing import TYPE_CHECKING, Any, Iterator, Literal, Optional
from pydantic import BaseModel, Field
+from autogpt.processing.text import summarize_text
from autogpt.prompts.utils import format_numbered_list, indent
+if TYPE_CHECKING:
+ from autogpt.agents.base import CommandArgs, CommandName
+ from autogpt.config.config import Config
+ from autogpt.core.resource.model_providers import ChatModelProvider
+
class Action(BaseModel):
name: str
@@ -84,6 +91,27 @@ ActionResult = ActionSuccessResult | ActionErrorResult | ActionInterruptedByHuma
class Episode(BaseModel):
action: Action
result: ActionResult | None
+ summary: str | None = None
+
+ def format(self):
+ step = f"Executed `{self.action.format_call()}`\n"
+ step += f'- **Reasoning:** "{self.action.reasoning}"\n'
+ step += (
+ "- **Status:** "
+ f"`{self.result.status if self.result else 'did_not_finish'}`\n"
+ )
+ if self.result:
+ if self.result.status == "success":
+ result = str(self.result)
+ result = "\n" + indent(result) if "\n" in result else result
+ step += f"- **Output:** {result}"
+ elif self.result.status == "error":
+ step += f"- **Reason:** {self.result.reason}\n"
+ if self.result.error:
+ step += f"- **Error:** {self.result.error}\n"
+ elif self.result.status == "interrupted_by_human":
+ step += f"- **Feedback:** {self.result.feedback}\n"
+ return step
def __str__(self) -> str:
executed_action = f"Executed `{self.action.format_call()}`"
@@ -96,6 +124,7 @@ class EpisodicActionHistory(BaseModel):
episodes: list[Episode] = Field(default_factory=list)
cursor: int = 0
+ _lock = asyncio.Lock()
@property
def current_episode(self) -> Episode | None:
@@ -131,6 +160,15 @@ class EpisodicActionHistory(BaseModel):
self.current_episode.result = result
self.cursor = len(self.episodes)
+ def matches_last_command(
+ self, command_name: CommandName, arguments: CommandArgs
+ ) -> bool:
+ """Check if the last command matches the given name and arguments."""
+ if len(self.episodes) > 0:
+ last_command = self.episodes[-1].action
+ return last_command.name == command_name and last_command.args == arguments
+ return False
+
def rewind(self, number_of_episodes: int = 0) -> None:
"""Resets the history to an earlier state.
@@ -148,29 +186,48 @@ class EpisodicActionHistory(BaseModel):
self.episodes = self.episodes[:-number_of_episodes]
self.cursor = len(self.episodes)
+ async def handle_compression(
+ self, llm_provider: ChatModelProvider, app_config: Config
+ ) -> None:
+ """Compresses each episode in the action history using an LLM.
+
+ This method iterates over all episodes in the action history without a summary,
+ and generates a summary for them using an LLM.
+ """
+ compress_instruction = (
+ "The text represents an action, the reason for its execution, "
+ "and its result. "
+ "Condense the action taken and its result into one line. "
+ "Preserve any specific factual information gathered by the action."
+ )
+ async with self._lock:
+ # Gather all episodes without a summary
+ episodes_to_summarize = [ep for ep in self.episodes if ep.summary is None]
+
+ # Parallelize summarization calls
+ summarize_coroutines = [
+ summarize_text(
+ episode.format(),
+ instruction=compress_instruction,
+ llm_provider=llm_provider,
+ config=app_config,
+ )
+ for episode in episodes_to_summarize
+ ]
+ summaries = await asyncio.gather(*summarize_coroutines)
+
+ # Assign summaries to episodes
+ for episode, (summary, _) in zip(episodes_to_summarize, summaries):
+ episode.summary = summary
+
def fmt_list(self) -> str:
return format_numbered_list(self.episodes)
def fmt_paragraph(self) -> str:
steps: list[str] = []
- for i, c in enumerate(self.episodes, 1):
- step = f"### Step {i}: Executed `{c.action.format_call()}`\n"
- step += f'- **Reasoning:** "{c.action.reasoning}"\n'
- step += (
- f"- **Status:** `{c.result.status if c.result else 'did_not_finish'}`\n"
- )
- if c.result:
- if c.result.status == "success":
- result = str(c.result)
- result = "\n" + indent(result) if "\n" in result else result
- step += f"- **Output:** {result}"
- elif c.result.status == "error":
- step += f"- **Reason:** {c.result.reason}\n"
- if c.result.error:
- step += f"- **Error:** {c.result.error}\n"
- elif c.result.status == "interrupted_by_human":
- step += f"- **Feedback:** {c.result.feedback}\n"
+ for i, episode in enumerate(self.episodes, 1):
+ step = f"### Step {i}: {episode.format()}\n"
steps.append(step)
diff --git a/autogpts/autogpt/autogpt/models/command.py b/autogpts/autogpt/autogpt/models/command.py
index 90aa266cc..5472dc4aa 100644
--- a/autogpts/autogpt/autogpt/models/command.py
+++ b/autogpts/autogpt/autogpt/models/command.py
@@ -32,7 +32,7 @@ class Command:
enabled: Literal[True] | Callable[[Config], bool] = True,
disabled_reason: Optional[str] = None,
aliases: list[str] = [],
- available: Literal[True] | Callable[[BaseAgent], bool] = True,
+ available: bool | Callable[[BaseAgent], bool] = True,
):
self.name = name
self.description = description
@@ -55,7 +55,7 @@ class Command:
)
raise RuntimeError(f"Command '{self.name}' is disabled")
- if callable(self.available) and not self.available(agent):
+ if not self.available or callable(self.available) and not self.available(agent):
raise RuntimeError(f"Command '{self.name}' is not available")
return self.method(*args, **kwargs, agent=agent)
diff --git a/autogpts/autogpt/autogpt/models/context_item.py b/autogpts/autogpt/autogpt/models/context_item.py
index 0e5d9a373..a669bdcc8 100644
--- a/autogpts/autogpt/autogpt/models/context_item.py
+++ b/autogpts/autogpt/autogpt/models/context_item.py
@@ -1,4 +1,5 @@
import logging
+import os.path
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Optional
@@ -56,8 +57,9 @@ class FileContextItem(BaseModel, ContextItem):
@property
def content(self) -> str:
+ # TODO: use workspace.open_file()
with open(self.file_path, "rb") as file:
- return decode_textual_file(file, logger)
+ return decode_textual_file(file, os.path.splitext(file.name)[1], logger)
class FolderContextItem(BaseModel, ContextItem):
diff --git a/autogpts/autogpt/autogpt/plugins/__init__.py b/autogpts/autogpt/autogpt/plugins/__init__.py
index 0b08a62e4..618a9895a 100644
--- a/autogpts/autogpt/autogpt/plugins/__init__.py
+++ b/autogpts/autogpt/autogpt/plugins/__init__.py
@@ -6,7 +6,6 @@ import inspect
import json
import logging
import os
-import sys
import zipfile
from pathlib import Path
from typing import TYPE_CHECKING, List
@@ -220,21 +219,21 @@ def scan_plugins(config: Config) -> List[AutoGPTPluginTemplate]:
plugins_config = config.plugins_config
# Directory-based plugins
- for plugin_path in [f.path for f in os.scandir(config.plugins_dir) if f.is_dir()]:
+ for plugin_path in [f for f in Path(config.plugins_dir).iterdir() if f.is_dir()]:
# Avoid going into __pycache__ or other hidden directories
- if plugin_path.startswith("__"):
+ if plugin_path.name.startswith("__"):
continue
- plugin_module_path = plugin_path.split(os.path.sep)
- plugin_module_name = plugin_module_path[-1]
- qualified_module_name = ".".join(plugin_module_path)
+ plugin_module_name = plugin_path.name
+ qualified_module_name = ".".join(plugin_path.parts)
try:
- __import__(qualified_module_name)
- except ImportError:
- logger.error(f"Failed to load {qualified_module_name}")
+ plugin = importlib.import_module(qualified_module_name)
+ except ImportError as e:
+ logger.error(
+ f"Failed to load {qualified_module_name} from {plugin_path}: {e}"
+ )
continue
- plugin = sys.modules[qualified_module_name]
if not plugins_config.is_enabled(plugin_module_name):
logger.warning(
@@ -261,8 +260,8 @@ def scan_plugins(config: Config) -> List[AutoGPTPluginTemplate]:
zipped_package = zipimporter(str(plugin))
try:
zipped_module = zipped_package.load_module(str(module.parent))
- except ZipImportError:
- logger.error(f"Failed to load {str(module.parent)}")
+ except ZipImportError as e:
+ logger.error(f"Failed to load {module.parent} from {plugin}: {e}")
continue
for key in dir(zipped_module):
diff --git a/autogpts/autogpt/autogpt/plugins/plugins_config.py b/autogpts/autogpt/autogpt/plugins/plugins_config.py
index 0494b6e38..ad96d4a37 100644
--- a/autogpts/autogpt/autogpt/plugins/plugins_config.py
+++ b/autogpts/autogpt/autogpt/plugins/plugins_config.py
@@ -72,7 +72,7 @@ class PluginsConfig(BaseModel):
)
with open(plugins_config_file, "r") as f:
- plugins_config = yaml.load(f, Loader=yaml.FullLoader)
+ plugins_config = yaml.load(f, Loader=yaml.SafeLoader)
plugins = {}
for name, plugin in plugins_config.items():
diff --git a/autogpts/autogpt/autogpt/processing/text.py b/autogpts/autogpt/autogpt/processing/text.py
index c0e71c988..4cebbabd6 100644
--- a/autogpts/autogpt/autogpt/processing/text.py
+++ b/autogpts/autogpt/autogpt/processing/text.py
@@ -1,4 +1,5 @@
"""Text processing functions"""
+
import logging
import math
from typing import Iterator, Optional, TypeVar
@@ -12,6 +13,7 @@ from autogpt.core.resource.model_providers import (
ChatModelProvider,
ModelTokenizer,
)
+from autogpt.core.utils.json_utils import extract_list_from_json
logger = logging.getLogger(__name__)
@@ -57,105 +59,165 @@ async def summarize_text(
text: str,
llm_provider: ChatModelProvider,
config: Config,
- instruction: Optional[str] = None,
question: Optional[str] = None,
-) -> tuple[str, None | list[tuple[str, str]]]:
- """Summarize text using the OpenAI API
+ instruction: Optional[str] = None,
+) -> tuple[str, list[tuple[str, str]]]:
+ if question:
+ if instruction:
+ raise ValueError(
+ "Parameters 'question' and 'instructions' cannot both be set"
+ )
- Args:
- text (str): The text to summarize.
- llm_provider: LLM provider to use for summarization.
- config (Config): The global application config, containing the FAST_LLM setting.
- instruction (str): Additional instruction for summarization, e.g.
- "focus on information related to polar bears", or
- "omit personal information contained in the text".
- question (str): Question to be answered by the summary.
+ instruction = (
+ f'From the text, answer the question: "{question}". '
+ "If the answer is not in the text, indicate this clearly "
+ "and concisely state why the text is not suitable to answer the question."
+ )
+ elif not instruction:
+ instruction = (
+ "Summarize or describe the text clearly and concisely, "
+ "whichever seems more appropriate."
+ )
- Returns:
- str: The summary of the text
- list[(summary, chunk)]: Text chunks and their summary, if the text was chunked.
- None otherwise.
- """
- if not text:
- raise ValueError("No text to summarize")
+ return await _process_text( # type: ignore
+ text=text,
+ instruction=instruction,
+ llm_provider=llm_provider,
+ config=config,
+ )
- if instruction and question:
- raise ValueError("Parameters 'question' and 'instructions' cannot both be set")
- model = config.fast_llm
+async def extract_information(
+ source_text: str,
+ topics_of_interest: list[str],
+ llm_provider: ChatModelProvider,
+ config: Config,
+) -> list[str]:
+ fmt_topics_list = "\n".join(f"* {topic}." for topic in topics_of_interest)
+ instruction = (
+ "Extract relevant pieces of information about the following topics:\n"
+ f"{fmt_topics_list}\n"
+ "Reword pieces of information if needed to make them self-explanatory. "
+ "Be concise.\n\n"
+ "Respond with an `Array<string>` in JSON format AND NOTHING ELSE. "
+ 'If the text contains no relevant information, return "[]".'
+ )
+ return await _process_text( # type: ignore
+ text=source_text,
+ instruction=instruction,
+ output_type=list[str],
+ llm_provider=llm_provider,
+ config=config,
+ )
- if question:
- instruction = (
- 'Include any information that can be used to answer the question: "%s". '
- "Do not directly answer the question itself."
- ) % question
- summarization_prompt = ChatPrompt(messages=[])
+async def _process_text(
+ text: str,
+ instruction: str,
+ llm_provider: ChatModelProvider,
+ config: Config,
+ output_type: type[str | list[str]] = str,
+) -> tuple[str, list[tuple[str, str]]] | list[str]:
+ """Process text using the OpenAI API for summarization or information extraction
+
+ Params:
+ text (str): The text to process.
+ instruction (str): Additional instruction for processing.
+ llm_provider: LLM provider to use.
+ config (Config): The global application config.
+ output_type: `str` for summaries or `list[str]` for piece-wise info extraction.
+
+ Returns:
+ For summarization: tuple[str, None | list[(summary, chunk)]]
+ For piece-wise information extraction: list[str]
+ """
+ if not text.strip():
+ raise ValueError("No content")
+
+ model = config.fast_llm
text_tlength = llm_provider.count_tokens(text, model)
- logger.info(f"Text length: {text_tlength} tokens")
+ logger.debug(f"Text length: {text_tlength} tokens")
- # reserve 50 tokens for summary prompt, 500 for the response
- max_chunk_length = llm_provider.get_token_limit(model) - 550
- logger.info(f"Max chunk length: {max_chunk_length} tokens")
+ max_result_tokens = 500
+ max_chunk_length = llm_provider.get_token_limit(model) - max_result_tokens - 50
+ logger.debug(f"Max chunk length: {max_chunk_length} tokens")
if text_tlength < max_chunk_length:
- # summarization_prompt.add("user", text)
- summarization_prompt.messages.append(
- ChatMessage.user(
- "Write a concise summary of the following text."
- f"{f' {instruction}' if instruction is not None else ''}:"
- "\n\n\n"
- f'LITERAL TEXT: """{text}"""'
- "\n\n\n"
- "CONCISE SUMMARY: The text is best summarized as"
- )
+ prompt = ChatPrompt(
+ messages=[
+ ChatMessage.system(
+ "The user is going to give you a text enclosed in triple quotes. "
+ f"{instruction}"
+ ),
+ ChatMessage.user(f'"""{text}"""'),
+ ]
)
- summary = (
- await llm_provider.create_chat_completion(
- model_prompt=summarization_prompt.messages,
- model_name=model,
- temperature=0,
- max_tokens=500,
- )
- ).response["content"]
-
- logger.debug(f"\n{'-'*16} SUMMARY {'-'*17}\n{summary}\n{'-'*42}\n")
- return summary.strip(), None
-
- summaries: list[str] = []
- chunks = list(
- split_text(
- text,
- config=config,
- max_chunk_length=max_chunk_length,
- tokenizer=llm_provider.get_tokenizer(model),
- )
- )
+ logger.debug(f"PROCESSING:\n{prompt}")
- for i, (chunk, chunk_length) in enumerate(chunks):
- logger.info(
- f"Summarizing chunk {i + 1} / {len(chunks)} of length {chunk_length} tokens"
+ response = await llm_provider.create_chat_completion(
+ model_prompt=prompt.messages,
+ model_name=model,
+ temperature=0.5,
+ max_output_tokens=max_result_tokens,
+ completion_parser=lambda s: (
+ extract_list_from_json(s.content) if output_type is not str else None
+ ),
)
- summary, _ = await summarize_text(
- text=chunk,
- instruction=instruction,
- llm_provider=llm_provider,
- config=config,
+
+ if output_type == list[str]:
+ logger.debug(f"Raw LLM response: {repr(response.response.content)}")
+ fmt_result_bullet_list = "\n".join(f"* {r}" for r in response.parsed_result)
+ logger.debug(
+ f"\n{'-'*11} EXTRACTION RESULT {'-'*12}\n"
+ f"{fmt_result_bullet_list}\n"
+ f"{'-'*42}\n"
+ )
+ return response.parsed_result
+ else:
+ summary = response.response.content
+ logger.debug(f"\n{'-'*16} SUMMARY {'-'*17}\n{summary}\n{'-'*42}\n")
+ return summary.strip(), [(summary, text)]
+ else:
+ chunks = list(
+ split_text(
+ text,
+ config=config,
+ max_chunk_length=max_chunk_length,
+ tokenizer=llm_provider.get_tokenizer(model),
+ )
)
- summaries.append(summary)
- logger.info(f"Summarized {len(chunks)} chunks")
+ processed_results = []
+ for i, (chunk, _) in enumerate(chunks):
+ logger.info(f"Processing chunk {i + 1} / {len(chunks)}")
+ chunk_result = await _process_text(
+ text=chunk,
+ instruction=instruction,
+ output_type=output_type,
+ llm_provider=llm_provider,
+ config=config,
+ )
+ processed_results.extend(
+ chunk_result if output_type == list[str] else [chunk_result]
+ )
- summary, _ = await summarize_text(
- "\n\n".join(summaries),
- llm_provider=llm_provider,
- config=config,
- )
- return summary.strip(), [
- (summaries[i], chunks[i][0]) for i in range(0, len(chunks))
- ]
+ if output_type == list[str]:
+ return processed_results
+ else:
+ summary, _ = await _process_text(
+ "\n\n".join([result[0] for result in processed_results]),
+ instruction=(
+ "The text consists of multiple partial summaries. "
+ "Combine these partial summaries into one."
+ ),
+ llm_provider=llm_provider,
+ config=config,
+ )
+ return summary.strip(), [
+ (processed_results[i], chunks[i][0]) for i in range(0, len(chunks))
+ ]
def split_text(
diff --git a/autogpts/autogpt/autogpt/speech/macos_tts.py b/autogpts/autogpt/autogpt/speech/macos_tts.py
index e88331d21..6a1dd99d5 100644
--- a/autogpts/autogpt/autogpt/speech/macos_tts.py
+++ b/autogpts/autogpt/autogpt/speech/macos_tts.py
@@ -1,7 +1,7 @@
""" MacOS TTS Voice. """
from __future__ import annotations
-import os
+import subprocess
from autogpt.speech.base import VoiceBase
@@ -15,9 +15,9 @@ class MacOSTTS(VoiceBase):
def _speech(self, text: str, voice_index: int = 0) -> bool:
"""Play the given text."""
if voice_index == 0:
- os.system(f'say "{text}"')
+ subprocess.run(["say", text], shell=False)
elif voice_index == 1:
- os.system(f'say -v "Ava (Premium)" "{text}"')
+ subprocess.run(["say", "-v", "Ava (Premium)", text], shell=False)
else:
- os.system(f'say -v Samantha "{text}"')
+ subprocess.run(["say", "-v", "Samantha", text], shell=False)
return True
diff --git a/autogpts/autogpt/autogpt/utils.py b/autogpts/autogpt/autogpt/utils.py
index 4aa503a7b..18a7a6389 100644
--- a/autogpts/autogpt/autogpt/utils.py
+++ b/autogpts/autogpt/autogpt/utils.py
@@ -7,7 +7,7 @@ from colorama import Fore
def validate_yaml_file(file: str | Path):
try:
with open(file, encoding="utf-8") as fp:
- yaml.load(fp.read(), Loader=yaml.FullLoader)
+ yaml.load(fp.read(), Loader=yaml.SafeLoader)
except FileNotFoundError:
return (False, f"The file {Fore.CYAN}`{file}`{Fore.RESET} wasn't found")
except yaml.YAMLError as e:
diff --git a/autogpts/autogpt/azure.yaml.template b/autogpts/autogpt/azure.yaml.template
index 7ad0c9c82..d05a2c3f7 100644
--- a/autogpts/autogpt/azure.yaml.template
+++ b/autogpts/autogpt/azure.yaml.template
@@ -1,7 +1,7 @@
azure_api_type: azure
-azure_api_base: your-base-url-for-azure
azure_api_version: api-version-for-azure
+azure_endpoint: your-azure-openai-endpoint
azure_model_map:
- gpt-3.5-turbo: gpt35-deployment-id-for-azure
- gpt-4: gpt4-deployment-id-for-azure
- text-embedding-ada-002: embedding-deployment-id-for-azure
+ gpt-3.5-turbo-0125: gpt35-deployment-id-for-azure
+ gpt-4-turbo-preview: gpt4-deployment-id-for-azure
+ text-embedding-3-small: embedding-deployment-id-for-azure
diff --git a/autogpts/autogpt/poetry.lock b/autogpts/autogpt/poetry.lock
index 3666a0cde..50fa797f2 100644
--- a/autogpts/autogpt/poetry.lock
+++ b/autogpts/autogpt/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
[[package]]
name = "abstract-singleton"
@@ -21,15 +21,16 @@ files = []
develop = false
[package.dependencies]
+agent-protocol-client = "^1.1.0"
click = "^8.1.3"
+click-default-group = "^1.2.4"
colorama = "^0.4.6"
-fastapi = "^0.99.0"
+fastapi = "^0.109.1"
gitpython = "^3.1.32"
-helicone = "^1.0.9"
httpx = "^0.24.0"
matplotlib = "^3.7.2"
networkx = "^3.1"
-openai = "^0.27.8"
+openai = "^1.7.2"
pandas = "^2.0.3"
pexpect = "^4.8.0"
psutil = "^5.9.5"
@@ -37,104 +38,119 @@ pydantic = "^1.10.9"
pytest = "^7.3.2"
pytest-asyncio = "^0.21.1"
python-dotenv = "^1.0.0"
-python-multipart = "^0.0.6"
+python-multipart = "^0.0.7"
pyvis = "^0.3.2"
requests = "^2.31.0"
selenium = "^4.11.2"
+tabulate = "^0.9.0"
toml = "^0.10.2"
types-requests = "^2.31.0.1"
uvicorn = "^0.23.2"
[package.source]
-type = "git"
-url = "https://github.com/Significant-Gravitas/AutoGPT.git"
-reference = "HEAD"
-resolved_reference = "967338193e96b8960f76329b4af97d07193f0ddb"
-subdirectory = "benchmark"
+type = "directory"
+url = "../../benchmark"
+
+[[package]]
+name = "agent-protocol-client"
+version = "1.1.0"
+description = "Agent Communication Protocol Client"
+optional = true
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "agent_protocol_client-1.1.0-py3-none-any.whl", hash = "sha256:0e8c6c97244189666ed18e320410abddce8c9dfb75437da1e590bbef3b6268be"},
+ {file = "agent_protocol_client-1.1.0.tar.gz", hash = "sha256:aa7e1042de1249477fdc29c2df08a44f2233dade9c02c1279e37c98e9d3a0d72"},
+]
+
+[package.dependencies]
+aiohttp = ">=3.8.4,<4.0.0"
+pydantic = ">=1.10.5,<2.0.0"
+python-dateutil = ">=2.8.2,<3.0.0"
+urllib3 = ">=1.25.3,<2.0.0"
[[package]]
name = "aiohttp"
-version = "3.9.1"
+version = "3.9.3"
description = "Async http client/server framework (asyncio)"
optional = false
python-versions = ">=3.8"
files = [
- {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1f80197f8b0b846a8d5cf7b7ec6084493950d0882cc5537fb7b96a69e3c8590"},
- {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c72444d17777865734aa1a4d167794c34b63e5883abb90356a0364a28904e6c0"},
- {file = "aiohttp-3.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b05d5cbe9dafcdc733262c3a99ccf63d2f7ce02543620d2bd8db4d4f7a22f83"},
- {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c4fa235d534b3547184831c624c0b7c1e262cd1de847d95085ec94c16fddcd5"},
- {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:289ba9ae8e88d0ba16062ecf02dd730b34186ea3b1e7489046fc338bdc3361c4"},
- {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bff7e2811814fa2271be95ab6e84c9436d027a0e59665de60edf44e529a42c1f"},
- {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81b77f868814346662c96ab36b875d7814ebf82340d3284a31681085c051320f"},
- {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b9c7426923bb7bd66d409da46c41e3fb40f5caf679da624439b9eba92043fa6"},
- {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8d44e7bf06b0c0a70a20f9100af9fcfd7f6d9d3913e37754c12d424179b4e48f"},
- {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22698f01ff5653fe66d16ffb7658f582a0ac084d7da1323e39fd9eab326a1f26"},
- {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ca7ca5abfbfe8d39e653870fbe8d7710be7a857f8a8386fc9de1aae2e02ce7e4"},
- {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:8d7f98fde213f74561be1d6d3fa353656197f75d4edfbb3d94c9eb9b0fc47f5d"},
- {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5216b6082c624b55cfe79af5d538e499cd5f5b976820eac31951fb4325974501"},
- {file = "aiohttp-3.9.1-cp310-cp310-win32.whl", hash = "sha256:0e7ba7ff228c0d9a2cd66194e90f2bca6e0abca810b786901a569c0de082f489"},
- {file = "aiohttp-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:c7e939f1ae428a86e4abbb9a7c4732bf4706048818dfd979e5e2839ce0159f23"},
- {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:df9cf74b9bc03d586fc53ba470828d7b77ce51b0582d1d0b5b2fb673c0baa32d"},
- {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ecca113f19d5e74048c001934045a2b9368d77b0b17691d905af18bd1c21275e"},
- {file = "aiohttp-3.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8cef8710fb849d97c533f259103f09bac167a008d7131d7b2b0e3a33269185c0"},
- {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea94403a21eb94c93386d559bce297381609153e418a3ffc7d6bf772f59cc35"},
- {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91c742ca59045dce7ba76cab6e223e41d2c70d79e82c284a96411f8645e2afff"},
- {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c93b7c2e52061f0925c3382d5cb8980e40f91c989563d3d32ca280069fd6a87"},
- {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee2527134f95e106cc1653e9ac78846f3a2ec1004cf20ef4e02038035a74544d"},
- {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11ff168d752cb41e8492817e10fb4f85828f6a0142b9726a30c27c35a1835f01"},
- {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b8c3a67eb87394386847d188996920f33b01b32155f0a94f36ca0e0c635bf3e3"},
- {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c7b5d5d64e2a14e35a9240b33b89389e0035e6de8dbb7ffa50d10d8b65c57449"},
- {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:69985d50a2b6f709412d944ffb2e97d0be154ea90600b7a921f95a87d6f108a2"},
- {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:c9110c06eaaac7e1f5562caf481f18ccf8f6fdf4c3323feab28a93d34cc646bd"},
- {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737e69d193dac7296365a6dcb73bbbf53bb760ab25a3727716bbd42022e8d7a"},
- {file = "aiohttp-3.9.1-cp311-cp311-win32.whl", hash = "sha256:4ee8caa925aebc1e64e98432d78ea8de67b2272252b0a931d2ac3bd876ad5544"},
- {file = "aiohttp-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:a34086c5cc285be878622e0a6ab897a986a6e8bf5b67ecb377015f06ed316587"},
- {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f800164276eec54e0af5c99feb9494c295118fc10a11b997bbb1348ba1a52065"},
- {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:500f1c59906cd142d452074f3811614be04819a38ae2b3239a48b82649c08821"},
- {file = "aiohttp-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0b0a6a36ed7e164c6df1e18ee47afbd1990ce47cb428739d6c99aaabfaf1b3af"},
- {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69da0f3ed3496808e8cbc5123a866c41c12c15baaaead96d256477edf168eb57"},
- {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:176df045597e674fa950bf5ae536be85699e04cea68fa3a616cf75e413737eb5"},
- {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b796b44111f0cab6bbf66214186e44734b5baab949cb5fb56154142a92989aeb"},
- {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f27fdaadce22f2ef950fc10dcdf8048407c3b42b73779e48a4e76b3c35bca26c"},
- {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcb6532b9814ea7c5a6a3299747c49de30e84472fa72821b07f5a9818bce0f66"},
- {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:54631fb69a6e44b2ba522f7c22a6fb2667a02fd97d636048478db2fd8c4e98fe"},
- {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4b4c452d0190c5a820d3f5c0f3cd8a28ace48c54053e24da9d6041bf81113183"},
- {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:cae4c0c2ca800c793cae07ef3d40794625471040a87e1ba392039639ad61ab5b"},
- {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:565760d6812b8d78d416c3c7cfdf5362fbe0d0d25b82fed75d0d29e18d7fc30f"},
- {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54311eb54f3a0c45efb9ed0d0a8f43d1bc6060d773f6973efd90037a51cd0a3f"},
- {file = "aiohttp-3.9.1-cp312-cp312-win32.whl", hash = "sha256:85c3e3c9cb1d480e0b9a64c658cd66b3cfb8e721636ab8b0e746e2d79a7a9eed"},
- {file = "aiohttp-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:11cb254e397a82efb1805d12561e80124928e04e9c4483587ce7390b3866d213"},
- {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8a22a34bc594d9d24621091d1b91511001a7eea91d6652ea495ce06e27381f70"},
- {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:598db66eaf2e04aa0c8900a63b0101fdc5e6b8a7ddd805c56d86efb54eb66672"},
- {file = "aiohttp-3.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c9376e2b09895c8ca8b95362283365eb5c03bdc8428ade80a864160605715f1"},
- {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41473de252e1797c2d2293804e389a6d6986ef37cbb4a25208de537ae32141dd"},
- {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c5857612c9813796960c00767645cb5da815af16dafb32d70c72a8390bbf690"},
- {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffcd828e37dc219a72c9012ec44ad2e7e3066bec6ff3aaa19e7d435dbf4032ca"},
- {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:219a16763dc0294842188ac8a12262b5671817042b35d45e44fd0a697d8c8361"},
- {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f694dc8a6a3112059258a725a4ebe9acac5fe62f11c77ac4dcf896edfa78ca28"},
- {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bcc0ea8d5b74a41b621ad4a13d96c36079c81628ccc0b30cfb1603e3dfa3a014"},
- {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:90ec72d231169b4b8d6085be13023ece8fa9b1bb495e4398d847e25218e0f431"},
- {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:cf2a0ac0615842b849f40c4d7f304986a242f1e68286dbf3bd7a835e4f83acfd"},
- {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:0e49b08eafa4f5707ecfb321ab9592717a319e37938e301d462f79b4e860c32a"},
- {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2c59e0076ea31c08553e868cec02d22191c086f00b44610f8ab7363a11a5d9d8"},
- {file = "aiohttp-3.9.1-cp38-cp38-win32.whl", hash = "sha256:4831df72b053b1eed31eb00a2e1aff6896fb4485301d4ccb208cac264b648db4"},
- {file = "aiohttp-3.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:3135713c5562731ee18f58d3ad1bf41e1d8883eb68b363f2ffde5b2ea4b84cc7"},
- {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cfeadf42840c1e870dc2042a232a8748e75a36b52d78968cda6736de55582766"},
- {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70907533db712f7aa791effb38efa96f044ce3d4e850e2d7691abd759f4f0ae0"},
- {file = "aiohttp-3.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cdefe289681507187e375a5064c7599f52c40343a8701761c802c1853a504558"},
- {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7481f581251bb5558ba9f635db70908819caa221fc79ee52a7f58392778c636"},
- {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49f0c1b3c2842556e5de35f122fc0f0b721334ceb6e78c3719693364d4af8499"},
- {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d406b01a9f5a7e232d1b0d161b40c05275ffbcbd772dc18c1d5a570961a1ca4"},
- {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d8e4450e7fe24d86e86b23cc209e0023177b6d59502e33807b732d2deb6975f"},
- {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c0266cd6f005e99f3f51e583012de2778e65af6b73860038b968a0a8888487a"},
- {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab221850108a4a063c5b8a70f00dd7a1975e5a1713f87f4ab26a46e5feac5a0e"},
- {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c88a15f272a0ad3d7773cf3a37cc7b7d077cbfc8e331675cf1346e849d97a4e5"},
- {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:237533179d9747080bcaad4d02083ce295c0d2eab3e9e8ce103411a4312991a0"},
- {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:02ab6006ec3c3463b528374c4cdce86434e7b89ad355e7bf29e2f16b46c7dd6f"},
- {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04fa38875e53eb7e354ece1607b1d2fdee2d175ea4e4d745f6ec9f751fe20c7c"},
- {file = "aiohttp-3.9.1-cp39-cp39-win32.whl", hash = "sha256:82eefaf1a996060602f3cc1112d93ba8b201dbf5d8fd9611227de2003dddb3b7"},
- {file = "aiohttp-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:9b05d33ff8e6b269e30a7957bd3244ffbce2a7a35a81b81c382629b80af1a8bf"},
- {file = "aiohttp-3.9.1.tar.gz", hash = "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"},
+ {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"},
+ {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"},
+ {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"},
+ {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"},
+ {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"},
+ {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"},
+ {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"},
+ {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"},
+ {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"},
+ {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"},
+ {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"},
]
[package.dependencies]
@@ -164,19 +180,20 @@ frozenlist = ">=1.1.0"
[[package]]
name = "anyio"
-version = "4.1.0"
+version = "4.2.0"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
optional = false
python-versions = ">=3.8"
files = [
- {file = "anyio-4.1.0-py3-none-any.whl", hash = "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f"},
- {file = "anyio-4.1.0.tar.gz", hash = "sha256:5a0bec7085176715be77df87fc66d6c9d70626bd752fcc85f57cdbee5b3760da"},
+ {file = "anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee"},
+ {file = "anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f"},
]
[package.dependencies]
exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""}
idna = ">=2.8"
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"]
@@ -184,16 +201,22 @@ test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypo
trio = ["trio (>=0.23)"]
[[package]]
-name = "appdirs"
-version = "1.4.4"
-description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+name = "asgiref"
+version = "3.7.2"
+description = "ASGI specs, helper code, and adapters"
optional = false
-python-versions = "*"
+python-versions = ">=3.7"
files = [
- {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
- {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
+ {file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"},
+ {file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"},
]
+[package.dependencies]
+typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""}
+
+[package.extras]
+tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
+
[[package]]
name = "asttokens"
version = "2.4.1"
@@ -236,21 +259,22 @@ files = [
[[package]]
name = "attrs"
-version = "23.1.0"
+version = "23.2.0"
description = "Classes Without Boilerplate"
optional = false
python-versions = ">=3.7"
files = [
- {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
- {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
+ {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"},
+ {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"},
]
[package.extras]
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
-dev = ["attrs[docs,tests]", "pre-commit"]
+dev = ["attrs[tests]", "pre-commit"]
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
tests = ["attrs[tests-no-zope]", "zope-interface"]
-tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"]
+tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"]
[[package]]
name = "auto_gpt_plugin_template"
@@ -299,13 +323,13 @@ aiohttp = "^3.8.5"
bs4 = "^0.0.1"
chromadb = "^0.4.10"
colorlog = "^6.7.0"
-duckduckgo-search = "^4.0.0"
+duckduckgo-search = "^5.0.0"
google-cloud-storage = "^2.13.0"
jinja2 = "^3.1.2"
-litellm = "^0.1.821"
-openai = "^0.27.8"
+litellm = "^1.17.9"
+openai = "^1.7.2"
python-dotenv = "^1.0.0"
-python-multipart = "^0.0.6"
+python-multipart = "^0.0.7"
selenium = "^4.13.0"
sqlalchemy = "^2.0.19"
tenacity = "^8.2.2"
@@ -319,8 +343,8 @@ benchmark = ["agbenchmark @ git+https://github.com/Significant-Gravitas/AutoGPT.
[package.source]
type = "git"
url = "https://github.com/Significant-Gravitas/AutoGPT.git"
-reference = "HEAD"
-resolved_reference = "967338193e96b8960f76329b4af97d07193f0ddb"
+reference = "ab05b7ae70754c063909"
+resolved_reference = "ab05b7ae70754c06390982d237d86dc7290cd1aa"
subdirectory = "autogpts/forge"
[[package]]
@@ -336,28 +360,38 @@ files = [
[[package]]
name = "bcrypt"
-version = "4.1.1"
+version = "4.1.2"
description = "Modern password hashing for your software and your servers"
optional = false
python-versions = ">=3.7"
files = [
- {file = "bcrypt-4.1.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:196008d91201bbb1aa4e666fee5e610face25d532e433a560cabb33bfdff958b"},
- {file = "bcrypt-4.1.1-cp37-abi3-macosx_13_0_universal2.whl", hash = "sha256:2e197534c884336f9020c1f3a8efbaab0aa96fc798068cb2da9c671818b7fbb0"},
- {file = "bcrypt-4.1.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d573885b637815a7f3a3cd5f87724d7d0822da64b0ab0aa7f7c78bae534e86dc"},
- {file = "bcrypt-4.1.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab33473f973e8058d1b2df8d6e095d237c49fbf7a02b527541a86a5d1dc4444"},
- {file = "bcrypt-4.1.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:fb931cd004a7ad36a89789caf18a54c20287ec1cd62161265344b9c4554fdb2e"},
- {file = "bcrypt-4.1.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:12f40f78dcba4aa7d1354d35acf45fae9488862a4fb695c7eeda5ace6aae273f"},
- {file = "bcrypt-4.1.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2ade10e8613a3b8446214846d3ddbd56cfe9205a7d64742f0b75458c868f7492"},
- {file = "bcrypt-4.1.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f33b385c3e80b5a26b3a5e148e6165f873c1c202423570fdf45fe34e00e5f3e5"},
- {file = "bcrypt-4.1.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:755b9d27abcab678e0b8fb4d0abdebeea1f68dd1183b3f518bad8d31fa77d8be"},
- {file = "bcrypt-4.1.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a7a7b8a87e51e5e8ca85b9fdaf3a5dc7aaf123365a09be7a27883d54b9a0c403"},
- {file = "bcrypt-4.1.1-cp37-abi3-win32.whl", hash = "sha256:3d6c4e0d6963c52f8142cdea428e875042e7ce8c84812d8e5507bd1e42534e07"},
- {file = "bcrypt-4.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:14d41933510717f98aac63378b7956bbe548986e435df173c841d7f2bd0b2de7"},
- {file = "bcrypt-4.1.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:24c2ebd287b5b11016f31d506ca1052d068c3f9dc817160628504690376ff050"},
- {file = "bcrypt-4.1.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:476aa8e8aca554260159d4c7a97d6be529c8e177dbc1d443cb6b471e24e82c74"},
- {file = "bcrypt-4.1.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:12611c4b0a8b1c461646228344784a1089bc0c49975680a2f54f516e71e9b79e"},
- {file = "bcrypt-4.1.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c6450538a0fc32fb7ce4c6d511448c54c4ff7640b2ed81badf9898dcb9e5b737"},
- {file = "bcrypt-4.1.1.tar.gz", hash = "sha256:df37f5418d4f1cdcff845f60e747a015389fa4e63703c918330865e06ad80007"},
+ {file = "bcrypt-4.1.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:ac621c093edb28200728a9cca214d7e838529e557027ef0581685909acd28b5e"},
+ {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea505c97a5c465ab8c3ba75c0805a102ce526695cd6818c6de3b1a38f6f60da1"},
+ {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57fa9442758da926ed33a91644649d3e340a71e2d0a5a8de064fb621fd5a3326"},
+ {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:eb3bd3321517916696233b5e0c67fd7d6281f0ef48e66812db35fc963a422a1c"},
+ {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6cad43d8c63f34b26aef462b6f5e44fdcf9860b723d2453b5d391258c4c8e966"},
+ {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:44290ccc827d3a24604f2c8bcd00d0da349e336e6503656cb8192133e27335e2"},
+ {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:732b3920a08eacf12f93e6b04ea276c489f1c8fb49344f564cca2adb663b3e4c"},
+ {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1c28973decf4e0e69cee78c68e30a523be441972c826703bb93099868a8ff5b5"},
+ {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b8df79979c5bae07f1db22dcc49cc5bccf08a0380ca5c6f391cbb5790355c0b0"},
+ {file = "bcrypt-4.1.2-cp37-abi3-win32.whl", hash = "sha256:fbe188b878313d01b7718390f31528be4010fed1faa798c5a1d0469c9c48c369"},
+ {file = "bcrypt-4.1.2-cp37-abi3-win_amd64.whl", hash = "sha256:9800ae5bd5077b13725e2e3934aa3c9c37e49d3ea3d06318010aa40f54c63551"},
+ {file = "bcrypt-4.1.2-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:71b8be82bc46cedd61a9f4ccb6c1a493211d031415a34adde3669ee1b0afbb63"},
+ {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e3c6642077b0c8092580c819c1684161262b2e30c4f45deb000c38947bf483"},
+ {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:387e7e1af9a4dd636b9505a465032f2f5cb8e61ba1120e79a0e1cd0b512f3dfc"},
+ {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f70d9c61f9c4ca7d57f3bfe88a5ccf62546ffbadf3681bb1e268d9d2e41c91a7"},
+ {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2a298db2a8ab20056120b45e86c00a0a5eb50ec4075b6142db35f593b97cb3fb"},
+ {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ba55e40de38a24e2d78d34c2d36d6e864f93e0d79d0b6ce915e4335aa81d01b1"},
+ {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3566a88234e8de2ccae31968127b0ecccbb4cddb629da744165db72b58d88ca4"},
+ {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b90e216dc36864ae7132cb151ffe95155a37a14e0de3a8f64b49655dd959ff9c"},
+ {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:69057b9fc5093ea1ab00dd24ede891f3e5e65bee040395fb1e66ee196f9c9b4a"},
+ {file = "bcrypt-4.1.2-cp39-abi3-win32.whl", hash = "sha256:02d9ef8915f72dd6daaef40e0baeef8a017ce624369f09754baf32bb32dba25f"},
+ {file = "bcrypt-4.1.2-cp39-abi3-win_amd64.whl", hash = "sha256:be3ab1071662f6065899fe08428e45c16aa36e28bc42921c4901a191fda6ee42"},
+ {file = "bcrypt-4.1.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d75fc8cd0ba23f97bae88a6ec04e9e5351ff3c6ad06f38fe32ba50cbd0d11946"},
+ {file = "bcrypt-4.1.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:a97e07e83e3262599434816f631cc4c7ca2aa8e9c072c1b1a7fec2ae809a1d2d"},
+ {file = "bcrypt-4.1.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e51c42750b7585cee7892c2614be0d14107fad9581d1738d954a262556dd1aab"},
+ {file = "bcrypt-4.1.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba4e4cc26610581a6329b3937e02d319f5ad4b85b074846bf4fef8a8cf51e7bb"},
+ {file = "bcrypt-4.1.2.tar.gz", hash = "sha256:33313a1200a3ae90b75587ceac502b048b840fc69e7f7a0905b5f87fac7a1258"},
]
[package.extras]
@@ -384,33 +418,33 @@ lxml = ["lxml"]
[[package]]
name = "black"
-version = "23.12.0"
+version = "23.12.1"
description = "The uncompromising code formatter."
optional = false
python-versions = ">=3.8"
files = [
- {file = "black-23.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:67f19562d367468ab59bd6c36a72b2c84bc2f16b59788690e02bbcb140a77175"},
- {file = "black-23.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bbd75d9f28a7283b7426160ca21c5bd640ca7cd8ef6630b4754b6df9e2da8462"},
- {file = "black-23.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:593596f699ca2dcbbbdfa59fcda7d8ad6604370c10228223cd6cf6ce1ce7ed7e"},
- {file = "black-23.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:12d5f10cce8dc27202e9a252acd1c9a426c83f95496c959406c96b785a92bb7d"},
- {file = "black-23.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e73c5e3d37e5a3513d16b33305713237a234396ae56769b839d7c40759b8a41c"},
- {file = "black-23.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ba09cae1657c4f8a8c9ff6cfd4a6baaf915bb4ef7d03acffe6a2f6585fa1bd01"},
- {file = "black-23.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace64c1a349c162d6da3cef91e3b0e78c4fc596ffde9413efa0525456148873d"},
- {file = "black-23.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:72db37a2266b16d256b3ea88b9affcdd5c41a74db551ec3dd4609a59c17d25bf"},
- {file = "black-23.12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fdf6f23c83078a6c8da2442f4d4eeb19c28ac2a6416da7671b72f0295c4a697b"},
- {file = "black-23.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39dda060b9b395a6b7bf9c5db28ac87b3c3f48d4fdff470fa8a94ab8271da47e"},
- {file = "black-23.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7231670266ca5191a76cb838185d9be59cfa4f5dd401b7c1c70b993c58f6b1b5"},
- {file = "black-23.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:193946e634e80bfb3aec41830f5d7431f8dd5b20d11d89be14b84a97c6b8bc75"},
- {file = "black-23.12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bcf91b01ddd91a2fed9a8006d7baa94ccefe7e518556470cf40213bd3d44bbbc"},
- {file = "black-23.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:996650a89fe5892714ea4ea87bc45e41a59a1e01675c42c433a35b490e5aa3f0"},
- {file = "black-23.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdbff34c487239a63d86db0c9385b27cdd68b1bfa4e706aa74bb94a435403672"},
- {file = "black-23.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:97af22278043a6a1272daca10a6f4d36c04dfa77e61cbaaf4482e08f3640e9f0"},
- {file = "black-23.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ead25c273adfad1095a8ad32afdb8304933efba56e3c1d31b0fee4143a1e424a"},
- {file = "black-23.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c71048345bdbced456cddf1622832276d98a710196b842407840ae8055ade6ee"},
- {file = "black-23.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a832b6e00eef2c13b3239d514ea3b7d5cc3eaa03d0474eedcbbda59441ba5d"},
- {file = "black-23.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:6a82a711d13e61840fb11a6dfecc7287f2424f1ca34765e70c909a35ffa7fb95"},
- {file = "black-23.12.0-py3-none-any.whl", hash = "sha256:a7c07db8200b5315dc07e331dda4d889a56f6bf4db6a9c2a526fa3166a81614f"},
- {file = "black-23.12.0.tar.gz", hash = "sha256:330a327b422aca0634ecd115985c1c7fd7bdb5b5a2ef8aa9888a82e2ebe9437a"},
+ {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"},
+ {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"},
+ {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"},
+ {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"},
+ {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"},
+ {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"},
+ {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"},
+ {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"},
+ {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"},
+ {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"},
+ {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"},
+ {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"},
+ {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"},
+ {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"},
+ {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"},
+ {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"},
+ {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"},
+ {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"},
+ {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"},
+ {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"},
+ {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"},
+ {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"},
]
[package.dependencies]
@@ -476,428 +510,431 @@ numpy = {version = ">=1.19.0", markers = "python_version >= \"3.9\""}
[[package]]
name = "boto3"
-version = "1.33.13"
+version = "1.34.20"
description = "The AWS SDK for Python"
optional = false
-python-versions = ">= 3.7"
+python-versions = ">= 3.8"
files = [
- {file = "boto3-1.33.13-py3-none-any.whl", hash = "sha256:5f278b95fb2b32f3d09d950759a05664357ba35d81107bab1537c4ddd212cd8c"},
- {file = "boto3-1.33.13.tar.gz", hash = "sha256:0e966b8a475ecb06cc0846304454b8da2473d4c8198a45dfb2c5304871986883"},
+ {file = "boto3-1.34.20-py3-none-any.whl", hash = "sha256:a21da54634bd09dcad9e80d106512b6aabe493b1d4260688180156ef27afedc9"},
+ {file = "boto3-1.34.20.tar.gz", hash = "sha256:7f662b0c833e7a4d1272b7ec60ded3f14affd54d08620b708ba3abeb0e49d15e"},
]
[package.dependencies]
-botocore = ">=1.33.13,<1.34.0"
+botocore = ">=1.34.20,<1.35.0"
jmespath = ">=0.7.1,<2.0.0"
-s3transfer = ">=0.8.2,<0.9.0"
+s3transfer = ">=0.10.0,<0.11.0"
[package.extras]
crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]]
name = "boto3-stubs"
-version = "1.33.13"
-description = "Type annotations for boto3 1.33.13 generated with mypy-boto3-builder 7.21.0"
+version = "1.34.20"
+description = "Type annotations for boto3 1.34.20 generated with mypy-boto3-builder 7.23.1"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "boto3-stubs-1.33.13.tar.gz", hash = "sha256:c6b556adc792a70dbfa0bbab512bf96010e1bc652658ca0b01168ec11351e53b"},
- {file = "boto3_stubs-1.33.13-py3-none-any.whl", hash = "sha256:685a3e560895fc0712e51f2a96a1f5ee56325bc9c1f72085847b3e3454daa5bb"},
+ {file = "boto3-stubs-1.34.20.tar.gz", hash = "sha256:431851ea82b8596f8fa49de7014554ae0f2fa2cc6a0954459787a3b938796c68"},
+ {file = "boto3_stubs-1.34.20-py3-none-any.whl", hash = "sha256:718b4503625fc5c2cada3b8e78fa10273dfb07359261be6fc07b89e2b6e03cb0"},
]
[package.dependencies]
botocore-stubs = "*"
-mypy-boto3-s3 = {version = ">=1.33.0,<1.34.0", optional = true, markers = "extra == \"s3\""}
+mypy-boto3-s3 = {version = ">=1.34.0,<1.35.0", optional = true, markers = "extra == \"s3\""}
types-s3transfer = "*"
typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.12\""}
[package.extras]
-accessanalyzer = ["mypy-boto3-accessanalyzer (>=1.33.0,<1.34.0)"]
-account = ["mypy-boto3-account (>=1.33.0,<1.34.0)"]
-acm = ["mypy-boto3-acm (>=1.33.0,<1.34.0)"]
-acm-pca = ["mypy-boto3-acm-pca (>=1.33.0,<1.34.0)"]
-alexaforbusiness = ["mypy-boto3-alexaforbusiness (>=1.33.0,<1.34.0)"]
-all = ["mypy-boto3-accessanalyzer (>=1.33.0,<1.34.0)", "mypy-boto3-account (>=1.33.0,<1.34.0)", "mypy-boto3-acm (>=1.33.0,<1.34.0)", "mypy-boto3-acm-pca (>=1.33.0,<1.34.0)", "mypy-boto3-alexaforbusiness (>=1.33.0,<1.34.0)", "mypy-boto3-amp (>=1.33.0,<1.34.0)", "mypy-boto3-amplify (>=1.33.0,<1.34.0)", "mypy-boto3-amplifybackend (>=1.33.0,<1.34.0)", "mypy-boto3-amplifyuibuilder (>=1.33.0,<1.34.0)", "mypy-boto3-apigateway (>=1.33.0,<1.34.0)", "mypy-boto3-apigatewaymanagementapi (>=1.33.0,<1.34.0)", "mypy-boto3-apigatewayv2 (>=1.33.0,<1.34.0)", "mypy-boto3-appconfig (>=1.33.0,<1.34.0)", "mypy-boto3-appconfigdata (>=1.33.0,<1.34.0)", "mypy-boto3-appfabric (>=1.33.0,<1.34.0)", "mypy-boto3-appflow (>=1.33.0,<1.34.0)", "mypy-boto3-appintegrations (>=1.33.0,<1.34.0)", "mypy-boto3-application-autoscaling (>=1.33.0,<1.34.0)", "mypy-boto3-application-insights (>=1.33.0,<1.34.0)", "mypy-boto3-applicationcostprofiler (>=1.33.0,<1.34.0)", "mypy-boto3-appmesh (>=1.33.0,<1.34.0)", "mypy-boto3-apprunner (>=1.33.0,<1.34.0)", "mypy-boto3-appstream (>=1.33.0,<1.34.0)", "mypy-boto3-appsync (>=1.33.0,<1.34.0)", "mypy-boto3-arc-zonal-shift (>=1.33.0,<1.34.0)", "mypy-boto3-athena (>=1.33.0,<1.34.0)", "mypy-boto3-auditmanager (>=1.33.0,<1.34.0)", "mypy-boto3-autoscaling (>=1.33.0,<1.34.0)", "mypy-boto3-autoscaling-plans (>=1.33.0,<1.34.0)", "mypy-boto3-b2bi (>=1.33.0,<1.34.0)", "mypy-boto3-backup (>=1.33.0,<1.34.0)", "mypy-boto3-backup-gateway (>=1.33.0,<1.34.0)", "mypy-boto3-backupstorage (>=1.33.0,<1.34.0)", "mypy-boto3-batch (>=1.33.0,<1.34.0)", "mypy-boto3-bcm-data-exports (>=1.33.0,<1.34.0)", "mypy-boto3-bedrock (>=1.33.0,<1.34.0)", "mypy-boto3-bedrock-agent (>=1.33.0,<1.34.0)", "mypy-boto3-bedrock-agent-runtime (>=1.33.0,<1.34.0)", "mypy-boto3-bedrock-runtime (>=1.33.0,<1.34.0)", "mypy-boto3-billingconductor (>=1.33.0,<1.34.0)", "mypy-boto3-braket (>=1.33.0,<1.34.0)", "mypy-boto3-budgets (>=1.33.0,<1.34.0)", "mypy-boto3-ce (>=1.33.0,<1.34.0)", "mypy-boto3-chime (>=1.33.0,<1.34.0)", "mypy-boto3-chime-sdk-identity (>=1.33.0,<1.34.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.33.0,<1.34.0)", "mypy-boto3-chime-sdk-meetings (>=1.33.0,<1.34.0)", "mypy-boto3-chime-sdk-messaging (>=1.33.0,<1.34.0)", "mypy-boto3-chime-sdk-voice (>=1.33.0,<1.34.0)", "mypy-boto3-cleanrooms (>=1.33.0,<1.34.0)", "mypy-boto3-cleanroomsml (>=1.33.0,<1.34.0)", "mypy-boto3-cloud9 (>=1.33.0,<1.34.0)", "mypy-boto3-cloudcontrol (>=1.33.0,<1.34.0)", "mypy-boto3-clouddirectory (>=1.33.0,<1.34.0)", "mypy-boto3-cloudformation (>=1.33.0,<1.34.0)", "mypy-boto3-cloudfront (>=1.33.0,<1.34.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.33.0,<1.34.0)", "mypy-boto3-cloudhsm (>=1.33.0,<1.34.0)", "mypy-boto3-cloudhsmv2 (>=1.33.0,<1.34.0)", "mypy-boto3-cloudsearch (>=1.33.0,<1.34.0)", "mypy-boto3-cloudsearchdomain (>=1.33.0,<1.34.0)", "mypy-boto3-cloudtrail (>=1.33.0,<1.34.0)", "mypy-boto3-cloudtrail-data (>=1.33.0,<1.34.0)", "mypy-boto3-cloudwatch (>=1.33.0,<1.34.0)", "mypy-boto3-codeartifact (>=1.33.0,<1.34.0)", "mypy-boto3-codebuild (>=1.33.0,<1.34.0)", "mypy-boto3-codecatalyst (>=1.33.0,<1.34.0)", "mypy-boto3-codecommit (>=1.33.0,<1.34.0)", "mypy-boto3-codedeploy (>=1.33.0,<1.34.0)", "mypy-boto3-codeguru-reviewer (>=1.33.0,<1.34.0)", "mypy-boto3-codeguru-security (>=1.33.0,<1.34.0)", "mypy-boto3-codeguruprofiler (>=1.33.0,<1.34.0)", "mypy-boto3-codepipeline (>=1.33.0,<1.34.0)", "mypy-boto3-codestar (>=1.33.0,<1.34.0)", "mypy-boto3-codestar-connections (>=1.33.0,<1.34.0)", "mypy-boto3-codestar-notifications (>=1.33.0,<1.34.0)", "mypy-boto3-cognito-identity (>=1.33.0,<1.34.0)", "mypy-boto3-cognito-idp (>=1.33.0,<1.34.0)", "mypy-boto3-cognito-sync (>=1.33.0,<1.34.0)", "mypy-boto3-comprehend (>=1.33.0,<1.34.0)", "mypy-boto3-comprehendmedical (>=1.33.0,<1.34.0)", "mypy-boto3-compute-optimizer (>=1.33.0,<1.34.0)", "mypy-boto3-config (>=1.33.0,<1.34.0)", "mypy-boto3-connect (>=1.33.0,<1.34.0)", "mypy-boto3-connect-contact-lens (>=1.33.0,<1.34.0)", "mypy-boto3-connectcampaigns (>=1.33.0,<1.34.0)", "mypy-boto3-connectcases (>=1.33.0,<1.34.0)", "mypy-boto3-connectparticipant (>=1.33.0,<1.34.0)", "mypy-boto3-controltower (>=1.33.0,<1.34.0)", "mypy-boto3-cost-optimization-hub (>=1.33.0,<1.34.0)", "mypy-boto3-cur (>=1.33.0,<1.34.0)", "mypy-boto3-customer-profiles (>=1.33.0,<1.34.0)", "mypy-boto3-databrew (>=1.33.0,<1.34.0)", "mypy-boto3-dataexchange (>=1.33.0,<1.34.0)", "mypy-boto3-datapipeline (>=1.33.0,<1.34.0)", "mypy-boto3-datasync (>=1.33.0,<1.34.0)", "mypy-boto3-datazone (>=1.33.0,<1.34.0)", "mypy-boto3-dax (>=1.33.0,<1.34.0)", "mypy-boto3-detective (>=1.33.0,<1.34.0)", "mypy-boto3-devicefarm (>=1.33.0,<1.34.0)", "mypy-boto3-devops-guru (>=1.33.0,<1.34.0)", "mypy-boto3-directconnect (>=1.33.0,<1.34.0)", "mypy-boto3-discovery (>=1.33.0,<1.34.0)", "mypy-boto3-dlm (>=1.33.0,<1.34.0)", "mypy-boto3-dms (>=1.33.0,<1.34.0)", "mypy-boto3-docdb (>=1.33.0,<1.34.0)", "mypy-boto3-docdb-elastic (>=1.33.0,<1.34.0)", "mypy-boto3-drs (>=1.33.0,<1.34.0)", "mypy-boto3-ds (>=1.33.0,<1.34.0)", "mypy-boto3-dynamodb (>=1.33.0,<1.34.0)", "mypy-boto3-dynamodbstreams (>=1.33.0,<1.34.0)", "mypy-boto3-ebs (>=1.33.0,<1.34.0)", "mypy-boto3-ec2 (>=1.33.0,<1.34.0)", "mypy-boto3-ec2-instance-connect (>=1.33.0,<1.34.0)", "mypy-boto3-ecr (>=1.33.0,<1.34.0)", "mypy-boto3-ecr-public (>=1.33.0,<1.34.0)", "mypy-boto3-ecs (>=1.33.0,<1.34.0)", "mypy-boto3-efs (>=1.33.0,<1.34.0)", "mypy-boto3-eks (>=1.33.0,<1.34.0)", "mypy-boto3-eks-auth (>=1.33.0,<1.34.0)", "mypy-boto3-elastic-inference (>=1.33.0,<1.34.0)", "mypy-boto3-elasticache (>=1.33.0,<1.34.0)", "mypy-boto3-elasticbeanstalk (>=1.33.0,<1.34.0)", "mypy-boto3-elastictranscoder (>=1.33.0,<1.34.0)", "mypy-boto3-elb (>=1.33.0,<1.34.0)", "mypy-boto3-elbv2 (>=1.33.0,<1.34.0)", "mypy-boto3-emr (>=1.33.0,<1.34.0)", "mypy-boto3-emr-containers (>=1.33.0,<1.34.0)", "mypy-boto3-emr-serverless (>=1.33.0,<1.34.0)", "mypy-boto3-entityresolution (>=1.33.0,<1.34.0)", "mypy-boto3-es (>=1.33.0,<1.34.0)", "mypy-boto3-events (>=1.33.0,<1.34.0)", "mypy-boto3-evidently (>=1.33.0,<1.34.0)", "mypy-boto3-finspace (>=1.33.0,<1.34.0)", "mypy-boto3-finspace-data (>=1.33.0,<1.34.0)", "mypy-boto3-firehose (>=1.33.0,<1.34.0)", "mypy-boto3-fis (>=1.33.0,<1.34.0)", "mypy-boto3-fms (>=1.33.0,<1.34.0)", "mypy-boto3-forecast (>=1.33.0,<1.34.0)", "mypy-boto3-forecastquery (>=1.33.0,<1.34.0)", "mypy-boto3-frauddetector (>=1.33.0,<1.34.0)", "mypy-boto3-freetier (>=1.33.0,<1.34.0)", "mypy-boto3-fsx (>=1.33.0,<1.34.0)", "mypy-boto3-gamelift (>=1.33.0,<1.34.0)", "mypy-boto3-glacier (>=1.33.0,<1.34.0)", "mypy-boto3-globalaccelerator (>=1.33.0,<1.34.0)", "mypy-boto3-glue (>=1.33.0,<1.34.0)", "mypy-boto3-grafana (>=1.33.0,<1.34.0)", "mypy-boto3-greengrass (>=1.33.0,<1.34.0)", "mypy-boto3-greengrassv2 (>=1.33.0,<1.34.0)", "mypy-boto3-groundstation (>=1.33.0,<1.34.0)", "mypy-boto3-guardduty (>=1.33.0,<1.34.0)", "mypy-boto3-health (>=1.33.0,<1.34.0)", "mypy-boto3-healthlake (>=1.33.0,<1.34.0)", "mypy-boto3-honeycode (>=1.33.0,<1.34.0)", "mypy-boto3-iam (>=1.33.0,<1.34.0)", "mypy-boto3-identitystore (>=1.33.0,<1.34.0)", "mypy-boto3-imagebuilder (>=1.33.0,<1.34.0)", "mypy-boto3-importexport (>=1.33.0,<1.34.0)", "mypy-boto3-inspector (>=1.33.0,<1.34.0)", "mypy-boto3-inspector-scan (>=1.33.0,<1.34.0)", "mypy-boto3-inspector2 (>=1.33.0,<1.34.0)", "mypy-boto3-internetmonitor (>=1.33.0,<1.34.0)", "mypy-boto3-iot (>=1.33.0,<1.34.0)", "mypy-boto3-iot-data (>=1.33.0,<1.34.0)", "mypy-boto3-iot-jobs-data (>=1.33.0,<1.34.0)", "mypy-boto3-iot-roborunner (>=1.33.0,<1.34.0)", "mypy-boto3-iot1click-devices (>=1.33.0,<1.34.0)", "mypy-boto3-iot1click-projects (>=1.33.0,<1.34.0)", "mypy-boto3-iotanalytics (>=1.33.0,<1.34.0)", "mypy-boto3-iotdeviceadvisor (>=1.33.0,<1.34.0)", "mypy-boto3-iotevents (>=1.33.0,<1.34.0)", "mypy-boto3-iotevents-data (>=1.33.0,<1.34.0)", "mypy-boto3-iotfleethub (>=1.33.0,<1.34.0)", "mypy-boto3-iotfleetwise (>=1.33.0,<1.34.0)", "mypy-boto3-iotsecuretunneling (>=1.33.0,<1.34.0)", "mypy-boto3-iotsitewise (>=1.33.0,<1.34.0)", "mypy-boto3-iotthingsgraph (>=1.33.0,<1.34.0)", "mypy-boto3-iottwinmaker (>=1.33.0,<1.34.0)", "mypy-boto3-iotwireless (>=1.33.0,<1.34.0)", "mypy-boto3-ivs (>=1.33.0,<1.34.0)", "mypy-boto3-ivs-realtime (>=1.33.0,<1.34.0)", "mypy-boto3-ivschat (>=1.33.0,<1.34.0)", "mypy-boto3-kafka (>=1.33.0,<1.34.0)", "mypy-boto3-kafkaconnect (>=1.33.0,<1.34.0)", "mypy-boto3-kendra (>=1.33.0,<1.34.0)", "mypy-boto3-kendra-ranking (>=1.33.0,<1.34.0)", "mypy-boto3-keyspaces (>=1.33.0,<1.34.0)", "mypy-boto3-kinesis (>=1.33.0,<1.34.0)", "mypy-boto3-kinesis-video-archived-media (>=1.33.0,<1.34.0)", "mypy-boto3-kinesis-video-media (>=1.33.0,<1.34.0)", "mypy-boto3-kinesis-video-signaling (>=1.33.0,<1.34.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.33.0,<1.34.0)", "mypy-boto3-kinesisanalytics (>=1.33.0,<1.34.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.33.0,<1.34.0)", "mypy-boto3-kinesisvideo (>=1.33.0,<1.34.0)", "mypy-boto3-kms (>=1.33.0,<1.34.0)", "mypy-boto3-lakeformation (>=1.33.0,<1.34.0)", "mypy-boto3-lambda (>=1.33.0,<1.34.0)", "mypy-boto3-launch-wizard (>=1.33.0,<1.34.0)", "mypy-boto3-lex-models (>=1.33.0,<1.34.0)", "mypy-boto3-lex-runtime (>=1.33.0,<1.34.0)", "mypy-boto3-lexv2-models (>=1.33.0,<1.34.0)", "mypy-boto3-lexv2-runtime (>=1.33.0,<1.34.0)", "mypy-boto3-license-manager (>=1.33.0,<1.34.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.33.0,<1.34.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.33.0,<1.34.0)", "mypy-boto3-lightsail (>=1.33.0,<1.34.0)", "mypy-boto3-location (>=1.33.0,<1.34.0)", "mypy-boto3-logs (>=1.33.0,<1.34.0)", "mypy-boto3-lookoutequipment (>=1.33.0,<1.34.0)", "mypy-boto3-lookoutmetrics (>=1.33.0,<1.34.0)", "mypy-boto3-lookoutvision (>=1.33.0,<1.34.0)", "mypy-boto3-m2 (>=1.33.0,<1.34.0)", "mypy-boto3-machinelearning (>=1.33.0,<1.34.0)", "mypy-boto3-macie2 (>=1.33.0,<1.34.0)", "mypy-boto3-managedblockchain (>=1.33.0,<1.34.0)", "mypy-boto3-managedblockchain-query (>=1.33.0,<1.34.0)", "mypy-boto3-marketplace-agreement (>=1.33.0,<1.34.0)", "mypy-boto3-marketplace-catalog (>=1.33.0,<1.34.0)", "mypy-boto3-marketplace-deployment (>=1.33.0,<1.34.0)", "mypy-boto3-marketplace-entitlement (>=1.33.0,<1.34.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.33.0,<1.34.0)", "mypy-boto3-mediaconnect (>=1.33.0,<1.34.0)", "mypy-boto3-mediaconvert (>=1.33.0,<1.34.0)", "mypy-boto3-medialive (>=1.33.0,<1.34.0)", "mypy-boto3-mediapackage (>=1.33.0,<1.34.0)", "mypy-boto3-mediapackage-vod (>=1.33.0,<1.34.0)", "mypy-boto3-mediapackagev2 (>=1.33.0,<1.34.0)", "mypy-boto3-mediastore (>=1.33.0,<1.34.0)", "mypy-boto3-mediastore-data (>=1.33.0,<1.34.0)", "mypy-boto3-mediatailor (>=1.33.0,<1.34.0)", "mypy-boto3-medical-imaging (>=1.33.0,<1.34.0)", "mypy-boto3-memorydb (>=1.33.0,<1.34.0)", "mypy-boto3-meteringmarketplace (>=1.33.0,<1.34.0)", "mypy-boto3-mgh (>=1.33.0,<1.34.0)", "mypy-boto3-mgn (>=1.33.0,<1.34.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.33.0,<1.34.0)", "mypy-boto3-migrationhub-config (>=1.33.0,<1.34.0)", "mypy-boto3-migrationhuborchestrator (>=1.33.0,<1.34.0)", "mypy-boto3-migrationhubstrategy (>=1.33.0,<1.34.0)", "mypy-boto3-mobile (>=1.33.0,<1.34.0)", "mypy-boto3-mq (>=1.33.0,<1.34.0)", "mypy-boto3-mturk (>=1.33.0,<1.34.0)", "mypy-boto3-mwaa (>=1.33.0,<1.34.0)", "mypy-boto3-neptune (>=1.33.0,<1.34.0)", "mypy-boto3-neptunedata (>=1.33.0,<1.34.0)", "mypy-boto3-network-firewall (>=1.33.0,<1.34.0)", "mypy-boto3-networkmanager (>=1.33.0,<1.34.0)", "mypy-boto3-nimble (>=1.33.0,<1.34.0)", "mypy-boto3-oam (>=1.33.0,<1.34.0)", "mypy-boto3-omics (>=1.33.0,<1.34.0)", "mypy-boto3-opensearch (>=1.33.0,<1.34.0)", "mypy-boto3-opensearchserverless (>=1.33.0,<1.34.0)", "mypy-boto3-opsworks (>=1.33.0,<1.34.0)", "mypy-boto3-opsworkscm (>=1.33.0,<1.34.0)", "mypy-boto3-organizations (>=1.33.0,<1.34.0)", "mypy-boto3-osis (>=1.33.0,<1.34.0)", "mypy-boto3-outposts (>=1.33.0,<1.34.0)", "mypy-boto3-panorama (>=1.33.0,<1.34.0)", "mypy-boto3-payment-cryptography (>=1.33.0,<1.34.0)", "mypy-boto3-payment-cryptography-data (>=1.33.0,<1.34.0)", "mypy-boto3-pca-connector-ad (>=1.33.0,<1.34.0)", "mypy-boto3-personalize (>=1.33.0,<1.34.0)", "mypy-boto3-personalize-events (>=1.33.0,<1.34.0)", "mypy-boto3-personalize-runtime (>=1.33.0,<1.34.0)", "mypy-boto3-pi (>=1.33.0,<1.34.0)", "mypy-boto3-pinpoint (>=1.33.0,<1.34.0)", "mypy-boto3-pinpoint-email (>=1.33.0,<1.34.0)", "mypy-boto3-pinpoint-sms-voice (>=1.33.0,<1.34.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.33.0,<1.34.0)", "mypy-boto3-pipes (>=1.33.0,<1.34.0)", "mypy-boto3-polly (>=1.33.0,<1.34.0)", "mypy-boto3-pricing (>=1.33.0,<1.34.0)", "mypy-boto3-privatenetworks (>=1.33.0,<1.34.0)", "mypy-boto3-proton (>=1.33.0,<1.34.0)", "mypy-boto3-qbusiness (>=1.33.0,<1.34.0)", "mypy-boto3-qconnect (>=1.33.0,<1.34.0)", "mypy-boto3-qldb (>=1.33.0,<1.34.0)", "mypy-boto3-qldb-session (>=1.33.0,<1.34.0)", "mypy-boto3-quicksight (>=1.33.0,<1.34.0)", "mypy-boto3-ram (>=1.33.0,<1.34.0)", "mypy-boto3-rbin (>=1.33.0,<1.34.0)", "mypy-boto3-rds (>=1.33.0,<1.34.0)", "mypy-boto3-rds-data (>=1.33.0,<1.34.0)", "mypy-boto3-redshift (>=1.33.0,<1.34.0)", "mypy-boto3-redshift-data (>=1.33.0,<1.34.0)", "mypy-boto3-redshift-serverless (>=1.33.0,<1.34.0)", "mypy-boto3-rekognition (>=1.33.0,<1.34.0)", "mypy-boto3-repostspace (>=1.33.0,<1.34.0)", "mypy-boto3-resiliencehub (>=1.33.0,<1.34.0)", "mypy-boto3-resource-explorer-2 (>=1.33.0,<1.34.0)", "mypy-boto3-resource-groups (>=1.33.0,<1.34.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.33.0,<1.34.0)", "mypy-boto3-robomaker (>=1.33.0,<1.34.0)", "mypy-boto3-rolesanywhere (>=1.33.0,<1.34.0)", "mypy-boto3-route53 (>=1.33.0,<1.34.0)", "mypy-boto3-route53-recovery-cluster (>=1.33.0,<1.34.0)", "mypy-boto3-route53-recovery-control-config (>=1.33.0,<1.34.0)", "mypy-boto3-route53-recovery-readiness (>=1.33.0,<1.34.0)", "mypy-boto3-route53domains (>=1.33.0,<1.34.0)", "mypy-boto3-route53resolver (>=1.33.0,<1.34.0)", "mypy-boto3-rum (>=1.33.0,<1.34.0)", "mypy-boto3-s3 (>=1.33.0,<1.34.0)", "mypy-boto3-s3control (>=1.33.0,<1.34.0)", "mypy-boto3-s3outposts (>=1.33.0,<1.34.0)", "mypy-boto3-sagemaker (>=1.33.0,<1.34.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.33.0,<1.34.0)", "mypy-boto3-sagemaker-edge (>=1.33.0,<1.34.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.33.0,<1.34.0)", "mypy-boto3-sagemaker-geospatial (>=1.33.0,<1.34.0)", "mypy-boto3-sagemaker-metrics (>=1.33.0,<1.34.0)", "mypy-boto3-sagemaker-runtime (>=1.33.0,<1.34.0)", "mypy-boto3-savingsplans (>=1.33.0,<1.34.0)", "mypy-boto3-scheduler (>=1.33.0,<1.34.0)", "mypy-boto3-schemas (>=1.33.0,<1.34.0)", "mypy-boto3-sdb (>=1.33.0,<1.34.0)", "mypy-boto3-secretsmanager (>=1.33.0,<1.34.0)", "mypy-boto3-securityhub (>=1.33.0,<1.34.0)", "mypy-boto3-securitylake (>=1.33.0,<1.34.0)", "mypy-boto3-serverlessrepo (>=1.33.0,<1.34.0)", "mypy-boto3-service-quotas (>=1.33.0,<1.34.0)", "mypy-boto3-servicecatalog (>=1.33.0,<1.34.0)", "mypy-boto3-servicecatalog-appregistry (>=1.33.0,<1.34.0)", "mypy-boto3-servicediscovery (>=1.33.0,<1.34.0)", "mypy-boto3-ses (>=1.33.0,<1.34.0)", "mypy-boto3-sesv2 (>=1.33.0,<1.34.0)", "mypy-boto3-shield (>=1.33.0,<1.34.0)", "mypy-boto3-signer (>=1.33.0,<1.34.0)", "mypy-boto3-simspaceweaver (>=1.33.0,<1.34.0)", "mypy-boto3-sms (>=1.33.0,<1.34.0)", "mypy-boto3-sms-voice (>=1.33.0,<1.34.0)", "mypy-boto3-snow-device-management (>=1.33.0,<1.34.0)", "mypy-boto3-snowball (>=1.33.0,<1.34.0)", "mypy-boto3-sns (>=1.33.0,<1.34.0)", "mypy-boto3-sqs (>=1.33.0,<1.34.0)", "mypy-boto3-ssm (>=1.33.0,<1.34.0)", "mypy-boto3-ssm-contacts (>=1.33.0,<1.34.0)", "mypy-boto3-ssm-incidents (>=1.33.0,<1.34.0)", "mypy-boto3-ssm-sap (>=1.33.0,<1.34.0)", "mypy-boto3-sso (>=1.33.0,<1.34.0)", "mypy-boto3-sso-admin (>=1.33.0,<1.34.0)", "mypy-boto3-sso-oidc (>=1.33.0,<1.34.0)", "mypy-boto3-stepfunctions (>=1.33.0,<1.34.0)", "mypy-boto3-storagegateway (>=1.33.0,<1.34.0)", "mypy-boto3-sts (>=1.33.0,<1.34.0)", "mypy-boto3-support (>=1.33.0,<1.34.0)", "mypy-boto3-support-app (>=1.33.0,<1.34.0)", "mypy-boto3-swf (>=1.33.0,<1.34.0)", "mypy-boto3-synthetics (>=1.33.0,<1.34.0)", "mypy-boto3-textract (>=1.33.0,<1.34.0)", "mypy-boto3-timestream-query (>=1.33.0,<1.34.0)", "mypy-boto3-timestream-write (>=1.33.0,<1.34.0)", "mypy-boto3-tnb (>=1.33.0,<1.34.0)", "mypy-boto3-transcribe (>=1.33.0,<1.34.0)", "mypy-boto3-transfer (>=1.33.0,<1.34.0)", "mypy-boto3-translate (>=1.33.0,<1.34.0)", "mypy-boto3-trustedadvisor (>=1.33.0,<1.34.0)", "mypy-boto3-verifiedpermissions (>=1.33.0,<1.34.0)", "mypy-boto3-voice-id (>=1.33.0,<1.34.0)", "mypy-boto3-vpc-lattice (>=1.33.0,<1.34.0)", "mypy-boto3-waf (>=1.33.0,<1.34.0)", "mypy-boto3-waf-regional (>=1.33.0,<1.34.0)", "mypy-boto3-wafv2 (>=1.33.0,<1.34.0)", "mypy-boto3-wellarchitected (>=1.33.0,<1.34.0)", "mypy-boto3-wisdom (>=1.33.0,<1.34.0)", "mypy-boto3-workdocs (>=1.33.0,<1.34.0)", "mypy-boto3-worklink (>=1.33.0,<1.34.0)", "mypy-boto3-workmail (>=1.33.0,<1.34.0)", "mypy-boto3-workmailmessageflow (>=1.33.0,<1.34.0)", "mypy-boto3-workspaces (>=1.33.0,<1.34.0)", "mypy-boto3-workspaces-thin-client (>=1.33.0,<1.34.0)", "mypy-boto3-workspaces-web (>=1.33.0,<1.34.0)", "mypy-boto3-xray (>=1.33.0,<1.34.0)"]
-amp = ["mypy-boto3-amp (>=1.33.0,<1.34.0)"]
-amplify = ["mypy-boto3-amplify (>=1.33.0,<1.34.0)"]
-amplifybackend = ["mypy-boto3-amplifybackend (>=1.33.0,<1.34.0)"]
-amplifyuibuilder = ["mypy-boto3-amplifyuibuilder (>=1.33.0,<1.34.0)"]
-apigateway = ["mypy-boto3-apigateway (>=1.33.0,<1.34.0)"]
-apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (>=1.33.0,<1.34.0)"]
-apigatewayv2 = ["mypy-boto3-apigatewayv2 (>=1.33.0,<1.34.0)"]
-appconfig = ["mypy-boto3-appconfig (>=1.33.0,<1.34.0)"]
-appconfigdata = ["mypy-boto3-appconfigdata (>=1.33.0,<1.34.0)"]
-appfabric = ["mypy-boto3-appfabric (>=1.33.0,<1.34.0)"]
-appflow = ["mypy-boto3-appflow (>=1.33.0,<1.34.0)"]
-appintegrations = ["mypy-boto3-appintegrations (>=1.33.0,<1.34.0)"]
-application-autoscaling = ["mypy-boto3-application-autoscaling (>=1.33.0,<1.34.0)"]
-application-insights = ["mypy-boto3-application-insights (>=1.33.0,<1.34.0)"]
-applicationcostprofiler = ["mypy-boto3-applicationcostprofiler (>=1.33.0,<1.34.0)"]
-appmesh = ["mypy-boto3-appmesh (>=1.33.0,<1.34.0)"]
-apprunner = ["mypy-boto3-apprunner (>=1.33.0,<1.34.0)"]
-appstream = ["mypy-boto3-appstream (>=1.33.0,<1.34.0)"]
-appsync = ["mypy-boto3-appsync (>=1.33.0,<1.34.0)"]
-arc-zonal-shift = ["mypy-boto3-arc-zonal-shift (>=1.33.0,<1.34.0)"]
-athena = ["mypy-boto3-athena (>=1.33.0,<1.34.0)"]
-auditmanager = ["mypy-boto3-auditmanager (>=1.33.0,<1.34.0)"]
-autoscaling = ["mypy-boto3-autoscaling (>=1.33.0,<1.34.0)"]
-autoscaling-plans = ["mypy-boto3-autoscaling-plans (>=1.33.0,<1.34.0)"]
-b2bi = ["mypy-boto3-b2bi (>=1.33.0,<1.34.0)"]
-backup = ["mypy-boto3-backup (>=1.33.0,<1.34.0)"]
-backup-gateway = ["mypy-boto3-backup-gateway (>=1.33.0,<1.34.0)"]
-backupstorage = ["mypy-boto3-backupstorage (>=1.33.0,<1.34.0)"]
-batch = ["mypy-boto3-batch (>=1.33.0,<1.34.0)"]
-bcm-data-exports = ["mypy-boto3-bcm-data-exports (>=1.33.0,<1.34.0)"]
-bedrock = ["mypy-boto3-bedrock (>=1.33.0,<1.34.0)"]
-bedrock-agent = ["mypy-boto3-bedrock-agent (>=1.33.0,<1.34.0)"]
-bedrock-agent-runtime = ["mypy-boto3-bedrock-agent-runtime (>=1.33.0,<1.34.0)"]
-bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.33.0,<1.34.0)"]
-billingconductor = ["mypy-boto3-billingconductor (>=1.33.0,<1.34.0)"]
-boto3 = ["boto3 (==1.33.13)", "botocore (==1.33.13)"]
-braket = ["mypy-boto3-braket (>=1.33.0,<1.34.0)"]
-budgets = ["mypy-boto3-budgets (>=1.33.0,<1.34.0)"]
-ce = ["mypy-boto3-ce (>=1.33.0,<1.34.0)"]
-chime = ["mypy-boto3-chime (>=1.33.0,<1.34.0)"]
-chime-sdk-identity = ["mypy-boto3-chime-sdk-identity (>=1.33.0,<1.34.0)"]
-chime-sdk-media-pipelines = ["mypy-boto3-chime-sdk-media-pipelines (>=1.33.0,<1.34.0)"]
-chime-sdk-meetings = ["mypy-boto3-chime-sdk-meetings (>=1.33.0,<1.34.0)"]
-chime-sdk-messaging = ["mypy-boto3-chime-sdk-messaging (>=1.33.0,<1.34.0)"]
-chime-sdk-voice = ["mypy-boto3-chime-sdk-voice (>=1.33.0,<1.34.0)"]
-cleanrooms = ["mypy-boto3-cleanrooms (>=1.33.0,<1.34.0)"]
-cleanroomsml = ["mypy-boto3-cleanroomsml (>=1.33.0,<1.34.0)"]
-cloud9 = ["mypy-boto3-cloud9 (>=1.33.0,<1.34.0)"]
-cloudcontrol = ["mypy-boto3-cloudcontrol (>=1.33.0,<1.34.0)"]
-clouddirectory = ["mypy-boto3-clouddirectory (>=1.33.0,<1.34.0)"]
-cloudformation = ["mypy-boto3-cloudformation (>=1.33.0,<1.34.0)"]
-cloudfront = ["mypy-boto3-cloudfront (>=1.33.0,<1.34.0)"]
-cloudfront-keyvaluestore = ["mypy-boto3-cloudfront-keyvaluestore (>=1.33.0,<1.34.0)"]
-cloudhsm = ["mypy-boto3-cloudhsm (>=1.33.0,<1.34.0)"]
-cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (>=1.33.0,<1.34.0)"]
-cloudsearch = ["mypy-boto3-cloudsearch (>=1.33.0,<1.34.0)"]
-cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (>=1.33.0,<1.34.0)"]
-cloudtrail = ["mypy-boto3-cloudtrail (>=1.33.0,<1.34.0)"]
-cloudtrail-data = ["mypy-boto3-cloudtrail-data (>=1.33.0,<1.34.0)"]
-cloudwatch = ["mypy-boto3-cloudwatch (>=1.33.0,<1.34.0)"]
-codeartifact = ["mypy-boto3-codeartifact (>=1.33.0,<1.34.0)"]
-codebuild = ["mypy-boto3-codebuild (>=1.33.0,<1.34.0)"]
-codecatalyst = ["mypy-boto3-codecatalyst (>=1.33.0,<1.34.0)"]
-codecommit = ["mypy-boto3-codecommit (>=1.33.0,<1.34.0)"]
-codedeploy = ["mypy-boto3-codedeploy (>=1.33.0,<1.34.0)"]
-codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (>=1.33.0,<1.34.0)"]
-codeguru-security = ["mypy-boto3-codeguru-security (>=1.33.0,<1.34.0)"]
-codeguruprofiler = ["mypy-boto3-codeguruprofiler (>=1.33.0,<1.34.0)"]
-codepipeline = ["mypy-boto3-codepipeline (>=1.33.0,<1.34.0)"]
-codestar = ["mypy-boto3-codestar (>=1.33.0,<1.34.0)"]
-codestar-connections = ["mypy-boto3-codestar-connections (>=1.33.0,<1.34.0)"]
-codestar-notifications = ["mypy-boto3-codestar-notifications (>=1.33.0,<1.34.0)"]
-cognito-identity = ["mypy-boto3-cognito-identity (>=1.33.0,<1.34.0)"]
-cognito-idp = ["mypy-boto3-cognito-idp (>=1.33.0,<1.34.0)"]
-cognito-sync = ["mypy-boto3-cognito-sync (>=1.33.0,<1.34.0)"]
-comprehend = ["mypy-boto3-comprehend (>=1.33.0,<1.34.0)"]
-comprehendmedical = ["mypy-boto3-comprehendmedical (>=1.33.0,<1.34.0)"]
-compute-optimizer = ["mypy-boto3-compute-optimizer (>=1.33.0,<1.34.0)"]
-config = ["mypy-boto3-config (>=1.33.0,<1.34.0)"]
-connect = ["mypy-boto3-connect (>=1.33.0,<1.34.0)"]
-connect-contact-lens = ["mypy-boto3-connect-contact-lens (>=1.33.0,<1.34.0)"]
-connectcampaigns = ["mypy-boto3-connectcampaigns (>=1.33.0,<1.34.0)"]
-connectcases = ["mypy-boto3-connectcases (>=1.33.0,<1.34.0)"]
-connectparticipant = ["mypy-boto3-connectparticipant (>=1.33.0,<1.34.0)"]
-controltower = ["mypy-boto3-controltower (>=1.33.0,<1.34.0)"]
-cost-optimization-hub = ["mypy-boto3-cost-optimization-hub (>=1.33.0,<1.34.0)"]
-cur = ["mypy-boto3-cur (>=1.33.0,<1.34.0)"]
-customer-profiles = ["mypy-boto3-customer-profiles (>=1.33.0,<1.34.0)"]
-databrew = ["mypy-boto3-databrew (>=1.33.0,<1.34.0)"]
-dataexchange = ["mypy-boto3-dataexchange (>=1.33.0,<1.34.0)"]
-datapipeline = ["mypy-boto3-datapipeline (>=1.33.0,<1.34.0)"]
-datasync = ["mypy-boto3-datasync (>=1.33.0,<1.34.0)"]
-datazone = ["mypy-boto3-datazone (>=1.33.0,<1.34.0)"]
-dax = ["mypy-boto3-dax (>=1.33.0,<1.34.0)"]
-detective = ["mypy-boto3-detective (>=1.33.0,<1.34.0)"]
-devicefarm = ["mypy-boto3-devicefarm (>=1.33.0,<1.34.0)"]
-devops-guru = ["mypy-boto3-devops-guru (>=1.33.0,<1.34.0)"]
-directconnect = ["mypy-boto3-directconnect (>=1.33.0,<1.34.0)"]
-discovery = ["mypy-boto3-discovery (>=1.33.0,<1.34.0)"]
-dlm = ["mypy-boto3-dlm (>=1.33.0,<1.34.0)"]
-dms = ["mypy-boto3-dms (>=1.33.0,<1.34.0)"]
-docdb = ["mypy-boto3-docdb (>=1.33.0,<1.34.0)"]
-docdb-elastic = ["mypy-boto3-docdb-elastic (>=1.33.0,<1.34.0)"]
-drs = ["mypy-boto3-drs (>=1.33.0,<1.34.0)"]
-ds = ["mypy-boto3-ds (>=1.33.0,<1.34.0)"]
-dynamodb = ["mypy-boto3-dynamodb (>=1.33.0,<1.34.0)"]
-dynamodbstreams = ["mypy-boto3-dynamodbstreams (>=1.33.0,<1.34.0)"]
-ebs = ["mypy-boto3-ebs (>=1.33.0,<1.34.0)"]
-ec2 = ["mypy-boto3-ec2 (>=1.33.0,<1.34.0)"]
-ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (>=1.33.0,<1.34.0)"]
-ecr = ["mypy-boto3-ecr (>=1.33.0,<1.34.0)"]
-ecr-public = ["mypy-boto3-ecr-public (>=1.33.0,<1.34.0)"]
-ecs = ["mypy-boto3-ecs (>=1.33.0,<1.34.0)"]
-efs = ["mypy-boto3-efs (>=1.33.0,<1.34.0)"]
-eks = ["mypy-boto3-eks (>=1.33.0,<1.34.0)"]
-eks-auth = ["mypy-boto3-eks-auth (>=1.33.0,<1.34.0)"]
-elastic-inference = ["mypy-boto3-elastic-inference (>=1.33.0,<1.34.0)"]
-elasticache = ["mypy-boto3-elasticache (>=1.33.0,<1.34.0)"]
-elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (>=1.33.0,<1.34.0)"]
-elastictranscoder = ["mypy-boto3-elastictranscoder (>=1.33.0,<1.34.0)"]
-elb = ["mypy-boto3-elb (>=1.33.0,<1.34.0)"]
-elbv2 = ["mypy-boto3-elbv2 (>=1.33.0,<1.34.0)"]
-emr = ["mypy-boto3-emr (>=1.33.0,<1.34.0)"]
-emr-containers = ["mypy-boto3-emr-containers (>=1.33.0,<1.34.0)"]
-emr-serverless = ["mypy-boto3-emr-serverless (>=1.33.0,<1.34.0)"]
-entityresolution = ["mypy-boto3-entityresolution (>=1.33.0,<1.34.0)"]
-es = ["mypy-boto3-es (>=1.33.0,<1.34.0)"]
-essential = ["mypy-boto3-cloudformation (>=1.33.0,<1.34.0)", "mypy-boto3-dynamodb (>=1.33.0,<1.34.0)", "mypy-boto3-ec2 (>=1.33.0,<1.34.0)", "mypy-boto3-lambda (>=1.33.0,<1.34.0)", "mypy-boto3-rds (>=1.33.0,<1.34.0)", "mypy-boto3-s3 (>=1.33.0,<1.34.0)", "mypy-boto3-sqs (>=1.33.0,<1.34.0)"]
-events = ["mypy-boto3-events (>=1.33.0,<1.34.0)"]
-evidently = ["mypy-boto3-evidently (>=1.33.0,<1.34.0)"]
-finspace = ["mypy-boto3-finspace (>=1.33.0,<1.34.0)"]
-finspace-data = ["mypy-boto3-finspace-data (>=1.33.0,<1.34.0)"]
-firehose = ["mypy-boto3-firehose (>=1.33.0,<1.34.0)"]
-fis = ["mypy-boto3-fis (>=1.33.0,<1.34.0)"]
-fms = ["mypy-boto3-fms (>=1.33.0,<1.34.0)"]
-forecast = ["mypy-boto3-forecast (>=1.33.0,<1.34.0)"]
-forecastquery = ["mypy-boto3-forecastquery (>=1.33.0,<1.34.0)"]
-frauddetector = ["mypy-boto3-frauddetector (>=1.33.0,<1.34.0)"]
-freetier = ["mypy-boto3-freetier (>=1.33.0,<1.34.0)"]
-fsx = ["mypy-boto3-fsx (>=1.33.0,<1.34.0)"]
-gamelift = ["mypy-boto3-gamelift (>=1.33.0,<1.34.0)"]
-glacier = ["mypy-boto3-glacier (>=1.33.0,<1.34.0)"]
-globalaccelerator = ["mypy-boto3-globalaccelerator (>=1.33.0,<1.34.0)"]
-glue = ["mypy-boto3-glue (>=1.33.0,<1.34.0)"]
-grafana = ["mypy-boto3-grafana (>=1.33.0,<1.34.0)"]
-greengrass = ["mypy-boto3-greengrass (>=1.33.0,<1.34.0)"]
-greengrassv2 = ["mypy-boto3-greengrassv2 (>=1.33.0,<1.34.0)"]
-groundstation = ["mypy-boto3-groundstation (>=1.33.0,<1.34.0)"]
-guardduty = ["mypy-boto3-guardduty (>=1.33.0,<1.34.0)"]
-health = ["mypy-boto3-health (>=1.33.0,<1.34.0)"]
-healthlake = ["mypy-boto3-healthlake (>=1.33.0,<1.34.0)"]
-honeycode = ["mypy-boto3-honeycode (>=1.33.0,<1.34.0)"]
-iam = ["mypy-boto3-iam (>=1.33.0,<1.34.0)"]
-identitystore = ["mypy-boto3-identitystore (>=1.33.0,<1.34.0)"]
-imagebuilder = ["mypy-boto3-imagebuilder (>=1.33.0,<1.34.0)"]
-importexport = ["mypy-boto3-importexport (>=1.33.0,<1.34.0)"]
-inspector = ["mypy-boto3-inspector (>=1.33.0,<1.34.0)"]
-inspector-scan = ["mypy-boto3-inspector-scan (>=1.33.0,<1.34.0)"]
-inspector2 = ["mypy-boto3-inspector2 (>=1.33.0,<1.34.0)"]
-internetmonitor = ["mypy-boto3-internetmonitor (>=1.33.0,<1.34.0)"]
-iot = ["mypy-boto3-iot (>=1.33.0,<1.34.0)"]
-iot-data = ["mypy-boto3-iot-data (>=1.33.0,<1.34.0)"]
-iot-jobs-data = ["mypy-boto3-iot-jobs-data (>=1.33.0,<1.34.0)"]
-iot-roborunner = ["mypy-boto3-iot-roborunner (>=1.33.0,<1.34.0)"]
-iot1click-devices = ["mypy-boto3-iot1click-devices (>=1.33.0,<1.34.0)"]
-iot1click-projects = ["mypy-boto3-iot1click-projects (>=1.33.0,<1.34.0)"]
-iotanalytics = ["mypy-boto3-iotanalytics (>=1.33.0,<1.34.0)"]
-iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (>=1.33.0,<1.34.0)"]
-iotevents = ["mypy-boto3-iotevents (>=1.33.0,<1.34.0)"]
-iotevents-data = ["mypy-boto3-iotevents-data (>=1.33.0,<1.34.0)"]
-iotfleethub = ["mypy-boto3-iotfleethub (>=1.33.0,<1.34.0)"]
-iotfleetwise = ["mypy-boto3-iotfleetwise (>=1.33.0,<1.34.0)"]
-iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (>=1.33.0,<1.34.0)"]
-iotsitewise = ["mypy-boto3-iotsitewise (>=1.33.0,<1.34.0)"]
-iotthingsgraph = ["mypy-boto3-iotthingsgraph (>=1.33.0,<1.34.0)"]
-iottwinmaker = ["mypy-boto3-iottwinmaker (>=1.33.0,<1.34.0)"]
-iotwireless = ["mypy-boto3-iotwireless (>=1.33.0,<1.34.0)"]
-ivs = ["mypy-boto3-ivs (>=1.33.0,<1.34.0)"]
-ivs-realtime = ["mypy-boto3-ivs-realtime (>=1.33.0,<1.34.0)"]
-ivschat = ["mypy-boto3-ivschat (>=1.33.0,<1.34.0)"]
-kafka = ["mypy-boto3-kafka (>=1.33.0,<1.34.0)"]
-kafkaconnect = ["mypy-boto3-kafkaconnect (>=1.33.0,<1.34.0)"]
-kendra = ["mypy-boto3-kendra (>=1.33.0,<1.34.0)"]
-kendra-ranking = ["mypy-boto3-kendra-ranking (>=1.33.0,<1.34.0)"]
-keyspaces = ["mypy-boto3-keyspaces (>=1.33.0,<1.34.0)"]
-kinesis = ["mypy-boto3-kinesis (>=1.33.0,<1.34.0)"]
-kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (>=1.33.0,<1.34.0)"]
-kinesis-video-media = ["mypy-boto3-kinesis-video-media (>=1.33.0,<1.34.0)"]
-kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (>=1.33.0,<1.34.0)"]
-kinesis-video-webrtc-storage = ["mypy-boto3-kinesis-video-webrtc-storage (>=1.33.0,<1.34.0)"]
-kinesisanalytics = ["mypy-boto3-kinesisanalytics (>=1.33.0,<1.34.0)"]
-kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (>=1.33.0,<1.34.0)"]
-kinesisvideo = ["mypy-boto3-kinesisvideo (>=1.33.0,<1.34.0)"]
-kms = ["mypy-boto3-kms (>=1.33.0,<1.34.0)"]
-lakeformation = ["mypy-boto3-lakeformation (>=1.33.0,<1.34.0)"]
-lambda = ["mypy-boto3-lambda (>=1.33.0,<1.34.0)"]
-launch-wizard = ["mypy-boto3-launch-wizard (>=1.33.0,<1.34.0)"]
-lex-models = ["mypy-boto3-lex-models (>=1.33.0,<1.34.0)"]
-lex-runtime = ["mypy-boto3-lex-runtime (>=1.33.0,<1.34.0)"]
-lexv2-models = ["mypy-boto3-lexv2-models (>=1.33.0,<1.34.0)"]
-lexv2-runtime = ["mypy-boto3-lexv2-runtime (>=1.33.0,<1.34.0)"]
-license-manager = ["mypy-boto3-license-manager (>=1.33.0,<1.34.0)"]
-license-manager-linux-subscriptions = ["mypy-boto3-license-manager-linux-subscriptions (>=1.33.0,<1.34.0)"]
-license-manager-user-subscriptions = ["mypy-boto3-license-manager-user-subscriptions (>=1.33.0,<1.34.0)"]
-lightsail = ["mypy-boto3-lightsail (>=1.33.0,<1.34.0)"]
-location = ["mypy-boto3-location (>=1.33.0,<1.34.0)"]
-logs = ["mypy-boto3-logs (>=1.33.0,<1.34.0)"]
-lookoutequipment = ["mypy-boto3-lookoutequipment (>=1.33.0,<1.34.0)"]
-lookoutmetrics = ["mypy-boto3-lookoutmetrics (>=1.33.0,<1.34.0)"]
-lookoutvision = ["mypy-boto3-lookoutvision (>=1.33.0,<1.34.0)"]
-m2 = ["mypy-boto3-m2 (>=1.33.0,<1.34.0)"]
-machinelearning = ["mypy-boto3-machinelearning (>=1.33.0,<1.34.0)"]
-macie2 = ["mypy-boto3-macie2 (>=1.33.0,<1.34.0)"]
-managedblockchain = ["mypy-boto3-managedblockchain (>=1.33.0,<1.34.0)"]
-managedblockchain-query = ["mypy-boto3-managedblockchain-query (>=1.33.0,<1.34.0)"]
-marketplace-agreement = ["mypy-boto3-marketplace-agreement (>=1.33.0,<1.34.0)"]
-marketplace-catalog = ["mypy-boto3-marketplace-catalog (>=1.33.0,<1.34.0)"]
-marketplace-deployment = ["mypy-boto3-marketplace-deployment (>=1.33.0,<1.34.0)"]
-marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (>=1.33.0,<1.34.0)"]
-marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (>=1.33.0,<1.34.0)"]
-mediaconnect = ["mypy-boto3-mediaconnect (>=1.33.0,<1.34.0)"]
-mediaconvert = ["mypy-boto3-mediaconvert (>=1.33.0,<1.34.0)"]
-medialive = ["mypy-boto3-medialive (>=1.33.0,<1.34.0)"]
-mediapackage = ["mypy-boto3-mediapackage (>=1.33.0,<1.34.0)"]
-mediapackage-vod = ["mypy-boto3-mediapackage-vod (>=1.33.0,<1.34.0)"]
-mediapackagev2 = ["mypy-boto3-mediapackagev2 (>=1.33.0,<1.34.0)"]
-mediastore = ["mypy-boto3-mediastore (>=1.33.0,<1.34.0)"]
-mediastore-data = ["mypy-boto3-mediastore-data (>=1.33.0,<1.34.0)"]
-mediatailor = ["mypy-boto3-mediatailor (>=1.33.0,<1.34.0)"]
-medical-imaging = ["mypy-boto3-medical-imaging (>=1.33.0,<1.34.0)"]
-memorydb = ["mypy-boto3-memorydb (>=1.33.0,<1.34.0)"]
-meteringmarketplace = ["mypy-boto3-meteringmarketplace (>=1.33.0,<1.34.0)"]
-mgh = ["mypy-boto3-mgh (>=1.33.0,<1.34.0)"]
-mgn = ["mypy-boto3-mgn (>=1.33.0,<1.34.0)"]
-migration-hub-refactor-spaces = ["mypy-boto3-migration-hub-refactor-spaces (>=1.33.0,<1.34.0)"]
-migrationhub-config = ["mypy-boto3-migrationhub-config (>=1.33.0,<1.34.0)"]
-migrationhuborchestrator = ["mypy-boto3-migrationhuborchestrator (>=1.33.0,<1.34.0)"]
-migrationhubstrategy = ["mypy-boto3-migrationhubstrategy (>=1.33.0,<1.34.0)"]
-mobile = ["mypy-boto3-mobile (>=1.33.0,<1.34.0)"]
-mq = ["mypy-boto3-mq (>=1.33.0,<1.34.0)"]
-mturk = ["mypy-boto3-mturk (>=1.33.0,<1.34.0)"]
-mwaa = ["mypy-boto3-mwaa (>=1.33.0,<1.34.0)"]
-neptune = ["mypy-boto3-neptune (>=1.33.0,<1.34.0)"]
-neptunedata = ["mypy-boto3-neptunedata (>=1.33.0,<1.34.0)"]
-network-firewall = ["mypy-boto3-network-firewall (>=1.33.0,<1.34.0)"]
-networkmanager = ["mypy-boto3-networkmanager (>=1.33.0,<1.34.0)"]
-nimble = ["mypy-boto3-nimble (>=1.33.0,<1.34.0)"]
-oam = ["mypy-boto3-oam (>=1.33.0,<1.34.0)"]
-omics = ["mypy-boto3-omics (>=1.33.0,<1.34.0)"]
-opensearch = ["mypy-boto3-opensearch (>=1.33.0,<1.34.0)"]
-opensearchserverless = ["mypy-boto3-opensearchserverless (>=1.33.0,<1.34.0)"]
-opsworks = ["mypy-boto3-opsworks (>=1.33.0,<1.34.0)"]
-opsworkscm = ["mypy-boto3-opsworkscm (>=1.33.0,<1.34.0)"]
-organizations = ["mypy-boto3-organizations (>=1.33.0,<1.34.0)"]
-osis = ["mypy-boto3-osis (>=1.33.0,<1.34.0)"]
-outposts = ["mypy-boto3-outposts (>=1.33.0,<1.34.0)"]
-panorama = ["mypy-boto3-panorama (>=1.33.0,<1.34.0)"]
-payment-cryptography = ["mypy-boto3-payment-cryptography (>=1.33.0,<1.34.0)"]
-payment-cryptography-data = ["mypy-boto3-payment-cryptography-data (>=1.33.0,<1.34.0)"]
-pca-connector-ad = ["mypy-boto3-pca-connector-ad (>=1.33.0,<1.34.0)"]
-personalize = ["mypy-boto3-personalize (>=1.33.0,<1.34.0)"]
-personalize-events = ["mypy-boto3-personalize-events (>=1.33.0,<1.34.0)"]
-personalize-runtime = ["mypy-boto3-personalize-runtime (>=1.33.0,<1.34.0)"]
-pi = ["mypy-boto3-pi (>=1.33.0,<1.34.0)"]
-pinpoint = ["mypy-boto3-pinpoint (>=1.33.0,<1.34.0)"]
-pinpoint-email = ["mypy-boto3-pinpoint-email (>=1.33.0,<1.34.0)"]
-pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (>=1.33.0,<1.34.0)"]
-pinpoint-sms-voice-v2 = ["mypy-boto3-pinpoint-sms-voice-v2 (>=1.33.0,<1.34.0)"]
-pipes = ["mypy-boto3-pipes (>=1.33.0,<1.34.0)"]
-polly = ["mypy-boto3-polly (>=1.33.0,<1.34.0)"]
-pricing = ["mypy-boto3-pricing (>=1.33.0,<1.34.0)"]
-privatenetworks = ["mypy-boto3-privatenetworks (>=1.33.0,<1.34.0)"]
-proton = ["mypy-boto3-proton (>=1.33.0,<1.34.0)"]
-qbusiness = ["mypy-boto3-qbusiness (>=1.33.0,<1.34.0)"]
-qconnect = ["mypy-boto3-qconnect (>=1.33.0,<1.34.0)"]
-qldb = ["mypy-boto3-qldb (>=1.33.0,<1.34.0)"]
-qldb-session = ["mypy-boto3-qldb-session (>=1.33.0,<1.34.0)"]
-quicksight = ["mypy-boto3-quicksight (>=1.33.0,<1.34.0)"]
-ram = ["mypy-boto3-ram (>=1.33.0,<1.34.0)"]
-rbin = ["mypy-boto3-rbin (>=1.33.0,<1.34.0)"]
-rds = ["mypy-boto3-rds (>=1.33.0,<1.34.0)"]
-rds-data = ["mypy-boto3-rds-data (>=1.33.0,<1.34.0)"]
-redshift = ["mypy-boto3-redshift (>=1.33.0,<1.34.0)"]
-redshift-data = ["mypy-boto3-redshift-data (>=1.33.0,<1.34.0)"]
-redshift-serverless = ["mypy-boto3-redshift-serverless (>=1.33.0,<1.34.0)"]
-rekognition = ["mypy-boto3-rekognition (>=1.33.0,<1.34.0)"]
-repostspace = ["mypy-boto3-repostspace (>=1.33.0,<1.34.0)"]
-resiliencehub = ["mypy-boto3-resiliencehub (>=1.33.0,<1.34.0)"]
-resource-explorer-2 = ["mypy-boto3-resource-explorer-2 (>=1.33.0,<1.34.0)"]
-resource-groups = ["mypy-boto3-resource-groups (>=1.33.0,<1.34.0)"]
-resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (>=1.33.0,<1.34.0)"]
-robomaker = ["mypy-boto3-robomaker (>=1.33.0,<1.34.0)"]
-rolesanywhere = ["mypy-boto3-rolesanywhere (>=1.33.0,<1.34.0)"]
-route53 = ["mypy-boto3-route53 (>=1.33.0,<1.34.0)"]
-route53-recovery-cluster = ["mypy-boto3-route53-recovery-cluster (>=1.33.0,<1.34.0)"]
-route53-recovery-control-config = ["mypy-boto3-route53-recovery-control-config (>=1.33.0,<1.34.0)"]
-route53-recovery-readiness = ["mypy-boto3-route53-recovery-readiness (>=1.33.0,<1.34.0)"]
-route53domains = ["mypy-boto3-route53domains (>=1.33.0,<1.34.0)"]
-route53resolver = ["mypy-boto3-route53resolver (>=1.33.0,<1.34.0)"]
-rum = ["mypy-boto3-rum (>=1.33.0,<1.34.0)"]
-s3 = ["mypy-boto3-s3 (>=1.33.0,<1.34.0)"]
-s3control = ["mypy-boto3-s3control (>=1.33.0,<1.34.0)"]
-s3outposts = ["mypy-boto3-s3outposts (>=1.33.0,<1.34.0)"]
-sagemaker = ["mypy-boto3-sagemaker (>=1.33.0,<1.34.0)"]
-sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (>=1.33.0,<1.34.0)"]
-sagemaker-edge = ["mypy-boto3-sagemaker-edge (>=1.33.0,<1.34.0)"]
-sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (>=1.33.0,<1.34.0)"]
-sagemaker-geospatial = ["mypy-boto3-sagemaker-geospatial (>=1.33.0,<1.34.0)"]
-sagemaker-metrics = ["mypy-boto3-sagemaker-metrics (>=1.33.0,<1.34.0)"]
-sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (>=1.33.0,<1.34.0)"]
-savingsplans = ["mypy-boto3-savingsplans (>=1.33.0,<1.34.0)"]
-scheduler = ["mypy-boto3-scheduler (>=1.33.0,<1.34.0)"]
-schemas = ["mypy-boto3-schemas (>=1.33.0,<1.34.0)"]
-sdb = ["mypy-boto3-sdb (>=1.33.0,<1.34.0)"]
-secretsmanager = ["mypy-boto3-secretsmanager (>=1.33.0,<1.34.0)"]
-securityhub = ["mypy-boto3-securityhub (>=1.33.0,<1.34.0)"]
-securitylake = ["mypy-boto3-securitylake (>=1.33.0,<1.34.0)"]
-serverlessrepo = ["mypy-boto3-serverlessrepo (>=1.33.0,<1.34.0)"]
-service-quotas = ["mypy-boto3-service-quotas (>=1.33.0,<1.34.0)"]
-servicecatalog = ["mypy-boto3-servicecatalog (>=1.33.0,<1.34.0)"]
-servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (>=1.33.0,<1.34.0)"]
-servicediscovery = ["mypy-boto3-servicediscovery (>=1.33.0,<1.34.0)"]
-ses = ["mypy-boto3-ses (>=1.33.0,<1.34.0)"]
-sesv2 = ["mypy-boto3-sesv2 (>=1.33.0,<1.34.0)"]
-shield = ["mypy-boto3-shield (>=1.33.0,<1.34.0)"]
-signer = ["mypy-boto3-signer (>=1.33.0,<1.34.0)"]
-simspaceweaver = ["mypy-boto3-simspaceweaver (>=1.33.0,<1.34.0)"]
-sms = ["mypy-boto3-sms (>=1.33.0,<1.34.0)"]
-sms-voice = ["mypy-boto3-sms-voice (>=1.33.0,<1.34.0)"]
-snow-device-management = ["mypy-boto3-snow-device-management (>=1.33.0,<1.34.0)"]
-snowball = ["mypy-boto3-snowball (>=1.33.0,<1.34.0)"]
-sns = ["mypy-boto3-sns (>=1.33.0,<1.34.0)"]
-sqs = ["mypy-boto3-sqs (>=1.33.0,<1.34.0)"]
-ssm = ["mypy-boto3-ssm (>=1.33.0,<1.34.0)"]
-ssm-contacts = ["mypy-boto3-ssm-contacts (>=1.33.0,<1.34.0)"]
-ssm-incidents = ["mypy-boto3-ssm-incidents (>=1.33.0,<1.34.0)"]
-ssm-sap = ["mypy-boto3-ssm-sap (>=1.33.0,<1.34.0)"]
-sso = ["mypy-boto3-sso (>=1.33.0,<1.34.0)"]
-sso-admin = ["mypy-boto3-sso-admin (>=1.33.0,<1.34.0)"]
-sso-oidc = ["mypy-boto3-sso-oidc (>=1.33.0,<1.34.0)"]
-stepfunctions = ["mypy-boto3-stepfunctions (>=1.33.0,<1.34.0)"]
-storagegateway = ["mypy-boto3-storagegateway (>=1.33.0,<1.34.0)"]
-sts = ["mypy-boto3-sts (>=1.33.0,<1.34.0)"]
-support = ["mypy-boto3-support (>=1.33.0,<1.34.0)"]
-support-app = ["mypy-boto3-support-app (>=1.33.0,<1.34.0)"]
-swf = ["mypy-boto3-swf (>=1.33.0,<1.34.0)"]
-synthetics = ["mypy-boto3-synthetics (>=1.33.0,<1.34.0)"]
-textract = ["mypy-boto3-textract (>=1.33.0,<1.34.0)"]
-timestream-query = ["mypy-boto3-timestream-query (>=1.33.0,<1.34.0)"]
-timestream-write = ["mypy-boto3-timestream-write (>=1.33.0,<1.34.0)"]
-tnb = ["mypy-boto3-tnb (>=1.33.0,<1.34.0)"]
-transcribe = ["mypy-boto3-transcribe (>=1.33.0,<1.34.0)"]
-transfer = ["mypy-boto3-transfer (>=1.33.0,<1.34.0)"]
-translate = ["mypy-boto3-translate (>=1.33.0,<1.34.0)"]
-trustedadvisor = ["mypy-boto3-trustedadvisor (>=1.33.0,<1.34.0)"]
-verifiedpermissions = ["mypy-boto3-verifiedpermissions (>=1.33.0,<1.34.0)"]
-voice-id = ["mypy-boto3-voice-id (>=1.33.0,<1.34.0)"]
-vpc-lattice = ["mypy-boto3-vpc-lattice (>=1.33.0,<1.34.0)"]
-waf = ["mypy-boto3-waf (>=1.33.0,<1.34.0)"]
-waf-regional = ["mypy-boto3-waf-regional (>=1.33.0,<1.34.0)"]
-wafv2 = ["mypy-boto3-wafv2 (>=1.33.0,<1.34.0)"]
-wellarchitected = ["mypy-boto3-wellarchitected (>=1.33.0,<1.34.0)"]
-wisdom = ["mypy-boto3-wisdom (>=1.33.0,<1.34.0)"]
-workdocs = ["mypy-boto3-workdocs (>=1.33.0,<1.34.0)"]
-worklink = ["mypy-boto3-worklink (>=1.33.0,<1.34.0)"]
-workmail = ["mypy-boto3-workmail (>=1.33.0,<1.34.0)"]
-workmailmessageflow = ["mypy-boto3-workmailmessageflow (>=1.33.0,<1.34.0)"]
-workspaces = ["mypy-boto3-workspaces (>=1.33.0,<1.34.0)"]
-workspaces-thin-client = ["mypy-boto3-workspaces-thin-client (>=1.33.0,<1.34.0)"]
-workspaces-web = ["mypy-boto3-workspaces-web (>=1.33.0,<1.34.0)"]
-xray = ["mypy-boto3-xray (>=1.33.0,<1.34.0)"]
+accessanalyzer = ["mypy-boto3-accessanalyzer (>=1.34.0,<1.35.0)"]
+account = ["mypy-boto3-account (>=1.34.0,<1.35.0)"]
+acm = ["mypy-boto3-acm (>=1.34.0,<1.35.0)"]
+acm-pca = ["mypy-boto3-acm-pca (>=1.34.0,<1.35.0)"]
+alexaforbusiness = ["mypy-boto3-alexaforbusiness (>=1.34.0,<1.35.0)"]
+all = ["mypy-boto3-accessanalyzer (>=1.34.0,<1.35.0)", "mypy-boto3-account (>=1.34.0,<1.35.0)", "mypy-boto3-acm (>=1.34.0,<1.35.0)", "mypy-boto3-acm-pca (>=1.34.0,<1.35.0)", "mypy-boto3-alexaforbusiness (>=1.34.0,<1.35.0)", "mypy-boto3-amp (>=1.34.0,<1.35.0)", "mypy-boto3-amplify (>=1.34.0,<1.35.0)", "mypy-boto3-amplifybackend (>=1.34.0,<1.35.0)", "mypy-boto3-amplifyuibuilder (>=1.34.0,<1.35.0)", "mypy-boto3-apigateway (>=1.34.0,<1.35.0)", "mypy-boto3-apigatewaymanagementapi (>=1.34.0,<1.35.0)", "mypy-boto3-apigatewayv2 (>=1.34.0,<1.35.0)", "mypy-boto3-appconfig (>=1.34.0,<1.35.0)", "mypy-boto3-appconfigdata (>=1.34.0,<1.35.0)", "mypy-boto3-appfabric (>=1.34.0,<1.35.0)", "mypy-boto3-appflow (>=1.34.0,<1.35.0)", "mypy-boto3-appintegrations (>=1.34.0,<1.35.0)", "mypy-boto3-application-autoscaling (>=1.34.0,<1.35.0)", "mypy-boto3-application-insights (>=1.34.0,<1.35.0)", "mypy-boto3-applicationcostprofiler (>=1.34.0,<1.35.0)", "mypy-boto3-appmesh (>=1.34.0,<1.35.0)", "mypy-boto3-apprunner (>=1.34.0,<1.35.0)", "mypy-boto3-appstream (>=1.34.0,<1.35.0)", "mypy-boto3-appsync (>=1.34.0,<1.35.0)", "mypy-boto3-arc-zonal-shift (>=1.34.0,<1.35.0)", "mypy-boto3-athena (>=1.34.0,<1.35.0)", "mypy-boto3-auditmanager (>=1.34.0,<1.35.0)", "mypy-boto3-autoscaling (>=1.34.0,<1.35.0)", "mypy-boto3-autoscaling-plans (>=1.34.0,<1.35.0)", "mypy-boto3-b2bi (>=1.34.0,<1.35.0)", "mypy-boto3-backup (>=1.34.0,<1.35.0)", "mypy-boto3-backup-gateway (>=1.34.0,<1.35.0)", "mypy-boto3-backupstorage (>=1.34.0,<1.35.0)", "mypy-boto3-batch (>=1.34.0,<1.35.0)", "mypy-boto3-bcm-data-exports (>=1.34.0,<1.35.0)", "mypy-boto3-bedrock (>=1.34.0,<1.35.0)", "mypy-boto3-bedrock-agent (>=1.34.0,<1.35.0)", "mypy-boto3-bedrock-agent-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-bedrock-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-billingconductor (>=1.34.0,<1.35.0)", "mypy-boto3-braket (>=1.34.0,<1.35.0)", "mypy-boto3-budgets (>=1.34.0,<1.35.0)", "mypy-boto3-ce (>=1.34.0,<1.35.0)", "mypy-boto3-chime (>=1.34.0,<1.35.0)", "mypy-boto3-chime-sdk-identity (>=1.34.0,<1.35.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.34.0,<1.35.0)", "mypy-boto3-chime-sdk-meetings (>=1.34.0,<1.35.0)", "mypy-boto3-chime-sdk-messaging (>=1.34.0,<1.35.0)", "mypy-boto3-chime-sdk-voice (>=1.34.0,<1.35.0)", "mypy-boto3-cleanrooms (>=1.34.0,<1.35.0)", "mypy-boto3-cleanroomsml (>=1.34.0,<1.35.0)", "mypy-boto3-cloud9 (>=1.34.0,<1.35.0)", "mypy-boto3-cloudcontrol (>=1.34.0,<1.35.0)", "mypy-boto3-clouddirectory (>=1.34.0,<1.35.0)", "mypy-boto3-cloudformation (>=1.34.0,<1.35.0)", "mypy-boto3-cloudfront (>=1.34.0,<1.35.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.34.0,<1.35.0)", "mypy-boto3-cloudhsm (>=1.34.0,<1.35.0)", "mypy-boto3-cloudhsmv2 (>=1.34.0,<1.35.0)", "mypy-boto3-cloudsearch (>=1.34.0,<1.35.0)", "mypy-boto3-cloudsearchdomain (>=1.34.0,<1.35.0)", "mypy-boto3-cloudtrail (>=1.34.0,<1.35.0)", "mypy-boto3-cloudtrail-data (>=1.34.0,<1.35.0)", "mypy-boto3-cloudwatch (>=1.34.0,<1.35.0)", "mypy-boto3-codeartifact (>=1.34.0,<1.35.0)", "mypy-boto3-codebuild (>=1.34.0,<1.35.0)", "mypy-boto3-codecatalyst (>=1.34.0,<1.35.0)", "mypy-boto3-codecommit (>=1.34.0,<1.35.0)", "mypy-boto3-codedeploy (>=1.34.0,<1.35.0)", "mypy-boto3-codeguru-reviewer (>=1.34.0,<1.35.0)", "mypy-boto3-codeguru-security (>=1.34.0,<1.35.0)", "mypy-boto3-codeguruprofiler (>=1.34.0,<1.35.0)", "mypy-boto3-codepipeline (>=1.34.0,<1.35.0)", "mypy-boto3-codestar (>=1.34.0,<1.35.0)", "mypy-boto3-codestar-connections (>=1.34.0,<1.35.0)", "mypy-boto3-codestar-notifications (>=1.34.0,<1.35.0)", "mypy-boto3-cognito-identity (>=1.34.0,<1.35.0)", "mypy-boto3-cognito-idp (>=1.34.0,<1.35.0)", "mypy-boto3-cognito-sync (>=1.34.0,<1.35.0)", "mypy-boto3-comprehend (>=1.34.0,<1.35.0)", "mypy-boto3-comprehendmedical (>=1.34.0,<1.35.0)", "mypy-boto3-compute-optimizer (>=1.34.0,<1.35.0)", "mypy-boto3-config (>=1.34.0,<1.35.0)", "mypy-boto3-connect (>=1.34.0,<1.35.0)", "mypy-boto3-connect-contact-lens (>=1.34.0,<1.35.0)", "mypy-boto3-connectcampaigns (>=1.34.0,<1.35.0)", "mypy-boto3-connectcases (>=1.34.0,<1.35.0)", "mypy-boto3-connectparticipant (>=1.34.0,<1.35.0)", "mypy-boto3-controltower (>=1.34.0,<1.35.0)", "mypy-boto3-cost-optimization-hub (>=1.34.0,<1.35.0)", "mypy-boto3-cur (>=1.34.0,<1.35.0)", "mypy-boto3-customer-profiles (>=1.34.0,<1.35.0)", "mypy-boto3-databrew (>=1.34.0,<1.35.0)", "mypy-boto3-dataexchange (>=1.34.0,<1.35.0)", "mypy-boto3-datapipeline (>=1.34.0,<1.35.0)", "mypy-boto3-datasync (>=1.34.0,<1.35.0)", "mypy-boto3-datazone (>=1.34.0,<1.35.0)", "mypy-boto3-dax (>=1.34.0,<1.35.0)", "mypy-boto3-detective (>=1.34.0,<1.35.0)", "mypy-boto3-devicefarm (>=1.34.0,<1.35.0)", "mypy-boto3-devops-guru (>=1.34.0,<1.35.0)", "mypy-boto3-directconnect (>=1.34.0,<1.35.0)", "mypy-boto3-discovery (>=1.34.0,<1.35.0)", "mypy-boto3-dlm (>=1.34.0,<1.35.0)", "mypy-boto3-dms (>=1.34.0,<1.35.0)", "mypy-boto3-docdb (>=1.34.0,<1.35.0)", "mypy-boto3-docdb-elastic (>=1.34.0,<1.35.0)", "mypy-boto3-drs (>=1.34.0,<1.35.0)", "mypy-boto3-ds (>=1.34.0,<1.35.0)", "mypy-boto3-dynamodb (>=1.34.0,<1.35.0)", "mypy-boto3-dynamodbstreams (>=1.34.0,<1.35.0)", "mypy-boto3-ebs (>=1.34.0,<1.35.0)", "mypy-boto3-ec2 (>=1.34.0,<1.35.0)", "mypy-boto3-ec2-instance-connect (>=1.34.0,<1.35.0)", "mypy-boto3-ecr (>=1.34.0,<1.35.0)", "mypy-boto3-ecr-public (>=1.34.0,<1.35.0)", "mypy-boto3-ecs (>=1.34.0,<1.35.0)", "mypy-boto3-efs (>=1.34.0,<1.35.0)", "mypy-boto3-eks (>=1.34.0,<1.35.0)", "mypy-boto3-eks-auth (>=1.34.0,<1.35.0)", "mypy-boto3-elastic-inference (>=1.34.0,<1.35.0)", "mypy-boto3-elasticache (>=1.34.0,<1.35.0)", "mypy-boto3-elasticbeanstalk (>=1.34.0,<1.35.0)", "mypy-boto3-elastictranscoder (>=1.34.0,<1.35.0)", "mypy-boto3-elb (>=1.34.0,<1.35.0)", "mypy-boto3-elbv2 (>=1.34.0,<1.35.0)", "mypy-boto3-emr (>=1.34.0,<1.35.0)", "mypy-boto3-emr-containers (>=1.34.0,<1.35.0)", "mypy-boto3-emr-serverless (>=1.34.0,<1.35.0)", "mypy-boto3-entityresolution (>=1.34.0,<1.35.0)", "mypy-boto3-es (>=1.34.0,<1.35.0)", "mypy-boto3-events (>=1.34.0,<1.35.0)", "mypy-boto3-evidently (>=1.34.0,<1.35.0)", "mypy-boto3-finspace (>=1.34.0,<1.35.0)", "mypy-boto3-finspace-data (>=1.34.0,<1.35.0)", "mypy-boto3-firehose (>=1.34.0,<1.35.0)", "mypy-boto3-fis (>=1.34.0,<1.35.0)", "mypy-boto3-fms (>=1.34.0,<1.35.0)", "mypy-boto3-forecast (>=1.34.0,<1.35.0)", "mypy-boto3-forecastquery (>=1.34.0,<1.35.0)", "mypy-boto3-frauddetector (>=1.34.0,<1.35.0)", "mypy-boto3-freetier (>=1.34.0,<1.35.0)", "mypy-boto3-fsx (>=1.34.0,<1.35.0)", "mypy-boto3-gamelift (>=1.34.0,<1.35.0)", "mypy-boto3-glacier (>=1.34.0,<1.35.0)", "mypy-boto3-globalaccelerator (>=1.34.0,<1.35.0)", "mypy-boto3-glue (>=1.34.0,<1.35.0)", "mypy-boto3-grafana (>=1.34.0,<1.35.0)", "mypy-boto3-greengrass (>=1.34.0,<1.35.0)", "mypy-boto3-greengrassv2 (>=1.34.0,<1.35.0)", "mypy-boto3-groundstation (>=1.34.0,<1.35.0)", "mypy-boto3-guardduty (>=1.34.0,<1.35.0)", "mypy-boto3-health (>=1.34.0,<1.35.0)", "mypy-boto3-healthlake (>=1.34.0,<1.35.0)", "mypy-boto3-honeycode (>=1.34.0,<1.35.0)", "mypy-boto3-iam (>=1.34.0,<1.35.0)", "mypy-boto3-identitystore (>=1.34.0,<1.35.0)", "mypy-boto3-imagebuilder (>=1.34.0,<1.35.0)", "mypy-boto3-importexport (>=1.34.0,<1.35.0)", "mypy-boto3-inspector (>=1.34.0,<1.35.0)", "mypy-boto3-inspector-scan (>=1.34.0,<1.35.0)", "mypy-boto3-inspector2 (>=1.34.0,<1.35.0)", "mypy-boto3-internetmonitor (>=1.34.0,<1.35.0)", "mypy-boto3-iot (>=1.34.0,<1.35.0)", "mypy-boto3-iot-data (>=1.34.0,<1.35.0)", "mypy-boto3-iot-jobs-data (>=1.34.0,<1.35.0)", "mypy-boto3-iot-roborunner (>=1.34.0,<1.35.0)", "mypy-boto3-iot1click-devices (>=1.34.0,<1.35.0)", "mypy-boto3-iot1click-projects (>=1.34.0,<1.35.0)", "mypy-boto3-iotanalytics (>=1.34.0,<1.35.0)", "mypy-boto3-iotdeviceadvisor (>=1.34.0,<1.35.0)", "mypy-boto3-iotevents (>=1.34.0,<1.35.0)", "mypy-boto3-iotevents-data (>=1.34.0,<1.35.0)", "mypy-boto3-iotfleethub (>=1.34.0,<1.35.0)", "mypy-boto3-iotfleetwise (>=1.34.0,<1.35.0)", "mypy-boto3-iotsecuretunneling (>=1.34.0,<1.35.0)", "mypy-boto3-iotsitewise (>=1.34.0,<1.35.0)", "mypy-boto3-iotthingsgraph (>=1.34.0,<1.35.0)", "mypy-boto3-iottwinmaker (>=1.34.0,<1.35.0)", "mypy-boto3-iotwireless (>=1.34.0,<1.35.0)", "mypy-boto3-ivs (>=1.34.0,<1.35.0)", "mypy-boto3-ivs-realtime (>=1.34.0,<1.35.0)", "mypy-boto3-ivschat (>=1.34.0,<1.35.0)", "mypy-boto3-kafka (>=1.34.0,<1.35.0)", "mypy-boto3-kafkaconnect (>=1.34.0,<1.35.0)", "mypy-boto3-kendra (>=1.34.0,<1.35.0)", "mypy-boto3-kendra-ranking (>=1.34.0,<1.35.0)", "mypy-boto3-keyspaces (>=1.34.0,<1.35.0)", "mypy-boto3-kinesis (>=1.34.0,<1.35.0)", "mypy-boto3-kinesis-video-archived-media (>=1.34.0,<1.35.0)", "mypy-boto3-kinesis-video-media (>=1.34.0,<1.35.0)", "mypy-boto3-kinesis-video-signaling (>=1.34.0,<1.35.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.34.0,<1.35.0)", "mypy-boto3-kinesisanalytics (>=1.34.0,<1.35.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.34.0,<1.35.0)", "mypy-boto3-kinesisvideo (>=1.34.0,<1.35.0)", "mypy-boto3-kms (>=1.34.0,<1.35.0)", "mypy-boto3-lakeformation (>=1.34.0,<1.35.0)", "mypy-boto3-lambda (>=1.34.0,<1.35.0)", "mypy-boto3-launch-wizard (>=1.34.0,<1.35.0)", "mypy-boto3-lex-models (>=1.34.0,<1.35.0)", "mypy-boto3-lex-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-lexv2-models (>=1.34.0,<1.35.0)", "mypy-boto3-lexv2-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-license-manager (>=1.34.0,<1.35.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.34.0,<1.35.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.34.0,<1.35.0)", "mypy-boto3-lightsail (>=1.34.0,<1.35.0)", "mypy-boto3-location (>=1.34.0,<1.35.0)", "mypy-boto3-logs (>=1.34.0,<1.35.0)", "mypy-boto3-lookoutequipment (>=1.34.0,<1.35.0)", "mypy-boto3-lookoutmetrics (>=1.34.0,<1.35.0)", "mypy-boto3-lookoutvision (>=1.34.0,<1.35.0)", "mypy-boto3-m2 (>=1.34.0,<1.35.0)", "mypy-boto3-machinelearning (>=1.34.0,<1.35.0)", "mypy-boto3-macie2 (>=1.34.0,<1.35.0)", "mypy-boto3-managedblockchain (>=1.34.0,<1.35.0)", "mypy-boto3-managedblockchain-query (>=1.34.0,<1.35.0)", "mypy-boto3-marketplace-agreement (>=1.34.0,<1.35.0)", "mypy-boto3-marketplace-catalog (>=1.34.0,<1.35.0)", "mypy-boto3-marketplace-deployment (>=1.34.0,<1.35.0)", "mypy-boto3-marketplace-entitlement (>=1.34.0,<1.35.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.34.0,<1.35.0)", "mypy-boto3-mediaconnect (>=1.34.0,<1.35.0)", "mypy-boto3-mediaconvert (>=1.34.0,<1.35.0)", "mypy-boto3-medialive (>=1.34.0,<1.35.0)", "mypy-boto3-mediapackage (>=1.34.0,<1.35.0)", "mypy-boto3-mediapackage-vod (>=1.34.0,<1.35.0)", "mypy-boto3-mediapackagev2 (>=1.34.0,<1.35.0)", "mypy-boto3-mediastore (>=1.34.0,<1.35.0)", "mypy-boto3-mediastore-data (>=1.34.0,<1.35.0)", "mypy-boto3-mediatailor (>=1.34.0,<1.35.0)", "mypy-boto3-medical-imaging (>=1.34.0,<1.35.0)", "mypy-boto3-memorydb (>=1.34.0,<1.35.0)", "mypy-boto3-meteringmarketplace (>=1.34.0,<1.35.0)", "mypy-boto3-mgh (>=1.34.0,<1.35.0)", "mypy-boto3-mgn (>=1.34.0,<1.35.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.34.0,<1.35.0)", "mypy-boto3-migrationhub-config (>=1.34.0,<1.35.0)", "mypy-boto3-migrationhuborchestrator (>=1.34.0,<1.35.0)", "mypy-boto3-migrationhubstrategy (>=1.34.0,<1.35.0)", "mypy-boto3-mobile (>=1.34.0,<1.35.0)", "mypy-boto3-mq (>=1.34.0,<1.35.0)", "mypy-boto3-mturk (>=1.34.0,<1.35.0)", "mypy-boto3-mwaa (>=1.34.0,<1.35.0)", "mypy-boto3-neptune (>=1.34.0,<1.35.0)", "mypy-boto3-neptune-graph (>=1.34.0,<1.35.0)", "mypy-boto3-neptunedata (>=1.34.0,<1.35.0)", "mypy-boto3-network-firewall (>=1.34.0,<1.35.0)", "mypy-boto3-networkmanager (>=1.34.0,<1.35.0)", "mypy-boto3-networkmonitor (>=1.34.0,<1.35.0)", "mypy-boto3-nimble (>=1.34.0,<1.35.0)", "mypy-boto3-oam (>=1.34.0,<1.35.0)", "mypy-boto3-omics (>=1.34.0,<1.35.0)", "mypy-boto3-opensearch (>=1.34.0,<1.35.0)", "mypy-boto3-opensearchserverless (>=1.34.0,<1.35.0)", "mypy-boto3-opsworks (>=1.34.0,<1.35.0)", "mypy-boto3-opsworkscm (>=1.34.0,<1.35.0)", "mypy-boto3-organizations (>=1.34.0,<1.35.0)", "mypy-boto3-osis (>=1.34.0,<1.35.0)", "mypy-boto3-outposts (>=1.34.0,<1.35.0)", "mypy-boto3-panorama (>=1.34.0,<1.35.0)", "mypy-boto3-payment-cryptography (>=1.34.0,<1.35.0)", "mypy-boto3-payment-cryptography-data (>=1.34.0,<1.35.0)", "mypy-boto3-pca-connector-ad (>=1.34.0,<1.35.0)", "mypy-boto3-personalize (>=1.34.0,<1.35.0)", "mypy-boto3-personalize-events (>=1.34.0,<1.35.0)", "mypy-boto3-personalize-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-pi (>=1.34.0,<1.35.0)", "mypy-boto3-pinpoint (>=1.34.0,<1.35.0)", "mypy-boto3-pinpoint-email (>=1.34.0,<1.35.0)", "mypy-boto3-pinpoint-sms-voice (>=1.34.0,<1.35.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.34.0,<1.35.0)", "mypy-boto3-pipes (>=1.34.0,<1.35.0)", "mypy-boto3-polly (>=1.34.0,<1.35.0)", "mypy-boto3-pricing (>=1.34.0,<1.35.0)", "mypy-boto3-privatenetworks (>=1.34.0,<1.35.0)", "mypy-boto3-proton (>=1.34.0,<1.35.0)", "mypy-boto3-qbusiness (>=1.34.0,<1.35.0)", "mypy-boto3-qconnect (>=1.34.0,<1.35.0)", "mypy-boto3-qldb (>=1.34.0,<1.35.0)", "mypy-boto3-qldb-session (>=1.34.0,<1.35.0)", "mypy-boto3-quicksight (>=1.34.0,<1.35.0)", "mypy-boto3-ram (>=1.34.0,<1.35.0)", "mypy-boto3-rbin (>=1.34.0,<1.35.0)", "mypy-boto3-rds (>=1.34.0,<1.35.0)", "mypy-boto3-rds-data (>=1.34.0,<1.35.0)", "mypy-boto3-redshift (>=1.34.0,<1.35.0)", "mypy-boto3-redshift-data (>=1.34.0,<1.35.0)", "mypy-boto3-redshift-serverless (>=1.34.0,<1.35.0)", "mypy-boto3-rekognition (>=1.34.0,<1.35.0)", "mypy-boto3-repostspace (>=1.34.0,<1.35.0)", "mypy-boto3-resiliencehub (>=1.34.0,<1.35.0)", "mypy-boto3-resource-explorer-2 (>=1.34.0,<1.35.0)", "mypy-boto3-resource-groups (>=1.34.0,<1.35.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.34.0,<1.35.0)", "mypy-boto3-robomaker (>=1.34.0,<1.35.0)", "mypy-boto3-rolesanywhere (>=1.34.0,<1.35.0)", "mypy-boto3-route53 (>=1.34.0,<1.35.0)", "mypy-boto3-route53-recovery-cluster (>=1.34.0,<1.35.0)", "mypy-boto3-route53-recovery-control-config (>=1.34.0,<1.35.0)", "mypy-boto3-route53-recovery-readiness (>=1.34.0,<1.35.0)", "mypy-boto3-route53domains (>=1.34.0,<1.35.0)", "mypy-boto3-route53resolver (>=1.34.0,<1.35.0)", "mypy-boto3-rum (>=1.34.0,<1.35.0)", "mypy-boto3-s3 (>=1.34.0,<1.35.0)", "mypy-boto3-s3control (>=1.34.0,<1.35.0)", "mypy-boto3-s3outposts (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-edge (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-geospatial (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-metrics (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-savingsplans (>=1.34.0,<1.35.0)", "mypy-boto3-scheduler (>=1.34.0,<1.35.0)", "mypy-boto3-schemas (>=1.34.0,<1.35.0)", "mypy-boto3-sdb (>=1.34.0,<1.35.0)", "mypy-boto3-secretsmanager (>=1.34.0,<1.35.0)", "mypy-boto3-securityhub (>=1.34.0,<1.35.0)", "mypy-boto3-securitylake (>=1.34.0,<1.35.0)", "mypy-boto3-serverlessrepo (>=1.34.0,<1.35.0)", "mypy-boto3-service-quotas (>=1.34.0,<1.35.0)", "mypy-boto3-servicecatalog (>=1.34.0,<1.35.0)", "mypy-boto3-servicecatalog-appregistry (>=1.34.0,<1.35.0)", "mypy-boto3-servicediscovery (>=1.34.0,<1.35.0)", "mypy-boto3-ses (>=1.34.0,<1.35.0)", "mypy-boto3-sesv2 (>=1.34.0,<1.35.0)", "mypy-boto3-shield (>=1.34.0,<1.35.0)", "mypy-boto3-signer (>=1.34.0,<1.35.0)", "mypy-boto3-simspaceweaver (>=1.34.0,<1.35.0)", "mypy-boto3-sms (>=1.34.0,<1.35.0)", "mypy-boto3-sms-voice (>=1.34.0,<1.35.0)", "mypy-boto3-snow-device-management (>=1.34.0,<1.35.0)", "mypy-boto3-snowball (>=1.34.0,<1.35.0)", "mypy-boto3-sns (>=1.34.0,<1.35.0)", "mypy-boto3-sqs (>=1.34.0,<1.35.0)", "mypy-boto3-ssm (>=1.34.0,<1.35.0)", "mypy-boto3-ssm-contacts (>=1.34.0,<1.35.0)", "mypy-boto3-ssm-incidents (>=1.34.0,<1.35.0)", "mypy-boto3-ssm-sap (>=1.34.0,<1.35.0)", "mypy-boto3-sso (>=1.34.0,<1.35.0)", "mypy-boto3-sso-admin (>=1.34.0,<1.35.0)", "mypy-boto3-sso-oidc (>=1.34.0,<1.35.0)", "mypy-boto3-stepfunctions (>=1.34.0,<1.35.0)", "mypy-boto3-storagegateway (>=1.34.0,<1.35.0)", "mypy-boto3-sts (>=1.34.0,<1.35.0)", "mypy-boto3-supplychain (>=1.34.0,<1.35.0)", "mypy-boto3-support (>=1.34.0,<1.35.0)", "mypy-boto3-support-app (>=1.34.0,<1.35.0)", "mypy-boto3-swf (>=1.34.0,<1.35.0)", "mypy-boto3-synthetics (>=1.34.0,<1.35.0)", "mypy-boto3-textract (>=1.34.0,<1.35.0)", "mypy-boto3-timestream-query (>=1.34.0,<1.35.0)", "mypy-boto3-timestream-write (>=1.34.0,<1.35.0)", "mypy-boto3-tnb (>=1.34.0,<1.35.0)", "mypy-boto3-transcribe (>=1.34.0,<1.35.0)", "mypy-boto3-transfer (>=1.34.0,<1.35.0)", "mypy-boto3-translate (>=1.34.0,<1.35.0)", "mypy-boto3-trustedadvisor (>=1.34.0,<1.35.0)", "mypy-boto3-verifiedpermissions (>=1.34.0,<1.35.0)", "mypy-boto3-voice-id (>=1.34.0,<1.35.0)", "mypy-boto3-vpc-lattice (>=1.34.0,<1.35.0)", "mypy-boto3-waf (>=1.34.0,<1.35.0)", "mypy-boto3-waf-regional (>=1.34.0,<1.35.0)", "mypy-boto3-wafv2 (>=1.34.0,<1.35.0)", "mypy-boto3-wellarchitected (>=1.34.0,<1.35.0)", "mypy-boto3-wisdom (>=1.34.0,<1.35.0)", "mypy-boto3-workdocs (>=1.34.0,<1.35.0)", "mypy-boto3-worklink (>=1.34.0,<1.35.0)", "mypy-boto3-workmail (>=1.34.0,<1.35.0)", "mypy-boto3-workmailmessageflow (>=1.34.0,<1.35.0)", "mypy-boto3-workspaces (>=1.34.0,<1.35.0)", "mypy-boto3-workspaces-thin-client (>=1.34.0,<1.35.0)", "mypy-boto3-workspaces-web (>=1.34.0,<1.35.0)", "mypy-boto3-xray (>=1.34.0,<1.35.0)"]
+amp = ["mypy-boto3-amp (>=1.34.0,<1.35.0)"]
+amplify = ["mypy-boto3-amplify (>=1.34.0,<1.35.0)"]
+amplifybackend = ["mypy-boto3-amplifybackend (>=1.34.0,<1.35.0)"]
+amplifyuibuilder = ["mypy-boto3-amplifyuibuilder (>=1.34.0,<1.35.0)"]
+apigateway = ["mypy-boto3-apigateway (>=1.34.0,<1.35.0)"]
+apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (>=1.34.0,<1.35.0)"]
+apigatewayv2 = ["mypy-boto3-apigatewayv2 (>=1.34.0,<1.35.0)"]
+appconfig = ["mypy-boto3-appconfig (>=1.34.0,<1.35.0)"]
+appconfigdata = ["mypy-boto3-appconfigdata (>=1.34.0,<1.35.0)"]
+appfabric = ["mypy-boto3-appfabric (>=1.34.0,<1.35.0)"]
+appflow = ["mypy-boto3-appflow (>=1.34.0,<1.35.0)"]
+appintegrations = ["mypy-boto3-appintegrations (>=1.34.0,<1.35.0)"]
+application-autoscaling = ["mypy-boto3-application-autoscaling (>=1.34.0,<1.35.0)"]
+application-insights = ["mypy-boto3-application-insights (>=1.34.0,<1.35.0)"]
+applicationcostprofiler = ["mypy-boto3-applicationcostprofiler (>=1.34.0,<1.35.0)"]
+appmesh = ["mypy-boto3-appmesh (>=1.34.0,<1.35.0)"]
+apprunner = ["mypy-boto3-apprunner (>=1.34.0,<1.35.0)"]
+appstream = ["mypy-boto3-appstream (>=1.34.0,<1.35.0)"]
+appsync = ["mypy-boto3-appsync (>=1.34.0,<1.35.0)"]
+arc-zonal-shift = ["mypy-boto3-arc-zonal-shift (>=1.34.0,<1.35.0)"]
+athena = ["mypy-boto3-athena (>=1.34.0,<1.35.0)"]
+auditmanager = ["mypy-boto3-auditmanager (>=1.34.0,<1.35.0)"]
+autoscaling = ["mypy-boto3-autoscaling (>=1.34.0,<1.35.0)"]
+autoscaling-plans = ["mypy-boto3-autoscaling-plans (>=1.34.0,<1.35.0)"]
+b2bi = ["mypy-boto3-b2bi (>=1.34.0,<1.35.0)"]
+backup = ["mypy-boto3-backup (>=1.34.0,<1.35.0)"]
+backup-gateway = ["mypy-boto3-backup-gateway (>=1.34.0,<1.35.0)"]
+backupstorage = ["mypy-boto3-backupstorage (>=1.34.0,<1.35.0)"]
+batch = ["mypy-boto3-batch (>=1.34.0,<1.35.0)"]
+bcm-data-exports = ["mypy-boto3-bcm-data-exports (>=1.34.0,<1.35.0)"]
+bedrock = ["mypy-boto3-bedrock (>=1.34.0,<1.35.0)"]
+bedrock-agent = ["mypy-boto3-bedrock-agent (>=1.34.0,<1.35.0)"]
+bedrock-agent-runtime = ["mypy-boto3-bedrock-agent-runtime (>=1.34.0,<1.35.0)"]
+bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.34.0,<1.35.0)"]
+billingconductor = ["mypy-boto3-billingconductor (>=1.34.0,<1.35.0)"]
+boto3 = ["boto3 (==1.34.20)", "botocore (==1.34.20)"]
+braket = ["mypy-boto3-braket (>=1.34.0,<1.35.0)"]
+budgets = ["mypy-boto3-budgets (>=1.34.0,<1.35.0)"]
+ce = ["mypy-boto3-ce (>=1.34.0,<1.35.0)"]
+chime = ["mypy-boto3-chime (>=1.34.0,<1.35.0)"]
+chime-sdk-identity = ["mypy-boto3-chime-sdk-identity (>=1.34.0,<1.35.0)"]
+chime-sdk-media-pipelines = ["mypy-boto3-chime-sdk-media-pipelines (>=1.34.0,<1.35.0)"]
+chime-sdk-meetings = ["mypy-boto3-chime-sdk-meetings (>=1.34.0,<1.35.0)"]
+chime-sdk-messaging = ["mypy-boto3-chime-sdk-messaging (>=1.34.0,<1.35.0)"]
+chime-sdk-voice = ["mypy-boto3-chime-sdk-voice (>=1.34.0,<1.35.0)"]
+cleanrooms = ["mypy-boto3-cleanrooms (>=1.34.0,<1.35.0)"]
+cleanroomsml = ["mypy-boto3-cleanroomsml (>=1.34.0,<1.35.0)"]
+cloud9 = ["mypy-boto3-cloud9 (>=1.34.0,<1.35.0)"]
+cloudcontrol = ["mypy-boto3-cloudcontrol (>=1.34.0,<1.35.0)"]
+clouddirectory = ["mypy-boto3-clouddirectory (>=1.34.0,<1.35.0)"]
+cloudformation = ["mypy-boto3-cloudformation (>=1.34.0,<1.35.0)"]
+cloudfront = ["mypy-boto3-cloudfront (>=1.34.0,<1.35.0)"]
+cloudfront-keyvaluestore = ["mypy-boto3-cloudfront-keyvaluestore (>=1.34.0,<1.35.0)"]
+cloudhsm = ["mypy-boto3-cloudhsm (>=1.34.0,<1.35.0)"]
+cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (>=1.34.0,<1.35.0)"]
+cloudsearch = ["mypy-boto3-cloudsearch (>=1.34.0,<1.35.0)"]
+cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (>=1.34.0,<1.35.0)"]
+cloudtrail = ["mypy-boto3-cloudtrail (>=1.34.0,<1.35.0)"]
+cloudtrail-data = ["mypy-boto3-cloudtrail-data (>=1.34.0,<1.35.0)"]
+cloudwatch = ["mypy-boto3-cloudwatch (>=1.34.0,<1.35.0)"]
+codeartifact = ["mypy-boto3-codeartifact (>=1.34.0,<1.35.0)"]
+codebuild = ["mypy-boto3-codebuild (>=1.34.0,<1.35.0)"]
+codecatalyst = ["mypy-boto3-codecatalyst (>=1.34.0,<1.35.0)"]
+codecommit = ["mypy-boto3-codecommit (>=1.34.0,<1.35.0)"]
+codedeploy = ["mypy-boto3-codedeploy (>=1.34.0,<1.35.0)"]
+codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (>=1.34.0,<1.35.0)"]
+codeguru-security = ["mypy-boto3-codeguru-security (>=1.34.0,<1.35.0)"]
+codeguruprofiler = ["mypy-boto3-codeguruprofiler (>=1.34.0,<1.35.0)"]
+codepipeline = ["mypy-boto3-codepipeline (>=1.34.0,<1.35.0)"]
+codestar = ["mypy-boto3-codestar (>=1.34.0,<1.35.0)"]
+codestar-connections = ["mypy-boto3-codestar-connections (>=1.34.0,<1.35.0)"]
+codestar-notifications = ["mypy-boto3-codestar-notifications (>=1.34.0,<1.35.0)"]
+cognito-identity = ["mypy-boto3-cognito-identity (>=1.34.0,<1.35.0)"]
+cognito-idp = ["mypy-boto3-cognito-idp (>=1.34.0,<1.35.0)"]
+cognito-sync = ["mypy-boto3-cognito-sync (>=1.34.0,<1.35.0)"]
+comprehend = ["mypy-boto3-comprehend (>=1.34.0,<1.35.0)"]
+comprehendmedical = ["mypy-boto3-comprehendmedical (>=1.34.0,<1.35.0)"]
+compute-optimizer = ["mypy-boto3-compute-optimizer (>=1.34.0,<1.35.0)"]
+config = ["mypy-boto3-config (>=1.34.0,<1.35.0)"]
+connect = ["mypy-boto3-connect (>=1.34.0,<1.35.0)"]
+connect-contact-lens = ["mypy-boto3-connect-contact-lens (>=1.34.0,<1.35.0)"]
+connectcampaigns = ["mypy-boto3-connectcampaigns (>=1.34.0,<1.35.0)"]
+connectcases = ["mypy-boto3-connectcases (>=1.34.0,<1.35.0)"]
+connectparticipant = ["mypy-boto3-connectparticipant (>=1.34.0,<1.35.0)"]
+controltower = ["mypy-boto3-controltower (>=1.34.0,<1.35.0)"]
+cost-optimization-hub = ["mypy-boto3-cost-optimization-hub (>=1.34.0,<1.35.0)"]
+cur = ["mypy-boto3-cur (>=1.34.0,<1.35.0)"]
+customer-profiles = ["mypy-boto3-customer-profiles (>=1.34.0,<1.35.0)"]
+databrew = ["mypy-boto3-databrew (>=1.34.0,<1.35.0)"]
+dataexchange = ["mypy-boto3-dataexchange (>=1.34.0,<1.35.0)"]
+datapipeline = ["mypy-boto3-datapipeline (>=1.34.0,<1.35.0)"]
+datasync = ["mypy-boto3-datasync (>=1.34.0,<1.35.0)"]
+datazone = ["mypy-boto3-datazone (>=1.34.0,<1.35.0)"]
+dax = ["mypy-boto3-dax (>=1.34.0,<1.35.0)"]
+detective = ["mypy-boto3-detective (>=1.34.0,<1.35.0)"]
+devicefarm = ["mypy-boto3-devicefarm (>=1.34.0,<1.35.0)"]
+devops-guru = ["mypy-boto3-devops-guru (>=1.34.0,<1.35.0)"]
+directconnect = ["mypy-boto3-directconnect (>=1.34.0,<1.35.0)"]
+discovery = ["mypy-boto3-discovery (>=1.34.0,<1.35.0)"]
+dlm = ["mypy-boto3-dlm (>=1.34.0,<1.35.0)"]
+dms = ["mypy-boto3-dms (>=1.34.0,<1.35.0)"]
+docdb = ["mypy-boto3-docdb (>=1.34.0,<1.35.0)"]
+docdb-elastic = ["mypy-boto3-docdb-elastic (>=1.34.0,<1.35.0)"]
+drs = ["mypy-boto3-drs (>=1.34.0,<1.35.0)"]
+ds = ["mypy-boto3-ds (>=1.34.0,<1.35.0)"]
+dynamodb = ["mypy-boto3-dynamodb (>=1.34.0,<1.35.0)"]
+dynamodbstreams = ["mypy-boto3-dynamodbstreams (>=1.34.0,<1.35.0)"]
+ebs = ["mypy-boto3-ebs (>=1.34.0,<1.35.0)"]
+ec2 = ["mypy-boto3-ec2 (>=1.34.0,<1.35.0)"]
+ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (>=1.34.0,<1.35.0)"]
+ecr = ["mypy-boto3-ecr (>=1.34.0,<1.35.0)"]
+ecr-public = ["mypy-boto3-ecr-public (>=1.34.0,<1.35.0)"]
+ecs = ["mypy-boto3-ecs (>=1.34.0,<1.35.0)"]
+efs = ["mypy-boto3-efs (>=1.34.0,<1.35.0)"]
+eks = ["mypy-boto3-eks (>=1.34.0,<1.35.0)"]
+eks-auth = ["mypy-boto3-eks-auth (>=1.34.0,<1.35.0)"]
+elastic-inference = ["mypy-boto3-elastic-inference (>=1.34.0,<1.35.0)"]
+elasticache = ["mypy-boto3-elasticache (>=1.34.0,<1.35.0)"]
+elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (>=1.34.0,<1.35.0)"]
+elastictranscoder = ["mypy-boto3-elastictranscoder (>=1.34.0,<1.35.0)"]
+elb = ["mypy-boto3-elb (>=1.34.0,<1.35.0)"]
+elbv2 = ["mypy-boto3-elbv2 (>=1.34.0,<1.35.0)"]
+emr = ["mypy-boto3-emr (>=1.34.0,<1.35.0)"]
+emr-containers = ["mypy-boto3-emr-containers (>=1.34.0,<1.35.0)"]
+emr-serverless = ["mypy-boto3-emr-serverless (>=1.34.0,<1.35.0)"]
+entityresolution = ["mypy-boto3-entityresolution (>=1.34.0,<1.35.0)"]
+es = ["mypy-boto3-es (>=1.34.0,<1.35.0)"]
+essential = ["mypy-boto3-cloudformation (>=1.34.0,<1.35.0)", "mypy-boto3-dynamodb (>=1.34.0,<1.35.0)", "mypy-boto3-ec2 (>=1.34.0,<1.35.0)", "mypy-boto3-lambda (>=1.34.0,<1.35.0)", "mypy-boto3-rds (>=1.34.0,<1.35.0)", "mypy-boto3-s3 (>=1.34.0,<1.35.0)", "mypy-boto3-sqs (>=1.34.0,<1.35.0)"]
+events = ["mypy-boto3-events (>=1.34.0,<1.35.0)"]
+evidently = ["mypy-boto3-evidently (>=1.34.0,<1.35.0)"]
+finspace = ["mypy-boto3-finspace (>=1.34.0,<1.35.0)"]
+finspace-data = ["mypy-boto3-finspace-data (>=1.34.0,<1.35.0)"]
+firehose = ["mypy-boto3-firehose (>=1.34.0,<1.35.0)"]
+fis = ["mypy-boto3-fis (>=1.34.0,<1.35.0)"]
+fms = ["mypy-boto3-fms (>=1.34.0,<1.35.0)"]
+forecast = ["mypy-boto3-forecast (>=1.34.0,<1.35.0)"]
+forecastquery = ["mypy-boto3-forecastquery (>=1.34.0,<1.35.0)"]
+frauddetector = ["mypy-boto3-frauddetector (>=1.34.0,<1.35.0)"]
+freetier = ["mypy-boto3-freetier (>=1.34.0,<1.35.0)"]
+fsx = ["mypy-boto3-fsx (>=1.34.0,<1.35.0)"]
+gamelift = ["mypy-boto3-gamelift (>=1.34.0,<1.35.0)"]
+glacier = ["mypy-boto3-glacier (>=1.34.0,<1.35.0)"]
+globalaccelerator = ["mypy-boto3-globalaccelerator (>=1.34.0,<1.35.0)"]
+glue = ["mypy-boto3-glue (>=1.34.0,<1.35.0)"]
+grafana = ["mypy-boto3-grafana (>=1.34.0,<1.35.0)"]
+greengrass = ["mypy-boto3-greengrass (>=1.34.0,<1.35.0)"]
+greengrassv2 = ["mypy-boto3-greengrassv2 (>=1.34.0,<1.35.0)"]
+groundstation = ["mypy-boto3-groundstation (>=1.34.0,<1.35.0)"]
+guardduty = ["mypy-boto3-guardduty (>=1.34.0,<1.35.0)"]
+health = ["mypy-boto3-health (>=1.34.0,<1.35.0)"]
+healthlake = ["mypy-boto3-healthlake (>=1.34.0,<1.35.0)"]
+honeycode = ["mypy-boto3-honeycode (>=1.34.0,<1.35.0)"]
+iam = ["mypy-boto3-iam (>=1.34.0,<1.35.0)"]
+identitystore = ["mypy-boto3-identitystore (>=1.34.0,<1.35.0)"]
+imagebuilder = ["mypy-boto3-imagebuilder (>=1.34.0,<1.35.0)"]
+importexport = ["mypy-boto3-importexport (>=1.34.0,<1.35.0)"]
+inspector = ["mypy-boto3-inspector (>=1.34.0,<1.35.0)"]
+inspector-scan = ["mypy-boto3-inspector-scan (>=1.34.0,<1.35.0)"]
+inspector2 = ["mypy-boto3-inspector2 (>=1.34.0,<1.35.0)"]
+internetmonitor = ["mypy-boto3-internetmonitor (>=1.34.0,<1.35.0)"]
+iot = ["mypy-boto3-iot (>=1.34.0,<1.35.0)"]
+iot-data = ["mypy-boto3-iot-data (>=1.34.0,<1.35.0)"]
+iot-jobs-data = ["mypy-boto3-iot-jobs-data (>=1.34.0,<1.35.0)"]
+iot-roborunner = ["mypy-boto3-iot-roborunner (>=1.34.0,<1.35.0)"]
+iot1click-devices = ["mypy-boto3-iot1click-devices (>=1.34.0,<1.35.0)"]
+iot1click-projects = ["mypy-boto3-iot1click-projects (>=1.34.0,<1.35.0)"]
+iotanalytics = ["mypy-boto3-iotanalytics (>=1.34.0,<1.35.0)"]
+iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (>=1.34.0,<1.35.0)"]
+iotevents = ["mypy-boto3-iotevents (>=1.34.0,<1.35.0)"]
+iotevents-data = ["mypy-boto3-iotevents-data (>=1.34.0,<1.35.0)"]
+iotfleethub = ["mypy-boto3-iotfleethub (>=1.34.0,<1.35.0)"]
+iotfleetwise = ["mypy-boto3-iotfleetwise (>=1.34.0,<1.35.0)"]
+iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (>=1.34.0,<1.35.0)"]
+iotsitewise = ["mypy-boto3-iotsitewise (>=1.34.0,<1.35.0)"]
+iotthingsgraph = ["mypy-boto3-iotthingsgraph (>=1.34.0,<1.35.0)"]
+iottwinmaker = ["mypy-boto3-iottwinmaker (>=1.34.0,<1.35.0)"]
+iotwireless = ["mypy-boto3-iotwireless (>=1.34.0,<1.35.0)"]
+ivs = ["mypy-boto3-ivs (>=1.34.0,<1.35.0)"]
+ivs-realtime = ["mypy-boto3-ivs-realtime (>=1.34.0,<1.35.0)"]
+ivschat = ["mypy-boto3-ivschat (>=1.34.0,<1.35.0)"]
+kafka = ["mypy-boto3-kafka (>=1.34.0,<1.35.0)"]
+kafkaconnect = ["mypy-boto3-kafkaconnect (>=1.34.0,<1.35.0)"]
+kendra = ["mypy-boto3-kendra (>=1.34.0,<1.35.0)"]
+kendra-ranking = ["mypy-boto3-kendra-ranking (>=1.34.0,<1.35.0)"]
+keyspaces = ["mypy-boto3-keyspaces (>=1.34.0,<1.35.0)"]
+kinesis = ["mypy-boto3-kinesis (>=1.34.0,<1.35.0)"]
+kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (>=1.34.0,<1.35.0)"]
+kinesis-video-media = ["mypy-boto3-kinesis-video-media (>=1.34.0,<1.35.0)"]
+kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (>=1.34.0,<1.35.0)"]
+kinesis-video-webrtc-storage = ["mypy-boto3-kinesis-video-webrtc-storage (>=1.34.0,<1.35.0)"]
+kinesisanalytics = ["mypy-boto3-kinesisanalytics (>=1.34.0,<1.35.0)"]
+kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (>=1.34.0,<1.35.0)"]
+kinesisvideo = ["mypy-boto3-kinesisvideo (>=1.34.0,<1.35.0)"]
+kms = ["mypy-boto3-kms (>=1.34.0,<1.35.0)"]
+lakeformation = ["mypy-boto3-lakeformation (>=1.34.0,<1.35.0)"]
+lambda = ["mypy-boto3-lambda (>=1.34.0,<1.35.0)"]
+launch-wizard = ["mypy-boto3-launch-wizard (>=1.34.0,<1.35.0)"]
+lex-models = ["mypy-boto3-lex-models (>=1.34.0,<1.35.0)"]
+lex-runtime = ["mypy-boto3-lex-runtime (>=1.34.0,<1.35.0)"]
+lexv2-models = ["mypy-boto3-lexv2-models (>=1.34.0,<1.35.0)"]
+lexv2-runtime = ["mypy-boto3-lexv2-runtime (>=1.34.0,<1.35.0)"]
+license-manager = ["mypy-boto3-license-manager (>=1.34.0,<1.35.0)"]
+license-manager-linux-subscriptions = ["mypy-boto3-license-manager-linux-subscriptions (>=1.34.0,<1.35.0)"]
+license-manager-user-subscriptions = ["mypy-boto3-license-manager-user-subscriptions (>=1.34.0,<1.35.0)"]
+lightsail = ["mypy-boto3-lightsail (>=1.34.0,<1.35.0)"]
+location = ["mypy-boto3-location (>=1.34.0,<1.35.0)"]
+logs = ["mypy-boto3-logs (>=1.34.0,<1.35.0)"]
+lookoutequipment = ["mypy-boto3-lookoutequipment (>=1.34.0,<1.35.0)"]
+lookoutmetrics = ["mypy-boto3-lookoutmetrics (>=1.34.0,<1.35.0)"]
+lookoutvision = ["mypy-boto3-lookoutvision (>=1.34.0,<1.35.0)"]
+m2 = ["mypy-boto3-m2 (>=1.34.0,<1.35.0)"]
+machinelearning = ["mypy-boto3-machinelearning (>=1.34.0,<1.35.0)"]
+macie2 = ["mypy-boto3-macie2 (>=1.34.0,<1.35.0)"]
+managedblockchain = ["mypy-boto3-managedblockchain (>=1.34.0,<1.35.0)"]
+managedblockchain-query = ["mypy-boto3-managedblockchain-query (>=1.34.0,<1.35.0)"]
+marketplace-agreement = ["mypy-boto3-marketplace-agreement (>=1.34.0,<1.35.0)"]
+marketplace-catalog = ["mypy-boto3-marketplace-catalog (>=1.34.0,<1.35.0)"]
+marketplace-deployment = ["mypy-boto3-marketplace-deployment (>=1.34.0,<1.35.0)"]
+marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (>=1.34.0,<1.35.0)"]
+marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (>=1.34.0,<1.35.0)"]
+mediaconnect = ["mypy-boto3-mediaconnect (>=1.34.0,<1.35.0)"]
+mediaconvert = ["mypy-boto3-mediaconvert (>=1.34.0,<1.35.0)"]
+medialive = ["mypy-boto3-medialive (>=1.34.0,<1.35.0)"]
+mediapackage = ["mypy-boto3-mediapackage (>=1.34.0,<1.35.0)"]
+mediapackage-vod = ["mypy-boto3-mediapackage-vod (>=1.34.0,<1.35.0)"]
+mediapackagev2 = ["mypy-boto3-mediapackagev2 (>=1.34.0,<1.35.0)"]
+mediastore = ["mypy-boto3-mediastore (>=1.34.0,<1.35.0)"]
+mediastore-data = ["mypy-boto3-mediastore-data (>=1.34.0,<1.35.0)"]
+mediatailor = ["mypy-boto3-mediatailor (>=1.34.0,<1.35.0)"]
+medical-imaging = ["mypy-boto3-medical-imaging (>=1.34.0,<1.35.0)"]
+memorydb = ["mypy-boto3-memorydb (>=1.34.0,<1.35.0)"]
+meteringmarketplace = ["mypy-boto3-meteringmarketplace (>=1.34.0,<1.35.0)"]
+mgh = ["mypy-boto3-mgh (>=1.34.0,<1.35.0)"]
+mgn = ["mypy-boto3-mgn (>=1.34.0,<1.35.0)"]
+migration-hub-refactor-spaces = ["mypy-boto3-migration-hub-refactor-spaces (>=1.34.0,<1.35.0)"]
+migrationhub-config = ["mypy-boto3-migrationhub-config (>=1.34.0,<1.35.0)"]
+migrationhuborchestrator = ["mypy-boto3-migrationhuborchestrator (>=1.34.0,<1.35.0)"]
+migrationhubstrategy = ["mypy-boto3-migrationhubstrategy (>=1.34.0,<1.35.0)"]
+mobile = ["mypy-boto3-mobile (>=1.34.0,<1.35.0)"]
+mq = ["mypy-boto3-mq (>=1.34.0,<1.35.0)"]
+mturk = ["mypy-boto3-mturk (>=1.34.0,<1.35.0)"]
+mwaa = ["mypy-boto3-mwaa (>=1.34.0,<1.35.0)"]
+neptune = ["mypy-boto3-neptune (>=1.34.0,<1.35.0)"]
+neptune-graph = ["mypy-boto3-neptune-graph (>=1.34.0,<1.35.0)"]
+neptunedata = ["mypy-boto3-neptunedata (>=1.34.0,<1.35.0)"]
+network-firewall = ["mypy-boto3-network-firewall (>=1.34.0,<1.35.0)"]
+networkmanager = ["mypy-boto3-networkmanager (>=1.34.0,<1.35.0)"]
+networkmonitor = ["mypy-boto3-networkmonitor (>=1.34.0,<1.35.0)"]
+nimble = ["mypy-boto3-nimble (>=1.34.0,<1.35.0)"]
+oam = ["mypy-boto3-oam (>=1.34.0,<1.35.0)"]
+omics = ["mypy-boto3-omics (>=1.34.0,<1.35.0)"]
+opensearch = ["mypy-boto3-opensearch (>=1.34.0,<1.35.0)"]
+opensearchserverless = ["mypy-boto3-opensearchserverless (>=1.34.0,<1.35.0)"]
+opsworks = ["mypy-boto3-opsworks (>=1.34.0,<1.35.0)"]
+opsworkscm = ["mypy-boto3-opsworkscm (>=1.34.0,<1.35.0)"]
+organizations = ["mypy-boto3-organizations (>=1.34.0,<1.35.0)"]
+osis = ["mypy-boto3-osis (>=1.34.0,<1.35.0)"]
+outposts = ["mypy-boto3-outposts (>=1.34.0,<1.35.0)"]
+panorama = ["mypy-boto3-panorama (>=1.34.0,<1.35.0)"]
+payment-cryptography = ["mypy-boto3-payment-cryptography (>=1.34.0,<1.35.0)"]
+payment-cryptography-data = ["mypy-boto3-payment-cryptography-data (>=1.34.0,<1.35.0)"]
+pca-connector-ad = ["mypy-boto3-pca-connector-ad (>=1.34.0,<1.35.0)"]
+personalize = ["mypy-boto3-personalize (>=1.34.0,<1.35.0)"]
+personalize-events = ["mypy-boto3-personalize-events (>=1.34.0,<1.35.0)"]
+personalize-runtime = ["mypy-boto3-personalize-runtime (>=1.34.0,<1.35.0)"]
+pi = ["mypy-boto3-pi (>=1.34.0,<1.35.0)"]
+pinpoint = ["mypy-boto3-pinpoint (>=1.34.0,<1.35.0)"]
+pinpoint-email = ["mypy-boto3-pinpoint-email (>=1.34.0,<1.35.0)"]
+pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (>=1.34.0,<1.35.0)"]
+pinpoint-sms-voice-v2 = ["mypy-boto3-pinpoint-sms-voice-v2 (>=1.34.0,<1.35.0)"]
+pipes = ["mypy-boto3-pipes (>=1.34.0,<1.35.0)"]
+polly = ["mypy-boto3-polly (>=1.34.0,<1.35.0)"]
+pricing = ["mypy-boto3-pricing (>=1.34.0,<1.35.0)"]
+privatenetworks = ["mypy-boto3-privatenetworks (>=1.34.0,<1.35.0)"]
+proton = ["mypy-boto3-proton (>=1.34.0,<1.35.0)"]
+qbusiness = ["mypy-boto3-qbusiness (>=1.34.0,<1.35.0)"]
+qconnect = ["mypy-boto3-qconnect (>=1.34.0,<1.35.0)"]
+qldb = ["mypy-boto3-qldb (>=1.34.0,<1.35.0)"]
+qldb-session = ["mypy-boto3-qldb-session (>=1.34.0,<1.35.0)"]
+quicksight = ["mypy-boto3-quicksight (>=1.34.0,<1.35.0)"]
+ram = ["mypy-boto3-ram (>=1.34.0,<1.35.0)"]
+rbin = ["mypy-boto3-rbin (>=1.34.0,<1.35.0)"]
+rds = ["mypy-boto3-rds (>=1.34.0,<1.35.0)"]
+rds-data = ["mypy-boto3-rds-data (>=1.34.0,<1.35.0)"]
+redshift = ["mypy-boto3-redshift (>=1.34.0,<1.35.0)"]
+redshift-data = ["mypy-boto3-redshift-data (>=1.34.0,<1.35.0)"]
+redshift-serverless = ["mypy-boto3-redshift-serverless (>=1.34.0,<1.35.0)"]
+rekognition = ["mypy-boto3-rekognition (>=1.34.0,<1.35.0)"]
+repostspace = ["mypy-boto3-repostspace (>=1.34.0,<1.35.0)"]
+resiliencehub = ["mypy-boto3-resiliencehub (>=1.34.0,<1.35.0)"]
+resource-explorer-2 = ["mypy-boto3-resource-explorer-2 (>=1.34.0,<1.35.0)"]
+resource-groups = ["mypy-boto3-resource-groups (>=1.34.0,<1.35.0)"]
+resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (>=1.34.0,<1.35.0)"]
+robomaker = ["mypy-boto3-robomaker (>=1.34.0,<1.35.0)"]
+rolesanywhere = ["mypy-boto3-rolesanywhere (>=1.34.0,<1.35.0)"]
+route53 = ["mypy-boto3-route53 (>=1.34.0,<1.35.0)"]
+route53-recovery-cluster = ["mypy-boto3-route53-recovery-cluster (>=1.34.0,<1.35.0)"]
+route53-recovery-control-config = ["mypy-boto3-route53-recovery-control-config (>=1.34.0,<1.35.0)"]
+route53-recovery-readiness = ["mypy-boto3-route53-recovery-readiness (>=1.34.0,<1.35.0)"]
+route53domains = ["mypy-boto3-route53domains (>=1.34.0,<1.35.0)"]
+route53resolver = ["mypy-boto3-route53resolver (>=1.34.0,<1.35.0)"]
+rum = ["mypy-boto3-rum (>=1.34.0,<1.35.0)"]
+s3 = ["mypy-boto3-s3 (>=1.34.0,<1.35.0)"]
+s3control = ["mypy-boto3-s3control (>=1.34.0,<1.35.0)"]
+s3outposts = ["mypy-boto3-s3outposts (>=1.34.0,<1.35.0)"]
+sagemaker = ["mypy-boto3-sagemaker (>=1.34.0,<1.35.0)"]
+sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (>=1.34.0,<1.35.0)"]
+sagemaker-edge = ["mypy-boto3-sagemaker-edge (>=1.34.0,<1.35.0)"]
+sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (>=1.34.0,<1.35.0)"]
+sagemaker-geospatial = ["mypy-boto3-sagemaker-geospatial (>=1.34.0,<1.35.0)"]
+sagemaker-metrics = ["mypy-boto3-sagemaker-metrics (>=1.34.0,<1.35.0)"]
+sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (>=1.34.0,<1.35.0)"]
+savingsplans = ["mypy-boto3-savingsplans (>=1.34.0,<1.35.0)"]
+scheduler = ["mypy-boto3-scheduler (>=1.34.0,<1.35.0)"]
+schemas = ["mypy-boto3-schemas (>=1.34.0,<1.35.0)"]
+sdb = ["mypy-boto3-sdb (>=1.34.0,<1.35.0)"]
+secretsmanager = ["mypy-boto3-secretsmanager (>=1.34.0,<1.35.0)"]
+securityhub = ["mypy-boto3-securityhub (>=1.34.0,<1.35.0)"]
+securitylake = ["mypy-boto3-securitylake (>=1.34.0,<1.35.0)"]
+serverlessrepo = ["mypy-boto3-serverlessrepo (>=1.34.0,<1.35.0)"]
+service-quotas = ["mypy-boto3-service-quotas (>=1.34.0,<1.35.0)"]
+servicecatalog = ["mypy-boto3-servicecatalog (>=1.34.0,<1.35.0)"]
+servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (>=1.34.0,<1.35.0)"]
+servicediscovery = ["mypy-boto3-servicediscovery (>=1.34.0,<1.35.0)"]
+ses = ["mypy-boto3-ses (>=1.34.0,<1.35.0)"]
+sesv2 = ["mypy-boto3-sesv2 (>=1.34.0,<1.35.0)"]
+shield = ["mypy-boto3-shield (>=1.34.0,<1.35.0)"]
+signer = ["mypy-boto3-signer (>=1.34.0,<1.35.0)"]
+simspaceweaver = ["mypy-boto3-simspaceweaver (>=1.34.0,<1.35.0)"]
+sms = ["mypy-boto3-sms (>=1.34.0,<1.35.0)"]
+sms-voice = ["mypy-boto3-sms-voice (>=1.34.0,<1.35.0)"]
+snow-device-management = ["mypy-boto3-snow-device-management (>=1.34.0,<1.35.0)"]
+snowball = ["mypy-boto3-snowball (>=1.34.0,<1.35.0)"]
+sns = ["mypy-boto3-sns (>=1.34.0,<1.35.0)"]
+sqs = ["mypy-boto3-sqs (>=1.34.0,<1.35.0)"]
+ssm = ["mypy-boto3-ssm (>=1.34.0,<1.35.0)"]
+ssm-contacts = ["mypy-boto3-ssm-contacts (>=1.34.0,<1.35.0)"]
+ssm-incidents = ["mypy-boto3-ssm-incidents (>=1.34.0,<1.35.0)"]
+ssm-sap = ["mypy-boto3-ssm-sap (>=1.34.0,<1.35.0)"]
+sso = ["mypy-boto3-sso (>=1.34.0,<1.35.0)"]
+sso-admin = ["mypy-boto3-sso-admin (>=1.34.0,<1.35.0)"]
+sso-oidc = ["mypy-boto3-sso-oidc (>=1.34.0,<1.35.0)"]
+stepfunctions = ["mypy-boto3-stepfunctions (>=1.34.0,<1.35.0)"]
+storagegateway = ["mypy-boto3-storagegateway (>=1.34.0,<1.35.0)"]
+sts = ["mypy-boto3-sts (>=1.34.0,<1.35.0)"]
+supplychain = ["mypy-boto3-supplychain (>=1.34.0,<1.35.0)"]
+support = ["mypy-boto3-support (>=1.34.0,<1.35.0)"]
+support-app = ["mypy-boto3-support-app (>=1.34.0,<1.35.0)"]
+swf = ["mypy-boto3-swf (>=1.34.0,<1.35.0)"]
+synthetics = ["mypy-boto3-synthetics (>=1.34.0,<1.35.0)"]
+textract = ["mypy-boto3-textract (>=1.34.0,<1.35.0)"]
+timestream-query = ["mypy-boto3-timestream-query (>=1.34.0,<1.35.0)"]
+timestream-write = ["mypy-boto3-timestream-write (>=1.34.0,<1.35.0)"]
+tnb = ["mypy-boto3-tnb (>=1.34.0,<1.35.0)"]
+transcribe = ["mypy-boto3-transcribe (>=1.34.0,<1.35.0)"]
+transfer = ["mypy-boto3-transfer (>=1.34.0,<1.35.0)"]
+translate = ["mypy-boto3-translate (>=1.34.0,<1.35.0)"]
+trustedadvisor = ["mypy-boto3-trustedadvisor (>=1.34.0,<1.35.0)"]
+verifiedpermissions = ["mypy-boto3-verifiedpermissions (>=1.34.0,<1.35.0)"]
+voice-id = ["mypy-boto3-voice-id (>=1.34.0,<1.35.0)"]
+vpc-lattice = ["mypy-boto3-vpc-lattice (>=1.34.0,<1.35.0)"]
+waf = ["mypy-boto3-waf (>=1.34.0,<1.35.0)"]
+waf-regional = ["mypy-boto3-waf-regional (>=1.34.0,<1.35.0)"]
+wafv2 = ["mypy-boto3-wafv2 (>=1.34.0,<1.35.0)"]
+wellarchitected = ["mypy-boto3-wellarchitected (>=1.34.0,<1.35.0)"]
+wisdom = ["mypy-boto3-wisdom (>=1.34.0,<1.35.0)"]
+workdocs = ["mypy-boto3-workdocs (>=1.34.0,<1.35.0)"]
+worklink = ["mypy-boto3-worklink (>=1.34.0,<1.35.0)"]
+workmail = ["mypy-boto3-workmail (>=1.34.0,<1.35.0)"]
+workmailmessageflow = ["mypy-boto3-workmailmessageflow (>=1.34.0,<1.35.0)"]
+workspaces = ["mypy-boto3-workspaces (>=1.34.0,<1.35.0)"]
+workspaces-thin-client = ["mypy-boto3-workspaces-thin-client (>=1.34.0,<1.35.0)"]
+workspaces-web = ["mypy-boto3-workspaces-web (>=1.34.0,<1.35.0)"]
+xray = ["mypy-boto3-xray (>=1.34.0,<1.35.0)"]
[[package]]
name = "botocore"
-version = "1.33.13"
+version = "1.34.20"
description = "Low-level, data-driven core of boto 3."
optional = false
-python-versions = ">= 3.7"
+python-versions = ">= 3.8"
files = [
- {file = "botocore-1.33.13-py3-none-any.whl", hash = "sha256:aeadccf4b7c674c7d47e713ef34671b834bc3e89723ef96d994409c9f54666e6"},
- {file = "botocore-1.33.13.tar.gz", hash = "sha256:fb577f4cb175605527458b04571451db1bd1a2036976b626206036acd4496617"},
+ {file = "botocore-1.34.20-py3-none-any.whl", hash = "sha256:f931f13d03e94b3350ad898b21ae2d40240f6571e8a8cdaa487951b51fe3a1fd"},
+ {file = "botocore-1.34.20.tar.gz", hash = "sha256:e944bc085222a13359933f4c0a1cce228bdd8aa90e1f2274e94bd55f561db307"},
]
[package.dependencies]
@@ -906,17 +943,17 @@ python-dateutil = ">=2.1,<3.0.0"
urllib3 = {version = ">=1.25.4,<2.1", markers = "python_version >= \"3.10\""}
[package.extras]
-crt = ["awscrt (==0.19.17)"]
+crt = ["awscrt (==0.19.19)"]
[[package]]
name = "botocore-stubs"
-version = "1.33.13"
+version = "1.34.20"
description = "Type annotations and code completion for botocore"
optional = false
-python-versions = ">=3.7,<4.0"
+python-versions = ">=3.8,<4.0"
files = [
- {file = "botocore_stubs-1.33.13-py3-none-any.whl", hash = "sha256:138dfc7bebf6c16d3754ce625bd761f607438e778bfb397824906e5ab36fa301"},
- {file = "botocore_stubs-1.33.13.tar.gz", hash = "sha256:b7b08a1beec9e6605fba12ffcd007b695bfc0a29f379a039f1ed69ec8eb1f7c7"},
+ {file = "botocore_stubs-1.34.20-py3-none-any.whl", hash = "sha256:45296ac7942578eb6baca49589115e9bfe3a803bfd3160fa42426381084f41cb"},
+ {file = "botocore_stubs-1.34.20.tar.gz", hash = "sha256:e85c2716858cbed5b935133fd681537b64bb991ad4fb43d55295edfffaf494e9"},
]
[package.dependencies]
@@ -939,6 +976,29 @@ files = [
beautifulsoup4 = "*"
[[package]]
+name = "build"
+version = "1.0.3"
+description = "A simple, correct Python build frontend"
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "build-1.0.3-py3-none-any.whl", hash = "sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f"},
+ {file = "build-1.0.3.tar.gz", hash = "sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "os_name == \"nt\""}
+packaging = ">=19.0"
+pyproject_hooks = "*"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"]
+test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"]
+typing = ["importlib-metadata (>=5.1)", "mypy (>=1.5.0,<1.6.0)", "tomli", "typing-extensions (>=3.7.4.3)"]
+virtualenv = ["virtualenv (>=20.0.35)"]
+
+[[package]]
name = "cachetools"
version = "5.3.2"
description = "Extensible memoizing collections and decorators"
@@ -1195,29 +1255,38 @@ numpy = "*"
[[package]]
name = "chromadb"
-version = "0.4.14"
+version = "0.4.22"
description = "Chroma."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "chromadb-0.4.14-py3-none-any.whl", hash = "sha256:c1b59bdfb4b35a40bad0b8927c5ed757adf191ff9db2b9a384dc46a76e1ff10f"},
- {file = "chromadb-0.4.14.tar.gz", hash = "sha256:0fcef603bcf9c854305020c3f8d368c09b1545d48bd2bceefd51861090f87dad"},
+ {file = "chromadb-0.4.22-py3-none-any.whl", hash = "sha256:ad210b27b4cda2f09d15adc9c83c81bfa66b69f39648a27b637306e40de0680d"},
+ {file = "chromadb-0.4.22.tar.gz", hash = "sha256:c793149e1c2bbbb52d77602c6c0594c5752f04cd9be12619250ddad2082af27a"},
]
[package.dependencies]
bcrypt = ">=4.0.1"
+build = ">=1.0.3"
chroma-hnswlib = "0.7.3"
fastapi = ">=0.95.2"
grpcio = ">=1.58.0"
importlib-resources = "*"
-numpy = {version = ">=1.22.5", markers = "python_version >= \"3.8\""}
+kubernetes = ">=28.1.0"
+mmh3 = ">=4.0.1"
+numpy = ">=1.22.5"
onnxruntime = ">=1.14.1"
+opentelemetry-api = ">=1.2.0"
+opentelemetry-exporter-otlp-proto-grpc = ">=1.2.0"
+opentelemetry-instrumentation-fastapi = ">=0.41b0"
+opentelemetry-sdk = ">=1.2.0"
overrides = ">=7.3.1"
posthog = ">=2.4.0"
pulsar-client = ">=3.1.0"
pydantic = ">=1.9"
pypika = ">=0.48.9"
+PyYAML = ">=6.0.0"
requests = ">=2.28"
+tenacity = ">=8.2.3"
tokenizers = ">=0.13.2"
tqdm = ">=4.65.0"
typer = ">=0.9.0"
@@ -1239,6 +1308,23 @@ files = [
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
+name = "click-default-group"
+version = "1.2.4"
+description = "click_default_group"
+optional = true
+python-versions = ">=2.7"
+files = [
+ {file = "click_default_group-1.2.4-py2.py3-none-any.whl", hash = "sha256:9b60486923720e7fc61731bdb32b617039aba820e22e1c88766b1125592eaa5f"},
+ {file = "click_default_group-1.2.4.tar.gz", hash = "sha256:eb3f3c99ec0d456ca6cd2a7f08f7d4e91771bef51b01bdd9580cc6450fe1251e"},
+]
+
+[package.dependencies]
+click = "*"
+
+[package.extras]
+test = ["pytest"]
+
+[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
@@ -1363,63 +1449,63 @@ test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"]
[[package]]
name = "coverage"
-version = "7.3.2"
+version = "7.4.0"
description = "Code coverage measurement for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"},
- {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"},
- {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"},
- {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"},
- {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"},
- {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"},
- {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"},
- {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"},
- {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"},
- {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"},
- {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"},
- {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"},
- {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"},
- {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"},
- {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"},
- {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"},
- {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"},
- {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"},
- {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"},
- {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"},
- {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"},
- {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"},
- {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"},
- {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"},
- {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"},
- {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"},
- {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"},
- {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"},
- {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"},
- {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"},
- {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"},
- {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"},
- {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"},
- {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"},
- {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"},
- {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"},
- {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"},
- {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"},
- {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"},
- {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"},
- {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"},
- {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"},
- {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"},
- {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"},
- {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"},
- {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"},
- {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"},
- {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"},
- {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"},
- {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"},
- {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"},
- {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"},
+ {file = "coverage-7.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36b0ea8ab20d6a7564e89cb6135920bc9188fb5f1f7152e94e8300b7b189441a"},
+ {file = "coverage-7.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0676cd0ba581e514b7f726495ea75aba3eb20899d824636c6f59b0ed2f88c471"},
+ {file = "coverage-7.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0ca5c71a5a1765a0f8f88022c52b6b8be740e512980362f7fdbb03725a0d6b9"},
+ {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7c97726520f784239f6c62506bc70e48d01ae71e9da128259d61ca5e9788516"},
+ {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:815ac2d0f3398a14286dc2cea223a6f338109f9ecf39a71160cd1628786bc6f5"},
+ {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:80b5ee39b7f0131ebec7968baa9b2309eddb35b8403d1869e08f024efd883566"},
+ {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5b2ccb7548a0b65974860a78c9ffe1173cfb5877460e5a229238d985565574ae"},
+ {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:995ea5c48c4ebfd898eacb098164b3cc826ba273b3049e4a889658548e321b43"},
+ {file = "coverage-7.4.0-cp310-cp310-win32.whl", hash = "sha256:79287fd95585ed36e83182794a57a46aeae0b64ca53929d1176db56aacc83451"},
+ {file = "coverage-7.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b14b4f8760006bfdb6e08667af7bc2d8d9bfdb648351915315ea17645347137"},
+ {file = "coverage-7.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04387a4a6ecb330c1878907ce0dc04078ea72a869263e53c72a1ba5bbdf380ca"},
+ {file = "coverage-7.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea81d8f9691bb53f4fb4db603203029643caffc82bf998ab5b59ca05560f4c06"},
+ {file = "coverage-7.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74775198b702868ec2d058cb92720a3c5a9177296f75bd97317c787daf711505"},
+ {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76f03940f9973bfaee8cfba70ac991825611b9aac047e5c80d499a44079ec0bc"},
+ {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:485e9f897cf4856a65a57c7f6ea3dc0d4e6c076c87311d4bc003f82cfe199d25"},
+ {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6ae8c9d301207e6856865867d762a4b6fd379c714fcc0607a84b92ee63feff70"},
+ {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bf477c355274a72435ceb140dc42de0dc1e1e0bf6e97195be30487d8eaaf1a09"},
+ {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:83c2dda2666fe32332f8e87481eed056c8b4d163fe18ecc690b02802d36a4d26"},
+ {file = "coverage-7.4.0-cp311-cp311-win32.whl", hash = "sha256:697d1317e5290a313ef0d369650cfee1a114abb6021fa239ca12b4849ebbd614"},
+ {file = "coverage-7.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:26776ff6c711d9d835557ee453082025d871e30b3fd6c27fcef14733f67f0590"},
+ {file = "coverage-7.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:13eaf476ec3e883fe3e5fe3707caeb88268a06284484a3daf8250259ef1ba143"},
+ {file = "coverage-7.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846f52f46e212affb5bcf131c952fb4075b55aae6b61adc9856222df89cbe3e2"},
+ {file = "coverage-7.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26f66da8695719ccf90e794ed567a1549bb2644a706b41e9f6eae6816b398c4a"},
+ {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:164fdcc3246c69a6526a59b744b62e303039a81e42cfbbdc171c91a8cc2f9446"},
+ {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:316543f71025a6565677d84bc4df2114e9b6a615aa39fb165d697dba06a54af9"},
+ {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bb1de682da0b824411e00a0d4da5a784ec6496b6850fdf8c865c1d68c0e318dd"},
+ {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0e8d06778e8fbffccfe96331a3946237f87b1e1d359d7fbe8b06b96c95a5407a"},
+ {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a56de34db7b7ff77056a37aedded01b2b98b508227d2d0979d373a9b5d353daa"},
+ {file = "coverage-7.4.0-cp312-cp312-win32.whl", hash = "sha256:51456e6fa099a8d9d91497202d9563a320513fcf59f33991b0661a4a6f2ad450"},
+ {file = "coverage-7.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:cd3c1e4cb2ff0083758f09be0f77402e1bdf704adb7f89108007300a6da587d0"},
+ {file = "coverage-7.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e9d1bf53c4c8de58d22e0e956a79a5b37f754ed1ffdbf1a260d9dcfa2d8a325e"},
+ {file = "coverage-7.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:109f5985182b6b81fe33323ab4707011875198c41964f014579cf82cebf2bb85"},
+ {file = "coverage-7.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cc9d4bc55de8003663ec94c2f215d12d42ceea128da8f0f4036235a119c88ac"},
+ {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc6d65b21c219ec2072c1293c505cf36e4e913a3f936d80028993dd73c7906b1"},
+ {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a10a4920def78bbfff4eff8a05c51be03e42f1c3735be42d851f199144897ba"},
+ {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b8e99f06160602bc64da35158bb76c73522a4010f0649be44a4e167ff8555952"},
+ {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7d360587e64d006402b7116623cebf9d48893329ef035278969fa3bbf75b697e"},
+ {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:29f3abe810930311c0b5d1a7140f6395369c3db1be68345638c33eec07535105"},
+ {file = "coverage-7.4.0-cp38-cp38-win32.whl", hash = "sha256:5040148f4ec43644702e7b16ca864c5314ccb8ee0751ef617d49aa0e2d6bf4f2"},
+ {file = "coverage-7.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:9864463c1c2f9cb3b5db2cf1ff475eed2f0b4285c2aaf4d357b69959941aa555"},
+ {file = "coverage-7.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:936d38794044b26c99d3dd004d8af0035ac535b92090f7f2bb5aa9c8e2f5cd42"},
+ {file = "coverage-7.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:799c8f873794a08cdf216aa5d0531c6a3747793b70c53f70e98259720a6fe2d7"},
+ {file = "coverage-7.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7defbb9737274023e2d7af02cac77043c86ce88a907c58f42b580a97d5bcca9"},
+ {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1526d265743fb49363974b7aa8d5899ff64ee07df47dd8d3e37dcc0818f09ed"},
+ {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf635a52fc1ea401baf88843ae8708591aa4adff875e5c23220de43b1ccf575c"},
+ {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:756ded44f47f330666843b5781be126ab57bb57c22adbb07d83f6b519783b870"},
+ {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0eb3c2f32dabe3a4aaf6441dde94f35687224dfd7eb2a7f47f3fd9428e421058"},
+ {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bfd5db349d15c08311702611f3dccbef4b4e2ec148fcc636cf8739519b4a5c0f"},
+ {file = "coverage-7.4.0-cp39-cp39-win32.whl", hash = "sha256:53d7d9158ee03956e0eadac38dfa1ec8068431ef8058fe6447043db1fb40d932"},
+ {file = "coverage-7.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfd2a8b6b0d8e66e944d47cdec2f47c48fef2ba2f2dff5a9a75757f64172857e"},
+ {file = "coverage-7.4.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:c530833afc4707fe48524a44844493f36d8727f04dcce91fb978c414a8556cc6"},
+ {file = "coverage-7.4.0.tar.gz", hash = "sha256:707c0f58cb1712b8809ece32b68996ee1e609f71bd14615bd8f87a1293cb610e"},
]
[package.dependencies]
@@ -1441,26 +1527,28 @@ files = [
[[package]]
name = "curl-cffi"
-version = "0.5.10"
+version = "0.6.2"
description = "libcurl ffi bindings for Python, with impersonation support"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "curl_cffi-0.5.10-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:892603dab5e56fb72bfff7ae969136138971f63f63defe98232e1ec55cb0f1c6"},
- {file = "curl_cffi-0.5.10-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:9937b8e13b1a6963c63e155b6621ec74649965105efedb919bc226fe731861cc"},
- {file = "curl_cffi-0.5.10-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b537595b9610a4dd0927c09823925b4e32b1ce0fd04385bfc5bb72ab830720e6"},
- {file = "curl_cffi-0.5.10-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b2bc8822d23415f6533c8b750475e9bbc76764025fe1dcb5866dc033607fd7b"},
- {file = "curl_cffi-0.5.10-cp37-abi3-win_amd64.whl", hash = "sha256:f9a1874b860c4e8db49bdfd9b9d4dc39999a1397d271ec78624c35c838e9e92a"},
- {file = "curl_cffi-0.5.10.tar.gz", hash = "sha256:55bac4b73e2d80ceeaabea33270fc8ca6ace594128a46710242f2e688b4f8bfc"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:23b8a2872b160718c04b06b1f8aa4fb1a2f4f94bce7040493515e081a27cad19"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ad3c1cf5360810825ec4bc3da425f26ee4098878a615dab9d309a99afd883ba9"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d01de6ed737ad1924aaa0198195b9020c38e77ce90ea3d72b9eacf4938c7adf"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37e513cc149d024a2d625e202f2cc9d4423d2937343ea2e06f797d99779e62dc"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-win32.whl", hash = "sha256:12e829af97cbf7c1d5afef177e786f6f404ddf163b08897a1ed087cadbeb4837"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-win_amd64.whl", hash = "sha256:3791b7a9ae4cb1298165300f2dc2d60a86779f055570ae83163fc2d8a74bf714"},
+ {file = "curl_cffi-0.6.2.tar.gz", hash = "sha256:9ee519e960b5fc6e0bbf13d0ecba9ce5f6306cb929354504bf03cc30f59a8f63"},
]
[package.dependencies]
+certifi = "*"
cffi = ">=1.12.0"
[package.extras]
build = ["cibuildwheel", "wheel"]
-dev = ["autoflake (==1.4)", "black (==22.8.0)", "coverage (==6.4.1)", "cryptography (==38.0.3)", "flake8 (==6.0.0)", "flake8-bugbear (==22.7.1)", "flake8-pie (==0.15.0)", "httpx (==0.23.1)", "isort (==5.10.1)", "mypy (==0.971)", "pytest (==7.1.2)", "pytest-asyncio (==0.19.0)", "pytest-trio (==0.7.0)", "trio (==0.21.0)", "trio-typing (==0.7.0)", "trustme (==0.9.0)", "types-certifi (==2021.10.8.2)", "uvicorn (==0.18.3)"]
-test = ["cryptography (==38.0.3)", "httpx (==0.23.1)", "pytest (==7.1.2)", "pytest-asyncio (==0.19.0)", "pytest-trio (==0.7.0)", "trio (==0.21.0)", "trio-typing (==0.7.0)", "trustme (==0.9.0)", "types-certifi (==2021.10.8.2)", "uvicorn (==0.18.3)"]
+dev = ["autoflake (==1.4)", "coverage (==6.4.1)", "cryptography (==38.0.3)", "flake8 (==6.0.0)", "flake8-bugbear (==22.7.1)", "flake8-pie (==0.15.0)", "httpx (==0.23.1)", "mypy (==0.971)", "nest-asyncio (==1.6.0)", "pytest (==7.1.2)", "pytest-asyncio (==0.19.0)", "pytest-trio (==0.7.0)", "ruff (==0.1.14)", "trio (==0.21.0)", "trio-typing (==0.7.0)", "trustme (==0.9.0)", "types-certifi (==2021.10.8.2)", "uvicorn (==0.18.3)", "websockets (==11.0.3)"]
+test = ["cryptography (==38.0.3)", "fastapi (==0.100.0)", "httpx (==0.23.1)", "nest-asyncio (==1.6.0)", "proxy.py (==2.4.3)", "pytest (==7.1.2)", "pytest-asyncio (==0.19.0)", "pytest-trio (==0.7.0)", "python-multipart (==0.0.6)", "trio (==0.21.0)", "trio-typing (==0.7.0)", "trustme (==0.9.0)", "types-certifi (==2021.10.8.2)", "uvicorn (==0.18.3)", "websockets (==11.0.3)"]
[[package]]
name = "cycler"
@@ -1531,6 +1619,33 @@ files = [
]
[[package]]
+name = "demjson3"
+version = "3.0.6"
+description = "encoder, decoder, and lint/validator for JSON (JavaScript Object Notation) compliant with RFC 7159"
+optional = false
+python-versions = "*"
+files = [
+ {file = "demjson3-3.0.6.tar.gz", hash = "sha256:37c83b0c6eb08d25defc88df0a2a4875d58a7809a9650bd6eee7afd8053cdbac"},
+]
+
+[[package]]
+name = "deprecated"
+version = "1.2.14"
+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.*"
+files = [
+ {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"},
+ {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"},
+]
+
+[package.dependencies]
+wrapt = ">=1.10,<2"
+
+[package.extras]
+dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"]
+
+[[package]]
name = "distlib"
version = "0.3.8"
description = "Distribution utilities"
@@ -1543,13 +1658,13 @@ files = [
[[package]]
name = "distro"
-version = "1.8.0"
+version = "1.9.0"
description = "Distro - an OS platform information API"
optional = false
python-versions = ">=3.6"
files = [
- {file = "distro-1.8.0-py3-none-any.whl", hash = "sha256:99522ca3e365cac527b44bde033f64c6945d90eb9f769703caaec52b09bbd3ff"},
- {file = "distro-1.8.0.tar.gz", hash = "sha256:02e111d1dc6a50abb8eed6bf31c3e48ed8b0830d1ea2a1b78c61765c2513fdd8"},
+ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"},
+ {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"},
]
[[package]]
@@ -1594,22 +1709,22 @@ websockets = ["websocket-client (>=1.3.0)"]
[[package]]
name = "duckduckgo-search"
-version = "4.1.0"
+version = "5.1.0"
description = "Search for words, documents, images, news, maps and text translation using the DuckDuckGo.com search engine."
optional = false
python-versions = ">=3.8"
files = [
- {file = "duckduckgo_search-4.1.0-py3-none-any.whl", hash = "sha256:fb0d2edcb4adf946c6d65a3a9b51e65778edafd344d982dfb27c54e5c05a09b5"},
- {file = "duckduckgo_search-4.1.0.tar.gz", hash = "sha256:0b213d515538f3f53c1baac29c9d84a44cf5487b670550a2548718d7be0253ea"},
+ {file = "duckduckgo_search-5.1.0-py3-none-any.whl", hash = "sha256:691a3e1c948ab9c4409af7891557bdfff66b9f0c521336b008bbc91675ba5353"},
+ {file = "duckduckgo_search-5.1.0.tar.gz", hash = "sha256:27522d05f1e3dc5c2fbe95bd12cc32ff96a790cf8ee993b2949158dee0dbfb1f"},
]
[package.dependencies]
click = ">=8.1.7"
-curl-cffi = ">=0.5.10"
-lxml = ">=4.9.3"
+curl-cffi = ">=0.6.2"
+lxml = ">=5.1.0"
[package.extras]
-dev = ["pytest (>=7.4.2)", "pytest-asyncio (>=0.21.1)", "ruff (>=0.1.6)"]
+dev = ["mypy (>=1.8.0)", "pytest (>=8.0.1)", "ruff (>=0.3.0)"]
[[package]]
name = "en-core-web-sm"
@@ -1672,22 +1787,22 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth
[[package]]
name = "fastapi"
-version = "0.99.1"
+version = "0.109.2"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "fastapi-0.99.1-py3-none-any.whl", hash = "sha256:976df7bab51ac7beda9f68c4513b8c4490b5c1135c72aafd0a5ee4023ec5282e"},
- {file = "fastapi-0.99.1.tar.gz", hash = "sha256:ac78f717cd80d657bd183f94d33b9bda84aa376a46a9dab513586b8eef1dc6fc"},
+ {file = "fastapi-0.109.2-py3-none-any.whl", hash = "sha256:2c9bab24667293b501cad8dd388c05240c850b58ec5876ee3283c47d6e1e3a4d"},
+ {file = "fastapi-0.109.2.tar.gz", hash = "sha256:f3817eac96fe4f65a2ebb4baa000f394e55f5fccdaf7f75250804bc58f354f73"},
]
[package.dependencies]
-pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0"
-starlette = ">=0.27.0,<0.28.0"
-typing-extensions = ">=4.5.0"
+pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
+starlette = ">=0.36.3,<0.37.0"
+typing-extensions = ">=4.8.0"
[package.extras]
-all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
+all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
[[package]]
name = "filelock"
@@ -1707,19 +1822,19 @@ typing = ["typing-extensions (>=4.8)"]
[[package]]
name = "flake8"
-version = "6.1.0"
+version = "7.0.0"
description = "the modular source code checker: pep8 pyflakes and co"
optional = false
python-versions = ">=3.8.1"
files = [
- {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"},
- {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"},
+ {file = "flake8-7.0.0-py2.py3-none-any.whl", hash = "sha256:a6dfbb75e03252917f2473ea9653f7cd799c3064e54d4c8140044c5c065f53c3"},
+ {file = "flake8-7.0.0.tar.gz", hash = "sha256:33f96621059e65eec474169085dc92bf26e7b2d47366b70be2f67ab80dc25132"},
]
[package.dependencies]
mccabe = ">=0.7.0,<0.8.0"
pycodestyle = ">=2.11.0,<2.12.0"
-pyflakes = ">=3.1.0,<3.2.0"
+pyflakes = ">=3.2.0,<3.3.0"
[[package]]
name = "flatbuffers"
@@ -1734,59 +1849,59 @@ files = [
[[package]]
name = "fonttools"
-version = "4.46.0"
+version = "4.47.2"
description = "Tools to manipulate font files"
optional = true
python-versions = ">=3.8"
files = [
- {file = "fonttools-4.46.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d4e69e2c7f93b695d2e6f18f709d501d945f65c1d237dafaabdd23cd935a5276"},
- {file = "fonttools-4.46.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:25852f0c63df0af022f698464a4a80f7d1d5bd974bcd22f995f6b4ad198e32dd"},
- {file = "fonttools-4.46.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:adab73618d0a328b203a0e242b3eba60a2b5662d9cb2bd16ed9c52af8a7d86af"},
- {file = "fonttools-4.46.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf923a4a556ab4cc4c52f69a4a2db624cf5a2cf360394368b40c5152fe3321e"},
- {file = "fonttools-4.46.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:87c214197712cc14fd2a4621efce2a9c501a77041232b789568149a8a3161517"},
- {file = "fonttools-4.46.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:156ae342a1ed1fe38e180de471e98fbf5b2b6ae280fa3323138569c4ca215844"},
- {file = "fonttools-4.46.0-cp310-cp310-win32.whl", hash = "sha256:c506e3d3a9e898caee4dc094f34b49c5566870d5a2d1ca2125f0a9f35ecc2205"},
- {file = "fonttools-4.46.0-cp310-cp310-win_amd64.whl", hash = "sha256:f8bc3973ed58893c4107993e0a7ae34901cb572b5e798249cbef35d30801ffd4"},
- {file = "fonttools-4.46.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:982f69855ac258260f51048d9e0c53c5f19881138cc7ca06deb38dc4b97404b6"},
- {file = "fonttools-4.46.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c23c59d321d62588620f2255cf951270bf637d88070f38ed8b5e5558775b86c"},
- {file = "fonttools-4.46.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0e94244ec24a940ecfbe5b31c975c8a575d5ed2d80f9a280ce3b21fa5dc9c34"},
- {file = "fonttools-4.46.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a9f9cdd7ef63d1b8ac90db335762451452426b3207abd79f60da510cea62da5"},
- {file = "fonttools-4.46.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ca9eceebe70035b057ce549e2054cad73e95cac3fe91a9d827253d1c14618204"},
- {file = "fonttools-4.46.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8be6adfa4e15977075278dd0a0bae74dec59be7b969b5ceed93fb86af52aa5be"},
- {file = "fonttools-4.46.0-cp311-cp311-win32.whl", hash = "sha256:7b5636f5706d49f13b6d610fe54ee662336cdf56b5a6f6683c0b803e23d826d2"},
- {file = "fonttools-4.46.0-cp311-cp311-win_amd64.whl", hash = "sha256:49ea0983e55fd7586a809787cd4644a7ae471e53ab8ddc016f9093b400e32646"},
- {file = "fonttools-4.46.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7b460720ce81773da1a3e7cc964c48e1e11942b280619582a897fa0117b56a62"},
- {file = "fonttools-4.46.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8bee9f4fc8c99824a424ae45c789ee8c67cb84f8e747afa7f83b7d3cef439c3b"},
- {file = "fonttools-4.46.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3d7b96aba96e05e8c911ce2dfc5acc6a178b8f44f6aa69371ab91aa587563da"},
- {file = "fonttools-4.46.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e6aeb5c340416d11a3209d75c48d13e72deea9e1517837dd1522c1fd1f17c11"},
- {file = "fonttools-4.46.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c779f8701deedf41908f287aeb775b8a6f59875ad1002b98ac6034ae4ddc1b7b"},
- {file = "fonttools-4.46.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce199227ce7921eaafdd4f96536f16b232d6b580ce74ce337de544bf06cb2752"},
- {file = "fonttools-4.46.0-cp312-cp312-win32.whl", hash = "sha256:1c9937c4dd1061afd22643389445fabda858af5e805860ec3082a4bc07c7a720"},
- {file = "fonttools-4.46.0-cp312-cp312-win_amd64.whl", hash = "sha256:a9fa52ef8fd14d7eb3d813e1451e7ace3e1eebfa9b7237d3f81fee8f3de6a114"},
- {file = "fonttools-4.46.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c94564b1f3b5dd87e73577610d85115b1936edcc596deaf84a31bbe70e17456b"},
- {file = "fonttools-4.46.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4a50a1dfad7f7ba5ca3f99cc73bf5cdac67ceade8e4b355a877521f20ad1b63"},
- {file = "fonttools-4.46.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89c2c520f9492844ecd6316d20c6c7a157b5c0cb73a1411b3db28ee304f30122"},
- {file = "fonttools-4.46.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5b7905fd68eacb7cc56a13139da5c312c45baae6950dd00b02563c54508a041"},
- {file = "fonttools-4.46.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8485cc468288e213f31afdaf1fdda3c79010f542559fbba936a54f4644df2570"},
- {file = "fonttools-4.46.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:87c3299da7da55394fb324349db0ede38114a46aafd0e7dfcabfecd28cdd94c3"},
- {file = "fonttools-4.46.0-cp38-cp38-win32.whl", hash = "sha256:f5f1423a504ccc329efb5aa79738de83d38c072be5308788dde6bd419969d7f5"},
- {file = "fonttools-4.46.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d4a4ebcc76e30898ff3296ea786491c70e183f738319ae2629e0d44f17ece42"},
- {file = "fonttools-4.46.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9a0e422ab79e5cb2b47913be6a4b5fd20c4c7ac34a24f3691a4e099e965e0b8"},
- {file = "fonttools-4.46.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:13ac0cba2fc63fa4b232f2a7971f35f35c6eaf10bd1271fa96d4ce6253a8acfd"},
- {file = "fonttools-4.46.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:795150d5edc595e1a2cfb3d65e8f4f3d027704fc2579f8990d381bef6b188eb6"},
- {file = "fonttools-4.46.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d00fc63131dcac6b25f50a5a129758438317e54e3ce5587163f7058de4b0e933"},
- {file = "fonttools-4.46.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3033b55f401a622de2630b3982234d97219d89b058607b87927eccb0f922313c"},
- {file = "fonttools-4.46.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e26e7fb908ae4f622813e7cb32cd2db6c24e3122bb3b98f25e832a2fe0e7e228"},
- {file = "fonttools-4.46.0-cp39-cp39-win32.whl", hash = "sha256:2d0eba685938c603f2f648dfc0aadbf8c6a4fe1c7ca608c2970a6ef39e00f254"},
- {file = "fonttools-4.46.0-cp39-cp39-win_amd64.whl", hash = "sha256:5200b01f463d97cc2b7ff8a1e3584151f4413e98cb8419da5f17d1dbb84cc214"},
- {file = "fonttools-4.46.0-py3-none-any.whl", hash = "sha256:5b627ed142398ea9202bd752c04311592558964d1a765fb2f78dc441a05633f4"},
- {file = "fonttools-4.46.0.tar.gz", hash = "sha256:2ae45716c27a41807d58a9f3f59983bdc8c0a46cb259e4450ab7e196253a9853"},
+ {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3b629108351d25512d4ea1a8393a2dba325b7b7d7308116b605ea3f8e1be88df"},
+ {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c19044256c44fe299d9a73456aabee4b4d06c6b930287be93b533b4737d70aa1"},
+ {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8be28c036b9f186e8c7eaf8a11b42373e7e4949f9e9f370202b9da4c4c3f56c"},
+ {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f83a4daef6d2a202acb9bf572958f91cfde5b10c8ee7fb1d09a4c81e5d851fd8"},
+ {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5a5318ba5365d992666ac4fe35365f93004109d18858a3e18ae46f67907670"},
+ {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8f57ecd742545362a0f7186774b2d1c53423ed9ece67689c93a1055b236f638c"},
+ {file = "fonttools-4.47.2-cp310-cp310-win32.whl", hash = "sha256:a1c154bb85dc9a4cf145250c88d112d88eb414bad81d4cb524d06258dea1bdc0"},
+ {file = "fonttools-4.47.2-cp310-cp310-win_amd64.whl", hash = "sha256:3e2b95dce2ead58fb12524d0ca7d63a63459dd489e7e5838c3cd53557f8933e1"},
+ {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:29495d6d109cdbabe73cfb6f419ce67080c3ef9ea1e08d5750240fd4b0c4763b"},
+ {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0a1d313a415eaaba2b35d6cd33536560deeebd2ed758b9bfb89ab5d97dc5deac"},
+ {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f898cdd67f52f18049250a6474185ef6544c91f27a7bee70d87d77a8daf89c"},
+ {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3480eeb52770ff75140fe7d9a2ec33fb67b07efea0ab5129c7e0c6a639c40c70"},
+ {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0255dbc128fee75fb9be364806b940ed450dd6838672a150d501ee86523ac61e"},
+ {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f791446ff297fd5f1e2247c188de53c1bfb9dd7f0549eba55b73a3c2087a2703"},
+ {file = "fonttools-4.47.2-cp311-cp311-win32.whl", hash = "sha256:740947906590a878a4bde7dd748e85fefa4d470a268b964748403b3ab2aeed6c"},
+ {file = "fonttools-4.47.2-cp311-cp311-win_amd64.whl", hash = "sha256:63fbed184979f09a65aa9c88b395ca539c94287ba3a364517698462e13e457c9"},
+ {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4ec558c543609e71b2275c4894e93493f65d2f41c15fe1d089080c1d0bb4d635"},
+ {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e040f905d542362e07e72e03612a6270c33d38281fd573160e1003e43718d68d"},
+ {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dd58cc03016b281bd2c74c84cdaa6bd3ce54c5a7f47478b7657b930ac3ed8eb"},
+ {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32ab2e9702dff0dd4510c7bb958f265a8d3dd5c0e2547e7b5f7a3df4979abb07"},
+ {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a808f3c1d1df1f5bf39be869b6e0c263570cdafb5bdb2df66087733f566ea71"},
+ {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac71e2e201df041a2891067dc36256755b1229ae167edbdc419b16da78732c2f"},
+ {file = "fonttools-4.47.2-cp312-cp312-win32.whl", hash = "sha256:69731e8bea0578b3c28fdb43dbf95b9386e2d49a399e9a4ad736b8e479b08085"},
+ {file = "fonttools-4.47.2-cp312-cp312-win_amd64.whl", hash = "sha256:b3e1304e5f19ca861d86a72218ecce68f391646d85c851742d265787f55457a4"},
+ {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:254d9a6f7be00212bf0c3159e0a420eb19c63793b2c05e049eb337f3023c5ecc"},
+ {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eabae77a07c41ae0b35184894202305c3ad211a93b2eb53837c2a1143c8bc952"},
+ {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86a5ab2873ed2575d0fcdf1828143cfc6b977ac448e3dc616bb1e3d20efbafa"},
+ {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13819db8445a0cec8c3ff5f243af6418ab19175072a9a92f6cc8ca7d1452754b"},
+ {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4e743935139aa485fe3253fc33fe467eab6ea42583fa681223ea3f1a93dd01e6"},
+ {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d49ce3ea7b7173faebc5664872243b40cf88814ca3eb135c4a3cdff66af71946"},
+ {file = "fonttools-4.47.2-cp38-cp38-win32.whl", hash = "sha256:94208ea750e3f96e267f394d5588579bb64cc628e321dbb1d4243ffbc291b18b"},
+ {file = "fonttools-4.47.2-cp38-cp38-win_amd64.whl", hash = "sha256:0f750037e02beb8b3569fbff701a572e62a685d2a0e840d75816592280e5feae"},
+ {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3d71606c9321f6701642bd4746f99b6089e53d7e9817fc6b964e90d9c5f0ecc6"},
+ {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86e0427864c6c91cf77f16d1fb9bf1bbf7453e824589e8fb8461b6ee1144f506"},
+ {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a00bd0e68e88987dcc047ea31c26d40a3c61185153b03457956a87e39d43c37"},
+ {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5d77479fb885ef38a16a253a2f4096bc3d14e63a56d6246bfdb56365a12b20c"},
+ {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5465df494f20a7d01712b072ae3ee9ad2887004701b95cb2cc6dcb9c2c97a899"},
+ {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4c811d3c73b6abac275babb8aa439206288f56fdb2c6f8835e3d7b70de8937a7"},
+ {file = "fonttools-4.47.2-cp39-cp39-win32.whl", hash = "sha256:5b60e3afa9635e3dfd3ace2757039593e3bd3cf128be0ddb7a1ff4ac45fa5a50"},
+ {file = "fonttools-4.47.2-cp39-cp39-win_amd64.whl", hash = "sha256:7ee48bd9d6b7e8f66866c9090807e3a4a56cf43ffad48962725a190e0dd774c8"},
+ {file = "fonttools-4.47.2-py3-none-any.whl", hash = "sha256:7eb7ad665258fba68fd22228a09f347469d95a97fb88198e133595947a20a184"},
+ {file = "fonttools-4.47.2.tar.gz", hash = "sha256:7df26dd3650e98ca45f1e29883c96a0b9f5bb6af8d632a6a108bc744fa0bd9b3"},
]
[package.extras]
-all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"]
+all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"]
graphite = ["lz4 (>=1.7.4.2)"]
-interpolatable = ["munkres", "scipy"]
+interpolatable = ["munkres", "pycairo", "scipy"]
lxml = ["lxml (>=4.0,<5)"]
pathops = ["skia-pathops (>=0.5.0)"]
plot = ["matplotlib"]
@@ -1799,72 +1914,88 @@ woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"]
[[package]]
name = "frozenlist"
-version = "1.4.0"
+version = "1.4.1"
description = "A list-like structure which implements collections.abc.MutableSequence"
optional = false
python-versions = ">=3.8"
files = [
- {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"},
- {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"},
- {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"},
- {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"},
- {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"},
- {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"},
- {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"},
- {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"},
- {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"},
- {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"},
- {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"},
- {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"},
- {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"},
- {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"},
- {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"},
- {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"},
- {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"},
- {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"},
- {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"},
- {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"},
- {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"},
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"},
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"},
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"},
+ {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"},
+ {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"},
+ {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"},
+ {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"},
+ {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"},
+ {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"},
+ {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"},
+ {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"},
+ {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"},
+ {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"},
+ {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"},
+ {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"},
]
[[package]]
@@ -1932,20 +2063,20 @@ smmap = ">=3.0.1,<6"
[[package]]
name = "gitpython"
-version = "3.1.40"
+version = "3.1.41"
description = "GitPython is a Python library used to interact with Git repositories"
optional = false
python-versions = ">=3.7"
files = [
- {file = "GitPython-3.1.40-py3-none-any.whl", hash = "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a"},
- {file = "GitPython-3.1.40.tar.gz", hash = "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4"},
+ {file = "GitPython-3.1.41-py3-none-any.whl", hash = "sha256:c36b6634d069b3f719610175020a9aed919421c87552185b085e04fbbdb10b7c"},
+ {file = "GitPython-3.1.41.tar.gz", hash = "sha256:ed66e624884f76df22c8e16066d567aaa5a37d5b5fa19db2c6df6f7156db9048"},
]
[package.dependencies]
gitdb = ">=4.0.1,<5"
[package.extras]
-test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-instafail", "pytest-subtests", "pytest-sugar"]
+test = ["black", "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", "sumtypes"]
[[package]]
name = "google-api-core"
@@ -1979,13 +2110,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"]
[[package]]
name = "google-api-python-client"
-version = "2.111.0"
+version = "2.114.0"
description = "Google API Client Library for Python"
optional = false
python-versions = ">=3.7"
files = [
- {file = "google-api-python-client-2.111.0.tar.gz", hash = "sha256:3a45a53c031478d1c82c7162dd25c9a965247bca6bd438af0838a9d9b8219405"},
- {file = "google_api_python_client-2.111.0-py2.py3-none-any.whl", hash = "sha256:b605adee2d09a843b97a59925757802904679e44e5599708cedb8939900dfbc7"},
+ {file = "google-api-python-client-2.114.0.tar.gz", hash = "sha256:e041bbbf60e682261281e9d64b4660035f04db1cccba19d1d68eebc24d1465ed"},
+ {file = "google_api_python_client-2.114.0-py2.py3-none-any.whl", hash = "sha256:690e0bb67d70ff6dea4e8a5d3738639c105a478ac35da153d3b2a384064e9e1a"},
]
[package.dependencies]
@@ -1997,13 +2128,13 @@ uritemplate = ">=3.0.1,<5"
[[package]]
name = "google-auth"
-version = "2.25.2"
+version = "2.26.2"
description = "Google Authentication Library"
optional = false
python-versions = ">=3.7"
files = [
- {file = "google-auth-2.25.2.tar.gz", hash = "sha256:42f707937feb4f5e5a39e6c4f343a17300a459aaf03141457ba505812841cc40"},
- {file = "google_auth-2.25.2-py2.py3-none-any.whl", hash = "sha256:473a8dfd0135f75bb79d878436e568f2695dce456764bf3a02b6f8c540b1d256"},
+ {file = "google-auth-2.26.2.tar.gz", hash = "sha256:97327dbbf58cccb58fc5a1712bba403ae76668e64814eb30f7316f7e27126b81"},
+ {file = "google_auth-2.26.2-py2.py3-none-any.whl", hash = "sha256:3f445c8ce9b61ed6459aad86d8ccdba4a9afed841b2d1451a11ef4db08957424"},
]
[package.dependencies]
@@ -2245,73 +2376,73 @@ grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"]
[[package]]
name = "greenlet"
-version = "3.0.2"
+version = "3.0.3"
description = "Lightweight in-process concurrent programming"
optional = false
python-versions = ">=3.7"
files = [
- {file = "greenlet-3.0.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9acd8fd67c248b8537953cb3af8787c18a87c33d4dcf6830e410ee1f95a63fd4"},
- {file = "greenlet-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:339c0272a62fac7e602e4e6ec32a64ff9abadc638b72f17f6713556ed011d493"},
- {file = "greenlet-3.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38878744926cec29b5cc3654ef47f3003f14bfbba7230e3c8492393fe29cc28b"},
- {file = "greenlet-3.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b3f0497db77cfd034f829678b28267eeeeaf2fc21b3f5041600f7617139e6773"},
- {file = "greenlet-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed1a8a08de7f68506a38f9a2ddb26bbd1480689e66d788fcd4b5f77e2d9ecfcc"},
- {file = "greenlet-3.0.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89a6f6ddcbef4000cda7e205c4c20d319488ff03db961d72d4e73519d2465309"},
- {file = "greenlet-3.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c1f647fe5b94b51488b314c82fdda10a8756d650cee8d3cd29f657c6031bdf73"},
- {file = "greenlet-3.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9560c580c896030ff9c311c603aaf2282234643c90d1dec738a1d93e3e53cd51"},
- {file = "greenlet-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2e9c5423046eec21f6651268cb674dfba97280701e04ef23d312776377313206"},
- {file = "greenlet-3.0.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1fd25dfc5879a82103b3d9e43fa952e3026c221996ff4d32a9c72052544835d"},
- {file = "greenlet-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cecfdc950dd25f25d6582952e58521bca749cf3eeb7a9bad69237024308c8196"},
- {file = "greenlet-3.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edf7a1daba1f7c54326291a8cde58da86ab115b78c91d502be8744f0aa8e3ffa"},
- {file = "greenlet-3.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4cf532bf3c58a862196b06947b1b5cc55503884f9b63bf18582a75228d9950e"},
- {file = "greenlet-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e79fb5a9fb2d0bd3b6573784f5e5adabc0b0566ad3180a028af99523ce8f6138"},
- {file = "greenlet-3.0.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:006c1028ac0cfcc4e772980cfe73f5476041c8c91d15d64f52482fc571149d46"},
- {file = "greenlet-3.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fefd5eb2c0b1adffdf2802ff7df45bfe65988b15f6b972706a0e55d451bffaea"},
- {file = "greenlet-3.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0c0fdb8142742ee68e97c106eb81e7d3e883cc739d9c5f2b28bc38a7bafeb6d1"},
- {file = "greenlet-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:8f8d14a0a4e8c670fbce633d8b9a1ee175673a695475acd838e372966845f764"},
- {file = "greenlet-3.0.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:654b84c9527182036747938b81938f1d03fb8321377510bc1854a9370418ab66"},
- {file = "greenlet-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bc4fde0842ff2b9cf33382ad0b4db91c2582db836793d58d174c569637144"},
- {file = "greenlet-3.0.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c27b142a9080bdd5869a2fa7ebf407b3c0b24bd812db925de90e9afe3c417fd6"},
- {file = "greenlet-3.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0df7eed98ea23b20e9db64d46eb05671ba33147df9405330695bcd81a73bb0c9"},
- {file = "greenlet-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb5d60805057d8948065338be6320d35e26b0a72f45db392eb32b70dd6dc9227"},
- {file = "greenlet-3.0.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e0e28f5233d64c693382f66d47c362b72089ebf8ac77df7e12ac705c9fa1163d"},
- {file = "greenlet-3.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e4bfa752b3688d74ab1186e2159779ff4867644d2b1ebf16db14281f0445377"},
- {file = "greenlet-3.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c42bb589e6e9f9d8bdd79f02f044dff020d30c1afa6e84c0b56d1ce8a324553c"},
- {file = "greenlet-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:b2cedf279ca38ef3f4ed0d013a6a84a7fc3d9495a716b84a5fc5ff448965f251"},
- {file = "greenlet-3.0.2-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:6d65bec56a7bc352bcf11b275b838df618651109074d455a772d3afe25390b7d"},
- {file = "greenlet-3.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0acadbc3f72cb0ee85070e8d36bd2a4673d2abd10731ee73c10222cf2dd4713c"},
- {file = "greenlet-3.0.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14b5d999aefe9ffd2049ad19079f733c3aaa426190ffecadb1d5feacef8fe397"},
- {file = "greenlet-3.0.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f27aa32466993c92d326df982c4acccd9530fe354e938d9e9deada563e71ce76"},
- {file = "greenlet-3.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f34a765c5170c0673eb747213a0275ecc749ab3652bdbec324621ed5b2edaef"},
- {file = "greenlet-3.0.2-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:520fcb53a39ef90f5021c77606952dbbc1da75d77114d69b8d7bded4a8e1a813"},
- {file = "greenlet-3.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d1fceb5351ab1601903e714c3028b37f6ea722be6873f46e349a960156c05650"},
- {file = "greenlet-3.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7363756cc439a503505b67983237d1cc19139b66488263eb19f5719a32597836"},
- {file = "greenlet-3.0.2-cp37-cp37m-win32.whl", hash = "sha256:d5547b462b8099b84746461e882a3eb8a6e3f80be46cb6afb8524eeb191d1a30"},
- {file = "greenlet-3.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:950e21562818f9c771989b5b65f990e76f4ac27af66e1bb34634ae67886ede2a"},
- {file = "greenlet-3.0.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d64643317e76b4b41fdba659e7eca29634e5739b8bc394eda3a9127f697ed4b0"},
- {file = "greenlet-3.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f9ea7c2c9795549653b6f7569f6bc75d2c7d1f6b2854eb8ce0bc6ec3cb2dd88"},
- {file = "greenlet-3.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db4233358d3438369051a2f290f1311a360d25c49f255a6c5d10b5bcb3aa2b49"},
- {file = "greenlet-3.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed9bf77b41798e8417657245b9f3649314218a4a17aefb02bb3992862df32495"},
- {file = "greenlet-3.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d0df07a38e41a10dfb62c6fc75ede196572b580f48ee49b9282c65639f3965"},
- {file = "greenlet-3.0.2-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10d247260db20887ae8857c0cbc750b9170f0b067dd7d38fb68a3f2334393bd3"},
- {file = "greenlet-3.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a37ae53cca36823597fd5f65341b6f7bac2dd69ecd6ca01334bb795460ab150b"},
- {file = "greenlet-3.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:80d068e4b6e2499847d916ef64176811ead6bf210a610859220d537d935ec6fd"},
- {file = "greenlet-3.0.2-cp38-cp38-win32.whl", hash = "sha256:b1405614692ac986490d10d3e1a05e9734f473750d4bee3cf7d1286ef7af7da6"},
- {file = "greenlet-3.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:8756a94ed8f293450b0e91119eca2a36332deba69feb2f9ca410d35e74eae1e4"},
- {file = "greenlet-3.0.2-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:2c93cd03acb1499ee4de675e1a4ed8eaaa7227f7949dc55b37182047b006a7aa"},
- {file = "greenlet-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1dac09e3c0b78265d2e6d3cbac2d7c48bd1aa4b04a8ffeda3adde9f1688df2c3"},
- {file = "greenlet-3.0.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ee59c4627c8c4bb3e15949fbcd499abd6b7f4ad9e0bfcb62c65c5e2cabe0ec4"},
- {file = "greenlet-3.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18fe39d70d482b22f0014e84947c5aaa7211fb8e13dc4cc1c43ed2aa1db06d9a"},
- {file = "greenlet-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84bef3cfb6b6bfe258c98c519811c240dbc5b33a523a14933a252e486797c90"},
- {file = "greenlet-3.0.2-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aecea0442975741e7d69daff9b13c83caff8c13eeb17485afa65f6360a045765"},
- {file = "greenlet-3.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f260e6c2337871a52161824058923df2bbddb38bc11a5cbe71f3474d877c5bd9"},
- {file = "greenlet-3.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fc14dd9554f88c9c1fe04771589ae24db76cd56c8f1104e4381b383d6b71aff8"},
- {file = "greenlet-3.0.2-cp39-cp39-win32.whl", hash = "sha256:bfcecc984d60b20ffe30173b03bfe9ba6cb671b0be1e95c3e2056d4fe7006590"},
- {file = "greenlet-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:c235131bf59d2546bb3ebaa8d436126267392f2e51b85ff45ac60f3a26549af0"},
- {file = "greenlet-3.0.2.tar.gz", hash = "sha256:1c1129bc47266d83444c85a8e990ae22688cf05fb20d7951fd2866007c2ba9bc"},
+ {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"},
+ {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"},
+ {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"},
+ {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"},
+ {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"},
+ {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"},
+ {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"},
+ {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"},
+ {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"},
+ {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"},
+ {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"},
+ {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"},
+ {file = "greenlet-3.0.3-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41"},
+ {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7"},
+ {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6"},
+ {file = "greenlet-3.0.3-cp37-cp37m-win32.whl", hash = "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d"},
+ {file = "greenlet-3.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67"},
+ {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"},
+ {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"},
+ {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"},
+ {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"},
+ {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"},
+ {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"},
+ {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"},
+ {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"},
+ {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"},
+ {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"},
+ {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"},
]
[package.extras]
-docs = ["Sphinx"]
+docs = ["Sphinx", "furo"]
test = ["objgraph", "psutil"]
[[package]]
@@ -2414,13 +2545,13 @@ protobuf = ">=4.21.6"
[[package]]
name = "gtts"
-version = "2.4.0"
+version = "2.5.0"
description = "gTTS (Google Text-to-Speech), a Python library and CLI tool to interface with Google Translate text-to-speech API"
optional = false
python-versions = ">=3.7"
files = [
- {file = "gTTS-2.4.0-py3-none-any.whl", hash = "sha256:08719f4f75c9d09921fa4fd994a372fd4020e2798234a153523da01a4fa53244"},
- {file = "gTTS-2.4.0.tar.gz", hash = "sha256:dabc62a57e81befe21c37476e084a72d5dc8f0d90be380b3236ad681d815cd4e"},
+ {file = "gTTS-2.5.0-py3-none-any.whl", hash = "sha256:181eca837c8c9ae280160573d76e8a340c1c54055c966ad11b4f4bf1b8e3194a"},
+ {file = "gTTS-2.5.0.tar.gz", hash = "sha256:d6d589b1759948490fbabd7a11d1799eeafdde8ba90580194918a18dc078ec49"},
]
[package.dependencies]
@@ -2458,22 +2589,6 @@ hpack = ">=4.0,<5"
hyperframe = ">=6.0,<7"
[[package]]
-name = "helicone"
-version = "1.0.14"
-description = "A Python wrapper for the OpenAI API that logs all requests to Helicone."
-optional = true
-python-versions = ">=3.8.1"
-files = [
- {file = "helicone-1.0.14-py3-none-any.whl", hash = "sha256:1828eb546e2f1aa780391ff640a1c62d55de030d3712c26db8d53f288333349a"},
- {file = "helicone-1.0.14.tar.gz", hash = "sha256:d8061b1ff7ed45257cd24f42e7f6e24d330130a30fe0444253d3cad4bb9d23d5"},
-]
-
-[package.dependencies]
-lockfile = ">=0.12.2,<0.13.0"
-openai = ">=0.27.0,<0.28.0"
-pyhumps = ">=3.8.0,<4.0.0"
-
-[[package]]
name = "hpack"
version = "4.0.0"
description = "Pure-Python HPACK header compression"
@@ -2592,13 +2707,13 @@ socks = ["socksio (==1.*)"]
[[package]]
name = "huggingface-hub"
-version = "0.19.4"
+version = "0.20.2"
description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub"
optional = false
python-versions = ">=3.8.0"
files = [
- {file = "huggingface_hub-0.19.4-py3-none-any.whl", hash = "sha256:dba013f779da16f14b606492828f3760600a1e1801432d09fe1c33e50b825bb5"},
- {file = "huggingface_hub-0.19.4.tar.gz", hash = "sha256:176a4fc355a851c17550e7619488f383189727eab209534d7cef2114dae77b22"},
+ {file = "huggingface_hub-0.20.2-py3-none-any.whl", hash = "sha256:53752eda2239d30a470c307a61cf9adcf136bc77b0a734338c7d04941af560d8"},
+ {file = "huggingface_hub-0.20.2.tar.gz", hash = "sha256:215c5fceff631030c7a3d19ba7b588921c908b3f21eef31d160ebc245b200ff6"},
]
[package.dependencies]
@@ -2611,15 +2726,14 @@ tqdm = ">=4.42.1"
typing-extensions = ">=3.7.4.3"
[package.extras]
-all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
+all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
cli = ["InquirerPy (==0.3.4)"]
-dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
-docs = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "hf-doc-builder", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)", "watchdog"]
+dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"]
inference = ["aiohttp", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)"]
quality = ["mypy (==1.5.1)", "ruff (>=0.1.3)"]
tensorflow = ["graphviz", "pydot", "tensorflow"]
-testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"]
+testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"]
torch = ["torch"]
typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"]
@@ -2699,13 +2813,13 @@ files = [
[[package]]
name = "importlib-metadata"
-version = "7.0.0"
+version = "6.11.0"
description = "Read metadata from Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"},
- {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"},
+ {file = "importlib_metadata-6.11.0-py3-none-any.whl", hash = "sha256:f0afba6205ad8f8947c7d338b5342d5db2afbfd82f9cbef7879a9539cc12eb9b"},
+ {file = "importlib_metadata-6.11.0.tar.gz", hash = "sha256:1231cf92d825c9e03cfc4da076a16de6422c863558229ea0b22b675657463443"},
]
[package.dependencies]
@@ -2755,13 +2869,13 @@ files = [
[[package]]
name = "ipython"
-version = "8.18.1"
+version = "8.20.0"
description = "IPython: Productive Interactive Computing"
optional = true
-python-versions = ">=3.9"
+python-versions = ">=3.10"
files = [
- {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"},
- {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"},
+ {file = "ipython-8.20.0-py3-none-any.whl", hash = "sha256:bc9716aad6f29f36c449e30821c9dd0c1c1a7b59ddcc26931685b87b4c569619"},
+ {file = "ipython-8.20.0.tar.gz", hash = "sha256:2f21bd3fc1d51550c89ee3944ae04bbc7bc79e129ea0937da6e6c68bfdbf117a"},
]
[package.dependencies]
@@ -2777,29 +2891,32 @@ stack-data = "*"
traitlets = ">=5"
[package.extras]
-all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
+all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.23)", "pandas", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
black = ["black"]
-doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"]
+doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"]
kernel = ["ipykernel"]
nbconvert = ["nbconvert"]
nbformat = ["nbformat"]
notebook = ["ipywidgets", "notebook"]
parallel = ["ipyparallel"]
qtconsole = ["qtconsole"]
-test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"]
-test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"]
+test = ["pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"]
+test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath", "trio"]
[[package]]
name = "isort"
-version = "5.13.1"
+version = "5.13.2"
description = "A Python utility / library to sort Python imports."
optional = false
python-versions = ">=3.8.0"
files = [
- {file = "isort-5.13.1-py3-none-any.whl", hash = "sha256:56a51732c25f94ca96f6721be206dd96a95f42950502eb26c1015d333bc6edb7"},
- {file = "isort-5.13.1.tar.gz", hash = "sha256:aaed790b463e8703fb1eddb831dfa8e8616bacde2c083bd557ef73c8189b7263"},
+ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"},
+ {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"},
]
+[package.extras]
+colors = ["colorama (>=0.4.6)"]
+
[[package]]
name = "jedi"
version = "0.19.1"
@@ -2821,13 +2938,13 @@ testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
[[package]]
name = "jinja2"
-version = "3.1.2"
+version = "3.1.3"
description = "A very fast and expressive template engine."
optional = false
python-versions = ">=3.7"
files = [
- {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
- {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+ {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"},
+ {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"},
]
[package.dependencies]
@@ -2865,13 +2982,13 @@ testing-libs = ["simplejson", "ujson"]
[[package]]
name = "jsonschema"
-version = "4.20.0"
+version = "4.21.0"
description = "An implementation of JSON Schema validation for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "jsonschema-4.20.0-py3-none-any.whl", hash = "sha256:ed6231f0429ecf966f5bc8dfef245998220549cbbcf140f913b7464c52c3b6b3"},
- {file = "jsonschema-4.20.0.tar.gz", hash = "sha256:4f614fd46d8d61258610998997743ec5492a648b33cf478c1ddc23ed4598a5fa"},
+ {file = "jsonschema-4.21.0-py3-none-any.whl", hash = "sha256:70a09719d375c0a2874571b363c8a24be7df8071b80c9aa76bc4551e7297c63c"},
+ {file = "jsonschema-4.21.0.tar.gz", hash = "sha256:3ba18e27f7491ea4a1b22edce00fb820eec968d397feb3f9cb61d5894bb38167"},
]
[package.dependencies]
@@ -2886,13 +3003,13 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-
[[package]]
name = "jsonschema-specifications"
-version = "2023.11.2"
+version = "2023.12.1"
description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry"
optional = false
python-versions = ">=3.8"
files = [
- {file = "jsonschema_specifications-2023.11.2-py3-none-any.whl", hash = "sha256:e74ba7c0a65e8cb49dc26837d6cfe576557084a8b423ed16a420984228104f93"},
- {file = "jsonschema_specifications-2023.11.2.tar.gz", hash = "sha256:9472fc4fea474cd74bea4a2b190daeccb5a9e4db2ea80efcf7a1b582fc9a81b8"},
+ {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"},
+ {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"},
]
[package.dependencies]
@@ -3012,6 +3129,32 @@ files = [
]
[[package]]
+name = "kubernetes"
+version = "29.0.0"
+description = "Kubernetes python client"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "kubernetes-29.0.0-py2.py3-none-any.whl", hash = "sha256:ab8cb0e0576ccdfb71886366efb102c6a20f268d817be065ce7f9909c631e43e"},
+ {file = "kubernetes-29.0.0.tar.gz", hash = "sha256:c4812e227ae74d07d53c88293e564e54b850452715a59a927e7e1bc6b9a60459"},
+]
+
+[package.dependencies]
+certifi = ">=14.05.14"
+google-auth = ">=1.0.1"
+oauthlib = ">=3.2.2"
+python-dateutil = ">=2.5.3"
+pyyaml = ">=5.4.1"
+requests = "*"
+requests-oauthlib = "*"
+six = ">=1.9.0"
+urllib3 = ">=1.24.2"
+websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.dev0 || >=0.43.dev0"
+
+[package.extras]
+adal = ["adal (>=1.0.2)"]
+
+[[package]]
name = "langcodes"
version = "3.3.0"
description = "Tools for labeling human languages with IETF language tags"
@@ -3027,35 +3170,29 @@ data = ["language-data (>=1.1,<2.0)"]
[[package]]
name = "litellm"
-version = "0.1.824"
+version = "1.17.13"
description = "Library to easily interface with LLM API providers"
optional = false
-python-versions = ">=3.8,<4.0"
+python-versions = ">=3.8, !=2.7.*, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*, !=3.7.*"
files = [
- {file = "litellm-0.1.824-py3-none-any.whl", hash = "sha256:3aed4d3d849b8e518aaafc62758a548111e4502bad7fbcd69581bfeb10bc016a"},
- {file = "litellm-0.1.824.tar.gz", hash = "sha256:8c4dd49d1d996a6b953f39271608139e96ac25c43b91dd32188367b7d233f584"},
+ {file = "litellm-1.17.13-py3-none-any.whl", hash = "sha256:d9370077a3a5e3540c3d2e84580c3fee5add9ff606d6715da0428399b73f389f"},
+ {file = "litellm-1.17.13.tar.gz", hash = "sha256:df2d42bb759cff4d3390a51c11dad87cfd581e56d43103bb4eb4fa4a81d0d38e"},
]
[package.dependencies]
-appdirs = ">=1.4.4,<2.0.0"
+aiohttp = "*"
click = "*"
importlib-metadata = ">=6.8.0"
jinja2 = ">=3.1.2,<4.0.0"
-openai = ">=0.27.0,<0.29.0"
+openai = ">=1.0.0"
python-dotenv = ">=0.2.0"
+requests = ">=2.31.0,<3.0.0"
tiktoken = ">=0.4.0"
tokenizers = "*"
-[[package]]
-name = "lockfile"
-version = "0.12.2"
-description = "Platform-independent file locking module"
-optional = true
-python-versions = "*"
-files = [
- {file = "lockfile-0.12.2-py2.py3-none-any.whl", hash = "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"},
- {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"},
-]
+[package.extras]
+extra-proxy = ["streamlit (>=1.29.0,<2.0.0)"]
+proxy = ["backoff", "fastapi (>=0.104.1,<0.105.0)", "gunicorn (>=21.2.0,<22.0.0)", "orjson (>=3.9.7,<4.0.0)", "pyyaml (>=6.0,<7.0)", "rq", "uvicorn (>=0.22.0,<0.23.0)"]
[[package]]
name = "loguru"
@@ -3077,110 +3214,96 @@ dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptio
[[package]]
name = "lxml"
-version = "4.9.3"
+version = "5.1.0"
description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*"
-files = [
- {file = "lxml-4.9.3-cp27-cp27m-macosx_11_0_x86_64.whl", hash = "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c"},
- {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d"},
- {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef"},
- {file = "lxml-4.9.3-cp27-cp27m-win32.whl", hash = "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7"},
- {file = "lxml-4.9.3-cp27-cp27m-win_amd64.whl", hash = "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1"},
- {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb"},
- {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e"},
- {file = "lxml-4.9.3-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991"},
- {file = "lxml-4.9.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd"},
- {file = "lxml-4.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c"},
- {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8"},
- {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76"},
- {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23"},
- {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f"},
- {file = "lxml-4.9.3-cp310-cp310-win32.whl", hash = "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85"},
- {file = "lxml-4.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d"},
- {file = "lxml-4.9.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5"},
- {file = "lxml-4.9.3-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf"},
- {file = "lxml-4.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a"},
- {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f"},
- {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b"},
- {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120"},
- {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6"},
- {file = "lxml-4.9.3-cp311-cp311-win32.whl", hash = "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305"},
- {file = "lxml-4.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc"},
- {file = "lxml-4.9.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4"},
- {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be"},
- {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13"},
- {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9"},
- {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5"},
- {file = "lxml-4.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8"},
- {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7"},
- {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2"},
- {file = "lxml-4.9.3-cp35-cp35m-win32.whl", hash = "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d"},
- {file = "lxml-4.9.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833"},
- {file = "lxml-4.9.3-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584"},
- {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287"},
- {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458"},
- {file = "lxml-4.9.3-cp36-cp36m-win32.whl", hash = "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477"},
- {file = "lxml-4.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4"},
- {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a"},
- {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02"},
- {file = "lxml-4.9.3-cp37-cp37m-win32.whl", hash = "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f"},
- {file = "lxml-4.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa"},
- {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40"},
- {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7"},
- {file = "lxml-4.9.3-cp38-cp38-win32.whl", hash = "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574"},
- {file = "lxml-4.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96"},
- {file = "lxml-4.9.3-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432"},
- {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69"},
- {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50"},
- {file = "lxml-4.9.3-cp39-cp39-win32.whl", hash = "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2"},
- {file = "lxml-4.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2"},
- {file = "lxml-4.9.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35"},
- {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0"},
- {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3"},
- {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b"},
- {file = "lxml-4.9.3-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b"},
- {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7"},
- {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d"},
- {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b"},
- {file = "lxml-4.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a"},
- {file = "lxml-4.9.3-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0"},
- {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694"},
- {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7"},
- {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4"},
- {file = "lxml-4.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9"},
- {file = "lxml-4.9.3.tar.gz", hash = "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c"},
+python-versions = ">=3.6"
+files = [
+ {file = "lxml-5.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:704f5572ff473a5f897745abebc6df40f22d4133c1e0a1f124e4f2bd3330ff7e"},
+ {file = "lxml-5.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9d3c0f8567ffe7502d969c2c1b809892dc793b5d0665f602aad19895f8d508da"},
+ {file = "lxml-5.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5fcfbebdb0c5d8d18b84118842f31965d59ee3e66996ac842e21f957eb76138c"},
+ {file = "lxml-5.1.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f37c6d7106a9d6f0708d4e164b707037b7380fcd0b04c5bd9cae1fb46a856fb"},
+ {file = "lxml-5.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2befa20a13f1a75c751f47e00929fb3433d67eb9923c2c0b364de449121f447c"},
+ {file = "lxml-5.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22b7ee4c35f374e2c20337a95502057964d7e35b996b1c667b5c65c567d2252a"},
+ {file = "lxml-5.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bf8443781533b8d37b295016a4b53c1494fa9a03573c09ca5104550c138d5c05"},
+ {file = "lxml-5.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:82bddf0e72cb2af3cbba7cec1d2fd11fda0de6be8f4492223d4a268713ef2147"},
+ {file = "lxml-5.1.0-cp310-cp310-win32.whl", hash = "sha256:b66aa6357b265670bb574f050ffceefb98549c721cf28351b748be1ef9577d93"},
+ {file = "lxml-5.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:4946e7f59b7b6a9e27bef34422f645e9a368cb2be11bf1ef3cafc39a1f6ba68d"},
+ {file = "lxml-5.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:14deca1460b4b0f6b01f1ddc9557704e8b365f55c63070463f6c18619ebf964f"},
+ {file = "lxml-5.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ed8c3d2cd329bf779b7ed38db176738f3f8be637bb395ce9629fc76f78afe3d4"},
+ {file = "lxml-5.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:436a943c2900bb98123b06437cdd30580a61340fbdb7b28aaf345a459c19046a"},
+ {file = "lxml-5.1.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:acb6b2f96f60f70e7f34efe0c3ea34ca63f19ca63ce90019c6cbca6b676e81fa"},
+ {file = "lxml-5.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af8920ce4a55ff41167ddbc20077f5698c2e710ad3353d32a07d3264f3a2021e"},
+ {file = "lxml-5.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cfced4a069003d8913408e10ca8ed092c49a7f6cefee9bb74b6b3e860683b45"},
+ {file = "lxml-5.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9e5ac3437746189a9b4121db2a7b86056ac8786b12e88838696899328fc44bb2"},
+ {file = "lxml-5.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f4c9bda132ad108b387c33fabfea47866af87f4ea6ffb79418004f0521e63204"},
+ {file = "lxml-5.1.0-cp311-cp311-win32.whl", hash = "sha256:bc64d1b1dab08f679fb89c368f4c05693f58a9faf744c4d390d7ed1d8223869b"},
+ {file = "lxml-5.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:a5ab722ae5a873d8dcee1f5f45ddd93c34210aed44ff2dc643b5025981908cda"},
+ {file = "lxml-5.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9aa543980ab1fbf1720969af1d99095a548ea42e00361e727c58a40832439114"},
+ {file = "lxml-5.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6f11b77ec0979f7e4dc5ae081325a2946f1fe424148d3945f943ceaede98adb8"},
+ {file = "lxml-5.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a36c506e5f8aeb40680491d39ed94670487ce6614b9d27cabe45d94cd5d63e1e"},
+ {file = "lxml-5.1.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f643ffd2669ffd4b5a3e9b41c909b72b2a1d5e4915da90a77e119b8d48ce867a"},
+ {file = "lxml-5.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16dd953fb719f0ffc5bc067428fc9e88f599e15723a85618c45847c96f11f431"},
+ {file = "lxml-5.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16018f7099245157564d7148165132c70adb272fb5a17c048ba70d9cc542a1a1"},
+ {file = "lxml-5.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:82cd34f1081ae4ea2ede3d52f71b7be313756e99b4b5f829f89b12da552d3aa3"},
+ {file = "lxml-5.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:19a1bc898ae9f06bccb7c3e1dfd73897ecbbd2c96afe9095a6026016e5ca97b8"},
+ {file = "lxml-5.1.0-cp312-cp312-win32.whl", hash = "sha256:13521a321a25c641b9ea127ef478b580b5ec82aa2e9fc076c86169d161798b01"},
+ {file = "lxml-5.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:1ad17c20e3666c035db502c78b86e58ff6b5991906e55bdbef94977700c72623"},
+ {file = "lxml-5.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:24ef5a4631c0b6cceaf2dbca21687e29725b7c4e171f33a8f8ce23c12558ded1"},
+ {file = "lxml-5.1.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d2900b7f5318bc7ad8631d3d40190b95ef2aa8cc59473b73b294e4a55e9f30f"},
+ {file = "lxml-5.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:601f4a75797d7a770daed8b42b97cd1bb1ba18bd51a9382077a6a247a12aa38d"},
+ {file = "lxml-5.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4b68c961b5cc402cbd99cca5eb2547e46ce77260eb705f4d117fd9c3f932b95"},
+ {file = "lxml-5.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:afd825e30f8d1f521713a5669b63657bcfe5980a916c95855060048b88e1adb7"},
+ {file = "lxml-5.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:262bc5f512a66b527d026518507e78c2f9c2bd9eb5c8aeeb9f0eb43fcb69dc67"},
+ {file = "lxml-5.1.0-cp36-cp36m-win32.whl", hash = "sha256:e856c1c7255c739434489ec9c8aa9cdf5179785d10ff20add308b5d673bed5cd"},
+ {file = "lxml-5.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:c7257171bb8d4432fe9d6fdde4d55fdbe663a63636a17f7f9aaba9bcb3153ad7"},
+ {file = "lxml-5.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b9e240ae0ba96477682aa87899d94ddec1cc7926f9df29b1dd57b39e797d5ab5"},
+ {file = "lxml-5.1.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a96f02ba1bcd330807fc060ed91d1f7a20853da6dd449e5da4b09bfcc08fdcf5"},
+ {file = "lxml-5.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3898ae2b58eeafedfe99e542a17859017d72d7f6a63de0f04f99c2cb125936"},
+ {file = "lxml-5.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61c5a7edbd7c695e54fca029ceb351fc45cd8860119a0f83e48be44e1c464862"},
+ {file = "lxml-5.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3aeca824b38ca78d9ee2ab82bd9883083d0492d9d17df065ba3b94e88e4d7ee6"},
+ {file = "lxml-5.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8f52fe6859b9db71ee609b0c0a70fea5f1e71c3462ecf144ca800d3f434f0764"},
+ {file = "lxml-5.1.0-cp37-cp37m-win32.whl", hash = "sha256:d42e3a3fc18acc88b838efded0e6ec3edf3e328a58c68fbd36a7263a874906c8"},
+ {file = "lxml-5.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:eac68f96539b32fce2c9b47eb7c25bb2582bdaf1bbb360d25f564ee9e04c542b"},
+ {file = "lxml-5.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ae15347a88cf8af0949a9872b57a320d2605ae069bcdf047677318bc0bba45b1"},
+ {file = "lxml-5.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c26aab6ea9c54d3bed716b8851c8bfc40cb249b8e9880e250d1eddde9f709bf5"},
+ {file = "lxml-5.1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:342e95bddec3a698ac24378d61996b3ee5ba9acfeb253986002ac53c9a5f6f84"},
+ {file = "lxml-5.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:725e171e0b99a66ec8605ac77fa12239dbe061482ac854d25720e2294652eeaa"},
+ {file = "lxml-5.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d184e0d5c918cff04cdde9dbdf9600e960161d773666958c9d7b565ccc60c45"},
+ {file = "lxml-5.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:98f3f020a2b736566c707c8e034945c02aa94e124c24f77ca097c446f81b01f1"},
+ {file = "lxml-5.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d48fc57e7c1e3df57be5ae8614bab6d4e7b60f65c5457915c26892c41afc59e"},
+ {file = "lxml-5.1.0-cp38-cp38-win32.whl", hash = "sha256:7ec465e6549ed97e9f1e5ed51c657c9ede767bc1c11552f7f4d022c4df4a977a"},
+ {file = "lxml-5.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:b21b4031b53d25b0858d4e124f2f9131ffc1530431c6d1321805c90da78388d1"},
+ {file = "lxml-5.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:52427a7eadc98f9e62cb1368a5079ae826f94f05755d2d567d93ee1bc3ceb354"},
+ {file = "lxml-5.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6a2a2c724d97c1eb8cf966b16ca2915566a4904b9aad2ed9a09c748ffe14f969"},
+ {file = "lxml-5.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:843b9c835580d52828d8f69ea4302537337a21e6b4f1ec711a52241ba4a824f3"},
+ {file = "lxml-5.1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9b99f564659cfa704a2dd82d0684207b1aadf7d02d33e54845f9fc78e06b7581"},
+ {file = "lxml-5.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f8b0c78e7aac24979ef09b7f50da871c2de2def043d468c4b41f512d831e912"},
+ {file = "lxml-5.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9bcf86dfc8ff3e992fed847c077bd875d9e0ba2fa25d859c3a0f0f76f07f0c8d"},
+ {file = "lxml-5.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:49a9b4af45e8b925e1cd6f3b15bbba2c81e7dba6dce170c677c9cda547411e14"},
+ {file = "lxml-5.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:280f3edf15c2a967d923bcfb1f8f15337ad36f93525828b40a0f9d6c2ad24890"},
+ {file = "lxml-5.1.0-cp39-cp39-win32.whl", hash = "sha256:ed7326563024b6e91fef6b6c7a1a2ff0a71b97793ac33dbbcf38f6005e51ff6e"},
+ {file = "lxml-5.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:8d7b4beebb178e9183138f552238f7e6613162a42164233e2bda00cb3afac58f"},
+ {file = "lxml-5.1.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9bd0ae7cc2b85320abd5e0abad5ccee5564ed5f0cc90245d2f9a8ef330a8deae"},
+ {file = "lxml-5.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8c1d679df4361408b628f42b26a5d62bd3e9ba7f0c0e7969f925021554755aa"},
+ {file = "lxml-5.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2ad3a8ce9e8a767131061a22cd28fdffa3cd2dc193f399ff7b81777f3520e372"},
+ {file = "lxml-5.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:304128394c9c22b6569eba2a6d98392b56fbdfbad58f83ea702530be80d0f9df"},
+ {file = "lxml-5.1.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d74fcaf87132ffc0447b3c685a9f862ffb5b43e70ea6beec2fb8057d5d2a1fea"},
+ {file = "lxml-5.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:8cf5877f7ed384dabfdcc37922c3191bf27e55b498fecece9fd5c2c7aaa34c33"},
+ {file = "lxml-5.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:877efb968c3d7eb2dad540b6cabf2f1d3c0fbf4b2d309a3c141f79c7e0061324"},
+ {file = "lxml-5.1.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f14a4fb1c1c402a22e6a341a24c1341b4a3def81b41cd354386dcb795f83897"},
+ {file = "lxml-5.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:25663d6e99659544ee8fe1b89b1a8c0aaa5e34b103fab124b17fa958c4a324a6"},
+ {file = "lxml-5.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8b9f19df998761babaa7f09e6bc169294eefafd6149aaa272081cbddc7ba4ca3"},
+ {file = "lxml-5.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e53d7e6a98b64fe54775d23a7c669763451340c3d44ad5e3a3b48a1efbdc96f"},
+ {file = "lxml-5.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c3cd1fc1dc7c376c54440aeaaa0dcc803d2126732ff5c6b68ccd619f2e64be4f"},
+ {file = "lxml-5.1.0.tar.gz", hash = "sha256:3eea6ed6e6c918e468e693c41ef07f3c3acc310b70ddd9cc72d9ef84bc9564ca"},
]
[package.extras]
cssselect = ["cssselect (>=0.7)"]
html5 = ["html5lib"]
htmlsoup = ["BeautifulSoup4"]
-source = ["Cython (>=0.29.35)"]
+source = ["Cython (>=3.0.7)"]
[[package]]
name = "markupsafe"
@@ -3325,6 +3448,98 @@ files = [
]
[[package]]
+name = "mmh3"
+version = "4.1.0"
+description = "Python extension for MurmurHash (MurmurHash3), a set of fast and robust hash functions."
+optional = false
+python-versions = "*"
+files = [
+ {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:be5ac76a8b0cd8095784e51e4c1c9c318c19edcd1709a06eb14979c8d850c31a"},
+ {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98a49121afdfab67cd80e912b36404139d7deceb6773a83620137aaa0da5714c"},
+ {file = "mmh3-4.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5259ac0535874366e7d1a5423ef746e0d36a9e3c14509ce6511614bdc5a7ef5b"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5950827ca0453a2be357696da509ab39646044e3fa15cad364eb65d78797437"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1dd0f652ae99585b9dd26de458e5f08571522f0402155809fd1dc8852a613a39"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99d25548070942fab1e4a6f04d1626d67e66d0b81ed6571ecfca511f3edf07e6"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53db8d9bad3cb66c8f35cbc894f336273f63489ce4ac416634932e3cbe79eb5b"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75da0f615eb55295a437264cc0b736753f830b09d102aa4c2a7d719bc445ec05"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b926b07fd678ea84b3a2afc1fa22ce50aeb627839c44382f3d0291e945621e1a"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c5b053334f9b0af8559d6da9dc72cef0a65b325ebb3e630c680012323c950bb6"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5bf33dc43cd6de2cb86e0aa73a1cc6530f557854bbbe5d59f41ef6de2e353d7b"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fa7eacd2b830727ba3dd65a365bed8a5c992ecd0c8348cf39a05cc77d22f4970"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:42dfd6742b9e3eec599f85270617debfa0bbb913c545bb980c8a4fa7b2d047da"},
+ {file = "mmh3-4.1.0-cp310-cp310-win32.whl", hash = "sha256:2974ad343f0d39dcc88e93ee6afa96cedc35a9883bc067febd7ff736e207fa47"},
+ {file = "mmh3-4.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:74699a8984ded645c1a24d6078351a056f5a5f1fe5838870412a68ac5e28d865"},
+ {file = "mmh3-4.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:f0dc874cedc23d46fc488a987faa6ad08ffa79e44fb08e3cd4d4cf2877c00a00"},
+ {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3280a463855b0eae64b681cd5b9ddd9464b73f81151e87bb7c91a811d25619e6"},
+ {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:97ac57c6c3301769e757d444fa7c973ceb002cb66534b39cbab5e38de61cd896"},
+ {file = "mmh3-4.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7b6502cdb4dbd880244818ab363c8770a48cdccecf6d729ade0241b736b5ec0"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52ba2da04671a9621580ddabf72f06f0e72c1c9c3b7b608849b58b11080d8f14"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a5fef4c4ecc782e6e43fbeab09cff1bac82c998a1773d3a5ee6a3605cde343e"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5135358a7e00991f73b88cdc8eda5203bf9de22120d10a834c5761dbeb07dd13"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cff9ae76a54f7c6fe0167c9c4028c12c1f6de52d68a31d11b6790bb2ae685560"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f02576a4d106d7830ca90278868bf0983554dd69183b7bbe09f2fcd51cf54f"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:073d57425a23721730d3ff5485e2da489dd3c90b04e86243dd7211f889898106"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:71e32ddec7f573a1a0feb8d2cf2af474c50ec21e7a8263026e8d3b4b629805db"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7cbb20b29d57e76a58b40fd8b13a9130db495a12d678d651b459bf61c0714cea"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a42ad267e131d7847076bb7e31050f6c4378cd38e8f1bf7a0edd32f30224d5c9"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4a013979fc9390abadc445ea2527426a0e7a4495c19b74589204f9b71bcaafeb"},
+ {file = "mmh3-4.1.0-cp311-cp311-win32.whl", hash = "sha256:1d3b1cdad7c71b7b88966301789a478af142bddcb3a2bee563f7a7d40519a00f"},
+ {file = "mmh3-4.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0dc6dc32eb03727467da8e17deffe004fbb65e8b5ee2b502d36250d7a3f4e2ec"},
+ {file = "mmh3-4.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:9ae3a5c1b32dda121c7dc26f9597ef7b01b4c56a98319a7fe86c35b8bc459ae6"},
+ {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0033d60c7939168ef65ddc396611077a7268bde024f2c23bdc283a19123f9e9c"},
+ {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d6af3e2287644b2b08b5924ed3a88c97b87b44ad08e79ca9f93d3470a54a41c5"},
+ {file = "mmh3-4.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d82eb4defa245e02bb0b0dc4f1e7ee284f8d212633389c91f7fba99ba993f0a2"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba245e94b8d54765e14c2d7b6214e832557e7856d5183bc522e17884cab2f45d"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb04e2feeabaad6231e89cd43b3d01a4403579aa792c9ab6fdeef45cc58d4ec0"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e3b1a27def545ce11e36158ba5d5390cdbc300cfe456a942cc89d649cf7e3b2"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce0ab79ff736d7044e5e9b3bfe73958a55f79a4ae672e6213e92492ad5e734d5"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b02268be6e0a8eeb8a924d7db85f28e47344f35c438c1e149878bb1c47b1cd3"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:deb887f5fcdaf57cf646b1e062d56b06ef2f23421c80885fce18b37143cba828"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99dd564e9e2b512eb117bd0cbf0f79a50c45d961c2a02402787d581cec5448d5"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:08373082dfaa38fe97aa78753d1efd21a1969e51079056ff552e687764eafdfe"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:54b9c6a2ea571b714e4fe28d3e4e2db37abfd03c787a58074ea21ee9a8fd1740"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a7b1edf24c69e3513f879722b97ca85e52f9032f24a52284746877f6a7304086"},
+ {file = "mmh3-4.1.0-cp312-cp312-win32.whl", hash = "sha256:411da64b951f635e1e2284b71d81a5a83580cea24994b328f8910d40bed67276"},
+ {file = "mmh3-4.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:bebc3ecb6ba18292e3d40c8712482b4477abd6981c2ebf0e60869bd90f8ac3a9"},
+ {file = "mmh3-4.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:168473dd608ade6a8d2ba069600b35199a9af837d96177d3088ca91f2b3798e3"},
+ {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:372f4b7e1dcde175507640679a2a8790185bb71f3640fc28a4690f73da986a3b"},
+ {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:438584b97f6fe13e944faf590c90fc127682b57ae969f73334040d9fa1c7ffa5"},
+ {file = "mmh3-4.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6e27931b232fc676675fac8641c6ec6b596daa64d82170e8597f5a5b8bdcd3b6"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:571a92bad859d7b0330e47cfd1850b76c39b615a8d8e7aa5853c1f971fd0c4b1"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a69d6afe3190fa08f9e3a58e5145549f71f1f3fff27bd0800313426929c7068"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afb127be0be946b7630220908dbea0cee0d9d3c583fa9114a07156f98566dc28"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:940d86522f36348ef1a494cbf7248ab3f4a1638b84b59e6c9e90408bd11ad729"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3dcccc4935686619a8e3d1f7b6e97e3bd89a4a796247930ee97d35ea1a39341"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01bb9b90d61854dfc2407c5e5192bfb47222d74f29d140cb2dd2a69f2353f7cc"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bcb1b8b951a2c0b0fb8a5426c62a22557e2ffc52539e0a7cc46eb667b5d606a9"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6477a05d5e5ab3168e82e8b106e316210ac954134f46ec529356607900aea82a"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:da5892287e5bea6977364b15712a2573c16d134bc5fdcdd4cf460006cf849278"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:99180d7fd2327a6fffbaff270f760576839dc6ee66d045fa3a450f3490fda7f5"},
+ {file = "mmh3-4.1.0-cp38-cp38-win32.whl", hash = "sha256:9b0d4f3949913a9f9a8fb1bb4cc6ecd52879730aab5ff8c5a3d8f5b593594b73"},
+ {file = "mmh3-4.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:598c352da1d945108aee0c3c3cfdd0e9b3edef74108f53b49d481d3990402169"},
+ {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:475d6d1445dd080f18f0f766277e1237fa2914e5fe3307a3b2a3044f30892103"},
+ {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5ca07c41e6a2880991431ac717c2a049056fff497651a76e26fc22224e8b5732"},
+ {file = "mmh3-4.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ebe052fef4bbe30c0548d12ee46d09f1b69035ca5208a7075e55adfe091be44"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaefd42e85afb70f2b855a011f7b4d8a3c7e19c3f2681fa13118e4d8627378c5"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0ae43caae5a47afe1b63a1ae3f0986dde54b5fb2d6c29786adbfb8edc9edfb"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6218666f74c8c013c221e7f5f8a693ac9cf68e5ac9a03f2373b32d77c48904de"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac59294a536ba447b5037f62d8367d7d93b696f80671c2c45645fa9f1109413c"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086844830fcd1e5c84fec7017ea1ee8491487cfc877847d96f86f68881569d2e"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e42b38fad664f56f77f6fbca22d08450f2464baa68acdbf24841bf900eb98e87"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d08b790a63a9a1cde3b5d7d733ed97d4eb884bfbc92f075a091652d6bfd7709a"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:73ea4cc55e8aea28c86799ecacebca09e5f86500414870a8abaedfcbaf74d288"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f90938ff137130e47bcec8dc1f4ceb02f10178c766e2ef58a9f657ff1f62d124"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:aa1f13e94b8631c8cd53259250556edcf1de71738936b60febba95750d9632bd"},
+ {file = "mmh3-4.1.0-cp39-cp39-win32.whl", hash = "sha256:a3b680b471c181490cf82da2142029edb4298e1bdfcb67c76922dedef789868d"},
+ {file = "mmh3-4.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:fefef92e9c544a8dbc08f77a8d1b6d48006a750c4375bbcd5ff8199d761e263b"},
+ {file = "mmh3-4.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:8e2c1f6a2b41723a4f82bd5a762a777836d29d664fc0095f17910bea0adfd4a6"},
+ {file = "mmh3-4.1.0.tar.gz", hash = "sha256:a1cf25348b9acd229dda464a094d6170f47d2850a1fcb762a3b6172d2ce6ca4a"},
+]
+
+[package.extras]
+test = ["mypy (>=1.0)", "pytest (>=7.0.0)"]
+
+[[package]]
name = "monotonic"
version = "1.6"
description = "An implementation of time.monotonic() for Python 2 & < 3.3"
@@ -3479,38 +3694,38 @@ files = [
[[package]]
name = "mypy"
-version = "1.7.1"
+version = "1.8.0"
description = "Optional static typing for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "mypy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:12cce78e329838d70a204293e7b29af9faa3ab14899aec397798a4b41be7f340"},
- {file = "mypy-1.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1484b8fa2c10adf4474f016e09d7a159602f3239075c7bf9f1627f5acf40ad49"},
- {file = "mypy-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31902408f4bf54108bbfb2e35369877c01c95adc6192958684473658c322c8a5"},
- {file = "mypy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f2c2521a8e4d6d769e3234350ba7b65ff5d527137cdcde13ff4d99114b0c8e7d"},
- {file = "mypy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:fcd2572dd4519e8a6642b733cd3a8cfc1ef94bafd0c1ceed9c94fe736cb65b6a"},
- {file = "mypy-1.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b901927f16224d0d143b925ce9a4e6b3a758010673eeded9b748f250cf4e8f7"},
- {file = "mypy-1.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2f7f6985d05a4e3ce8255396df363046c28bea790e40617654e91ed580ca7c51"},
- {file = "mypy-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:944bdc21ebd620eafefc090cdf83158393ec2b1391578359776c00de00e8907a"},
- {file = "mypy-1.7.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9c7ac372232c928fff0645d85f273a726970c014749b924ce5710d7d89763a28"},
- {file = "mypy-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:f6efc9bd72258f89a3816e3a98c09d36f079c223aa345c659622f056b760ab42"},
- {file = "mypy-1.7.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6dbdec441c60699288adf051f51a5d512b0d818526d1dcfff5a41f8cd8b4aaf1"},
- {file = "mypy-1.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fc3d14ee80cd22367caaaf6e014494415bf440980a3045bf5045b525680ac33"},
- {file = "mypy-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c6e4464ed5f01dc44dc9821caf67b60a4e5c3b04278286a85c067010653a0eb"},
- {file = "mypy-1.7.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d9b338c19fa2412f76e17525c1b4f2c687a55b156320acb588df79f2e6fa9fea"},
- {file = "mypy-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:204e0d6de5fd2317394a4eff62065614c4892d5a4d1a7ee55b765d7a3d9e3f82"},
- {file = "mypy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:84860e06ba363d9c0eeabd45ac0fde4b903ad7aa4f93cd8b648385a888e23200"},
- {file = "mypy-1.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8c5091ebd294f7628eb25ea554852a52058ac81472c921150e3a61cdd68f75a7"},
- {file = "mypy-1.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40716d1f821b89838589e5b3106ebbc23636ffdef5abc31f7cd0266db936067e"},
- {file = "mypy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cf3f0c5ac72139797953bd50bc6c95ac13075e62dbfcc923571180bebb662e9"},
- {file = "mypy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:78e25b2fd6cbb55ddfb8058417df193f0129cad5f4ee75d1502248e588d9e0d7"},
- {file = "mypy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75c4d2a6effd015786c87774e04331b6da863fc3fc4e8adfc3b40aa55ab516fe"},
- {file = "mypy-1.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2643d145af5292ee956aa0a83c2ce1038a3bdb26e033dadeb2f7066fb0c9abce"},
- {file = "mypy-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aa828610b67462ffe3057d4d8a4112105ed211596b750b53cbfe182f44777a"},
- {file = "mypy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ee5d62d28b854eb61889cde4e1dbc10fbaa5560cb39780c3995f6737f7e82120"},
- {file = "mypy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:72cf32ce7dd3562373f78bd751f73c96cfb441de147cc2448a92c1a308bd0ca6"},
- {file = "mypy-1.7.1-py3-none-any.whl", hash = "sha256:f7c5d642db47376a0cc130f0de6d055056e010debdaf0707cd2b0fc7e7ef30ea"},
- {file = "mypy-1.7.1.tar.gz", hash = "sha256:fcb6d9afb1b6208b4c712af0dafdc650f518836065df0d4fb1d800f5d6773db2"},
+ {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"},
+ {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"},
+ {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"},
+ {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"},
+ {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"},
+ {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"},
+ {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"},
+ {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"},
+ {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"},
+ {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"},
+ {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"},
+ {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"},
+ {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"},
+ {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"},
+ {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"},
+ {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"},
+ {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"},
+ {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"},
+ {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"},
+ {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"},
+ {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"},
+ {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"},
+ {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"},
+ {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"},
+ {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"},
+ {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"},
+ {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"},
]
[package.dependencies]
@@ -3526,13 +3741,13 @@ reports = ["lxml"]
[[package]]
name = "mypy-boto3-s3"
-version = "1.33.2"
-description = "Type annotations for boto3.S3 1.33.2 service generated with mypy-boto3-builder 7.20.3"
+version = "1.34.14"
+description = "Type annotations for boto3.S3 1.34.14 service generated with mypy-boto3-builder 7.21.0"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "mypy-boto3-s3-1.33.2.tar.gz", hash = "sha256:f54a3ad3288f4e4719ebada3dde68c320507b0fc451d59bc68af7e6ab15cbdad"},
- {file = "mypy_boto3_s3-1.33.2-py3-none-any.whl", hash = "sha256:9d463df6def30de31a467d49ab92ff7795d46709d56eff6f52216a08bac27918"},
+ {file = "mypy-boto3-s3-1.34.14.tar.gz", hash = "sha256:71c39ab0623cdb442d225b71c1783f6a513cff4c4a13505a2efbb2e3aff2e965"},
+ {file = "mypy_boto3_s3-1.34.14-py3-none-any.whl", hash = "sha256:f9669ecd182d5bf3532f5f2dcc5e5237776afe157ad5a0b37b26d6bec5fcc432"},
]
[package.dependencies]
@@ -3583,49 +3798,65 @@ setuptools = "*"
[[package]]
name = "numpy"
-version = "1.26.2"
+version = "1.26.3"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.9"
files = [
- {file = "numpy-1.26.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3703fc9258a4a122d17043e57b35e5ef1c5a5837c3db8be396c82e04c1cf9b0f"},
- {file = "numpy-1.26.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc392fdcbd21d4be6ae1bb4475a03ce3b025cd49a9be5345d76d7585aea69440"},
- {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36340109af8da8805d8851ef1d74761b3b88e81a9bd80b290bbfed61bd2b4f75"},
- {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcc008217145b3d77abd3e4d5ef586e3bdfba8fe17940769f8aa09b99e856c00"},
- {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3ced40d4e9e18242f70dd02d739e44698df3dcb010d31f495ff00a31ef6014fe"},
- {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b272d4cecc32c9e19911891446b72e986157e6a1809b7b56518b4f3755267523"},
- {file = "numpy-1.26.2-cp310-cp310-win32.whl", hash = "sha256:22f8fc02fdbc829e7a8c578dd8d2e15a9074b630d4da29cda483337e300e3ee9"},
- {file = "numpy-1.26.2-cp310-cp310-win_amd64.whl", hash = "sha256:26c9d33f8e8b846d5a65dd068c14e04018d05533b348d9eaeef6c1bd787f9919"},
- {file = "numpy-1.26.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b96e7b9c624ef3ae2ae0e04fa9b460f6b9f17ad8b4bec6d7756510f1f6c0c841"},
- {file = "numpy-1.26.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aa18428111fb9a591d7a9cc1b48150097ba6a7e8299fb56bdf574df650e7d1f1"},
- {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06fa1ed84aa60ea6ef9f91ba57b5ed963c3729534e6e54055fc151fad0423f0a"},
- {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96ca5482c3dbdd051bcd1fce8034603d6ebfc125a7bd59f55b40d8f5d246832b"},
- {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:854ab91a2906ef29dc3925a064fcd365c7b4da743f84b123002f6139bcb3f8a7"},
- {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f43740ab089277d403aa07567be138fc2a89d4d9892d113b76153e0e412409f8"},
- {file = "numpy-1.26.2-cp311-cp311-win32.whl", hash = "sha256:a2bbc29fcb1771cd7b7425f98b05307776a6baf43035d3b80c4b0f29e9545186"},
- {file = "numpy-1.26.2-cp311-cp311-win_amd64.whl", hash = "sha256:2b3fca8a5b00184828d12b073af4d0fc5fdd94b1632c2477526f6bd7842d700d"},
- {file = "numpy-1.26.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a4cd6ed4a339c21f1d1b0fdf13426cb3b284555c27ac2f156dfdaaa7e16bfab0"},
- {file = "numpy-1.26.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d5244aabd6ed7f312268b9247be47343a654ebea52a60f002dc70c769048e75"},
- {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a3cdb4d9c70e6b8c0814239ead47da00934666f668426fc6e94cce869e13fd7"},
- {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa317b2325f7aa0a9471663e6093c210cb2ae9c0ad824732b307d2c51983d5b6"},
- {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:174a8880739c16c925799c018f3f55b8130c1f7c8e75ab0a6fa9d41cab092fd6"},
- {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f79b231bf5c16b1f39c7f4875e1ded36abee1591e98742b05d8a0fb55d8a3eec"},
- {file = "numpy-1.26.2-cp312-cp312-win32.whl", hash = "sha256:4a06263321dfd3598cacb252f51e521a8cb4b6df471bb12a7ee5cbab20ea9167"},
- {file = "numpy-1.26.2-cp312-cp312-win_amd64.whl", hash = "sha256:b04f5dc6b3efdaab541f7857351aac359e6ae3c126e2edb376929bd3b7f92d7e"},
- {file = "numpy-1.26.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4eb8df4bf8d3d90d091e0146f6c28492b0be84da3e409ebef54349f71ed271ef"},
- {file = "numpy-1.26.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1a13860fdcd95de7cf58bd6f8bc5a5ef81c0b0625eb2c9a783948847abbef2c2"},
- {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64308ebc366a8ed63fd0bf426b6a9468060962f1a4339ab1074c228fa6ade8e3"},
- {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baf8aab04a2c0e859da118f0b38617e5ee65d75b83795055fb66c0d5e9e9b818"},
- {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d73a3abcac238250091b11caef9ad12413dab01669511779bc9b29261dd50210"},
- {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b361d369fc7e5e1714cf827b731ca32bff8d411212fccd29ad98ad622449cc36"},
- {file = "numpy-1.26.2-cp39-cp39-win32.whl", hash = "sha256:bd3f0091e845164a20bd5a326860c840fe2af79fa12e0469a12768a3ec578d80"},
- {file = "numpy-1.26.2-cp39-cp39-win_amd64.whl", hash = "sha256:2beef57fb031dcc0dc8fa4fe297a742027b954949cabb52a2a376c144e5e6060"},
- {file = "numpy-1.26.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1cc3d5029a30fb5f06704ad6b23b35e11309491c999838c31f124fee32107c79"},
- {file = "numpy-1.26.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94cc3c222bb9fb5a12e334d0479b97bb2df446fbe622b470928f5284ffca3f8d"},
- {file = "numpy-1.26.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe6b44fb8fcdf7eda4ef4461b97b3f63c466b27ab151bec2366db8b197387841"},
- {file = "numpy-1.26.2.tar.gz", hash = "sha256:f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea"},
+ {file = "numpy-1.26.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:806dd64230dbbfaca8a27faa64e2f414bf1c6622ab78cc4264f7f5f028fee3bf"},
+ {file = "numpy-1.26.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f98011ba4ab17f46f80f7f8f1c291ee7d855fcef0a5a98db80767a468c85cd"},
+ {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d45b3ec2faed4baca41c76617fcdcfa4f684ff7a151ce6fc78ad3b6e85af0a6"},
+ {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdd2b45bf079d9ad90377048e2747a0c82351989a2165821f0c96831b4a2a54b"},
+ {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:211ddd1e94817ed2d175b60b6374120244a4dd2287f4ece45d49228b4d529178"},
+ {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1240f767f69d7c4c8a29adde2310b871153df9b26b5cb2b54a561ac85146485"},
+ {file = "numpy-1.26.3-cp310-cp310-win32.whl", hash = "sha256:21a9484e75ad018974a2fdaa216524d64ed4212e418e0a551a2d83403b0531d3"},
+ {file = "numpy-1.26.3-cp310-cp310-win_amd64.whl", hash = "sha256:9e1591f6ae98bcfac2a4bbf9221c0b92ab49762228f38287f6eeb5f3f55905ce"},
+ {file = "numpy-1.26.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b831295e5472954104ecb46cd98c08b98b49c69fdb7040483aff799a755a7374"},
+ {file = "numpy-1.26.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9e87562b91f68dd8b1c39149d0323b42e0082db7ddb8e934ab4c292094d575d6"},
+ {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c66d6fec467e8c0f975818c1796d25c53521124b7cfb760114be0abad53a0a2"},
+ {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f25e2811a9c932e43943a2615e65fc487a0b6b49218899e62e426e7f0a57eeda"},
+ {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af36e0aa45e25c9f57bf684b1175e59ea05d9a7d3e8e87b7ae1a1da246f2767e"},
+ {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:51c7f1b344f302067b02e0f5b5d2daa9ed4a721cf49f070280ac202738ea7f00"},
+ {file = "numpy-1.26.3-cp311-cp311-win32.whl", hash = "sha256:7ca4f24341df071877849eb2034948459ce3a07915c2734f1abb4018d9c49d7b"},
+ {file = "numpy-1.26.3-cp311-cp311-win_amd64.whl", hash = "sha256:39763aee6dfdd4878032361b30b2b12593fb445ddb66bbac802e2113eb8a6ac4"},
+ {file = "numpy-1.26.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a7081fd19a6d573e1a05e600c82a1c421011db7935ed0d5c483e9dd96b99cf13"},
+ {file = "numpy-1.26.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12c70ac274b32bc00c7f61b515126c9205323703abb99cd41836e8125ea0043e"},
+ {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f784e13e598e9594750b2ef6729bcd5a47f6cfe4a12cca13def35e06d8163e3"},
+ {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f24750ef94d56ce6e33e4019a8a4d68cfdb1ef661a52cdaee628a56d2437419"},
+ {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:77810ef29e0fb1d289d225cabb9ee6cf4d11978a00bb99f7f8ec2132a84e0166"},
+ {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8ed07a90f5450d99dad60d3799f9c03c6566709bd53b497eb9ccad9a55867f36"},
+ {file = "numpy-1.26.3-cp312-cp312-win32.whl", hash = "sha256:f73497e8c38295aaa4741bdfa4fda1a5aedda5473074369eca10626835445511"},
+ {file = "numpy-1.26.3-cp312-cp312-win_amd64.whl", hash = "sha256:da4b0c6c699a0ad73c810736303f7fbae483bcb012e38d7eb06a5e3b432c981b"},
+ {file = "numpy-1.26.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1666f634cb3c80ccbd77ec97bc17337718f56d6658acf5d3b906ca03e90ce87f"},
+ {file = "numpy-1.26.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18c3319a7d39b2c6a9e3bb75aab2304ab79a811ac0168a671a62e6346c29b03f"},
+ {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b7e807d6888da0db6e7e75838444d62495e2b588b99e90dd80c3459594e857b"},
+ {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4d362e17bcb0011738c2d83e0a65ea8ce627057b2fdda37678f4374a382a137"},
+ {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b8c275f0ae90069496068c714387b4a0eba5d531aace269559ff2b43655edd58"},
+ {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cc0743f0302b94f397a4a65a660d4cd24267439eb16493fb3caad2e4389bccbb"},
+ {file = "numpy-1.26.3-cp39-cp39-win32.whl", hash = "sha256:9bc6d1a7f8cedd519c4b7b1156d98e051b726bf160715b769106661d567b3f03"},
+ {file = "numpy-1.26.3-cp39-cp39-win_amd64.whl", hash = "sha256:867e3644e208c8922a3be26fc6bbf112a035f50f0a86497f98f228c50c607bb2"},
+ {file = "numpy-1.26.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3c67423b3703f8fbd90f5adaa37f85b5794d3366948efe9a5190a5f3a83fc34e"},
+ {file = "numpy-1.26.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46f47ee566d98849323f01b349d58f2557f02167ee301e5e28809a8c0e27a2d0"},
+ {file = "numpy-1.26.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a8474703bffc65ca15853d5fd4d06b18138ae90c17c8d12169968e998e448bb5"},
+ {file = "numpy-1.26.3.tar.gz", hash = "sha256:697df43e2b6310ecc9d95f05d5ef20eacc09c7c4ecc9da3f235d39e71b7da1e4"},
+]
+
+[[package]]
+name = "oauthlib"
+version = "3.2.2"
+description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"},
+ {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"},
]
+[package.extras]
+rsa = ["cryptography (>=3.0.0)"]
+signals = ["blinker (>=1.4.0)"]
+signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"]
+
[[package]]
name = "onnxruntime"
version = "1.16.3"
@@ -3669,25 +3900,26 @@ sympy = "*"
[[package]]
name = "openai"
-version = "0.27.10"
-description = "Python client library for the OpenAI API"
+version = "1.8.0"
+description = "The official Python library for the openai API"
optional = false
python-versions = ">=3.7.1"
files = [
- {file = "openai-0.27.10-py3-none-any.whl", hash = "sha256:beabd1757e3286fa166dde3b70ebb5ad8081af046876b47c14c41e203ed22a14"},
- {file = "openai-0.27.10.tar.gz", hash = "sha256:60e09edf7100080283688748c6803b7b3b52d5a55d21890f3815292a0552d83b"},
+ {file = "openai-1.8.0-py3-none-any.whl", hash = "sha256:0f8f53805826103fdd8adaf379ad3ec23f9d867e698cbc14caf34b778d150175"},
+ {file = "openai-1.8.0.tar.gz", hash = "sha256:93366be27802f517e89328801913d2a5ede45e3b86fdcab420385b8a1b88c767"},
]
[package.dependencies]
-aiohttp = "*"
-requests = ">=2.20"
-tqdm = "*"
+anyio = ">=3.5.0,<5"
+distro = ">=1.7.0,<2"
+httpx = ">=0.23.0,<1"
+pydantic = ">=1.9.0,<3"
+sniffio = "*"
+tqdm = ">4"
+typing-extensions = ">=4.7,<5"
[package.extras]
-datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
-dev = ["black (>=21.6b0,<22.0)", "pytest (==6.*)", "pytest-asyncio", "pytest-mock"]
-embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"]
-wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"]
+datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
[[package]]
name = "openapi-python-client"
@@ -3715,6 +3947,172 @@ shellingham = ">=1.3.2,<2.0.0"
typer = ">0.6,<0.10"
[[package]]
+name = "opentelemetry-api"
+version = "1.22.0"
+description = "OpenTelemetry Python API"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_api-1.22.0-py3-none-any.whl", hash = "sha256:43621514301a7e9f5d06dd8013a1b450f30c2e9372b8e30aaeb4562abf2ce034"},
+ {file = "opentelemetry_api-1.22.0.tar.gz", hash = "sha256:15ae4ca925ecf9cfdfb7a709250846fbb08072260fca08ade78056c502b86bed"},
+]
+
+[package.dependencies]
+deprecated = ">=1.2.6"
+importlib-metadata = ">=6.0,<7.0"
+
+[[package]]
+name = "opentelemetry-exporter-otlp-proto-common"
+version = "1.22.0"
+description = "OpenTelemetry Protobuf encoding"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_exporter_otlp_proto_common-1.22.0-py3-none-any.whl", hash = "sha256:3f2538bec5312587f8676c332b3747f54c89fe6364803a807e217af4603201fa"},
+ {file = "opentelemetry_exporter_otlp_proto_common-1.22.0.tar.gz", hash = "sha256:71ae2f81bc6d6fe408d06388826edc8933759b2ca3a97d24054507dc7cfce52d"},
+]
+
+[package.dependencies]
+backoff = {version = ">=1.10.0,<3.0.0", markers = "python_version >= \"3.7\""}
+opentelemetry-proto = "1.22.0"
+
+[[package]]
+name = "opentelemetry-exporter-otlp-proto-grpc"
+version = "1.22.0"
+description = "OpenTelemetry Collector Protobuf over gRPC Exporter"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_exporter_otlp_proto_grpc-1.22.0-py3-none-any.whl", hash = "sha256:b5bcadc129272004316a455e9081216d3380c1fc2231a928ea6a70aa90e173fb"},
+ {file = "opentelemetry_exporter_otlp_proto_grpc-1.22.0.tar.gz", hash = "sha256:1e0e5aa4bbabc74942f06f268deffd94851d12a8dc30b02527472ef1729fe5b1"},
+]
+
+[package.dependencies]
+backoff = {version = ">=1.10.0,<3.0.0", markers = "python_version >= \"3.7\""}
+deprecated = ">=1.2.6"
+googleapis-common-protos = ">=1.52,<2.0"
+grpcio = ">=1.0.0,<2.0.0"
+opentelemetry-api = ">=1.15,<2.0"
+opentelemetry-exporter-otlp-proto-common = "1.22.0"
+opentelemetry-proto = "1.22.0"
+opentelemetry-sdk = ">=1.22.0,<1.23.0"
+
+[package.extras]
+test = ["pytest-grpc"]
+
+[[package]]
+name = "opentelemetry-instrumentation"
+version = "0.43b0"
+description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_instrumentation-0.43b0-py3-none-any.whl", hash = "sha256:0ff1334d7e359e27640e9d420024efeb73eacae464309c2e14ede7ba6c93967e"},
+ {file = "opentelemetry_instrumentation-0.43b0.tar.gz", hash = "sha256:c3755da6c4be8033be0216d0501e11f4832690f4e2eca5a3576fbf113498f0f6"},
+]
+
+[package.dependencies]
+opentelemetry-api = ">=1.4,<2.0"
+setuptools = ">=16.0"
+wrapt = ">=1.0.0,<2.0.0"
+
+[[package]]
+name = "opentelemetry-instrumentation-asgi"
+version = "0.43b0"
+description = "ASGI instrumentation for OpenTelemetry"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_instrumentation_asgi-0.43b0-py3-none-any.whl", hash = "sha256:1f593829fa039e9367820736fb063e92acd15c25b53d7bcb5d319971b8e93fd7"},
+ {file = "opentelemetry_instrumentation_asgi-0.43b0.tar.gz", hash = "sha256:3f6f19333dca31ef696672e4e36cb1c2613c71dc7e847c11ff36a37e1130dadc"},
+]
+
+[package.dependencies]
+asgiref = ">=3.0,<4.0"
+opentelemetry-api = ">=1.12,<2.0"
+opentelemetry-instrumentation = "0.43b0"
+opentelemetry-semantic-conventions = "0.43b0"
+opentelemetry-util-http = "0.43b0"
+
+[package.extras]
+instruments = ["asgiref (>=3.0,<4.0)"]
+test = ["opentelemetry-instrumentation-asgi[instruments]", "opentelemetry-test-utils (==0.43b0)"]
+
+[[package]]
+name = "opentelemetry-instrumentation-fastapi"
+version = "0.43b0"
+description = "OpenTelemetry FastAPI Instrumentation"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_instrumentation_fastapi-0.43b0-py3-none-any.whl", hash = "sha256:b79c044df68a52e07b35fa12a424e7cc0dd27ff0a171c5fdcc41dea9de8fc938"},
+ {file = "opentelemetry_instrumentation_fastapi-0.43b0.tar.gz", hash = "sha256:2afaaf470622e1a2732182c68f6d2431ffe5e026a7edacd0f83605632b66347f"},
+]
+
+[package.dependencies]
+opentelemetry-api = ">=1.12,<2.0"
+opentelemetry-instrumentation = "0.43b0"
+opentelemetry-instrumentation-asgi = "0.43b0"
+opentelemetry-semantic-conventions = "0.43b0"
+opentelemetry-util-http = "0.43b0"
+
+[package.extras]
+instruments = ["fastapi (>=0.58,<1.0)"]
+test = ["httpx (>=0.22,<1.0)", "opentelemetry-instrumentation-fastapi[instruments]", "opentelemetry-test-utils (==0.43b0)", "requests (>=2.23,<3.0)"]
+
+[[package]]
+name = "opentelemetry-proto"
+version = "1.22.0"
+description = "OpenTelemetry Python Proto"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_proto-1.22.0-py3-none-any.whl", hash = "sha256:ce7188d22c75b6d0fe53e7fb58501613d0feade5139538e79dedd9420610fa0c"},
+ {file = "opentelemetry_proto-1.22.0.tar.gz", hash = "sha256:9ec29169286029f17ca34ec1f3455802ffb90131642d2f545ece9a63e8f69003"},
+]
+
+[package.dependencies]
+protobuf = ">=3.19,<5.0"
+
+[[package]]
+name = "opentelemetry-sdk"
+version = "1.22.0"
+description = "OpenTelemetry Python SDK"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_sdk-1.22.0-py3-none-any.whl", hash = "sha256:a730555713d7c8931657612a88a141e3a4fe6eb5523d9e2d5a8b1e673d76efa6"},
+ {file = "opentelemetry_sdk-1.22.0.tar.gz", hash = "sha256:45267ac1f38a431fc2eb5d6e0c0d83afc0b78de57ac345488aa58c28c17991d0"},
+]
+
+[package.dependencies]
+opentelemetry-api = "1.22.0"
+opentelemetry-semantic-conventions = "0.43b0"
+typing-extensions = ">=3.7.4"
+
+[[package]]
+name = "opentelemetry-semantic-conventions"
+version = "0.43b0"
+description = "OpenTelemetry Semantic Conventions"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_semantic_conventions-0.43b0-py3-none-any.whl", hash = "sha256:291284d7c1bf15fdaddf309b3bd6d3b7ce12a253cec6d27144439819a15d8445"},
+ {file = "opentelemetry_semantic_conventions-0.43b0.tar.gz", hash = "sha256:b9576fb890df479626fa624e88dde42d3d60b8b6c8ae1152ad157a8b97358635"},
+]
+
+[[package]]
+name = "opentelemetry-util-http"
+version = "0.43b0"
+description = "Web util for OpenTelemetry"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_util_http-0.43b0-py3-none-any.whl", hash = "sha256:f25a820784b030f6cb86b3d76e5676c769b75ed3f55a210bcdae0a5e175ebadb"},
+ {file = "opentelemetry_util_http-0.43b0.tar.gz", hash = "sha256:3ff6ab361dbe99fc81200d625603c0fb890c055c6e416a3e6d661ddf47a6c7f7"},
+]
+
+[[package]]
name = "orjson"
version = "3.9.10"
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
@@ -3893,6 +4291,17 @@ qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
testing = ["docopt", "pytest (<6.0.0)"]
[[package]]
+name = "pathlib-abc"
+version = "0.1.1"
+description = "Backport of pathlib ABCs"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pathlib_abc-0.1.1-py3-none-any.whl", hash = "sha256:5cb2f942fdbb75ce0e00ed3b94de9695b0c5d4b419b5004a702da80f165b3109"},
+ {file = "pathlib_abc-0.1.1.tar.gz", hash = "sha256:084e7bdd919b0f7774914a9e64cd86a1b39860f81f781dd724258631f2915abe"},
+]
+
+[[package]]
name = "pathspec"
version = "0.12.1"
description = "Utility library for gitignore style pattern matching of file paths."
@@ -3905,16 +4314,17 @@ files = [
[[package]]
name = "pathy"
-version = "0.10.3"
+version = "0.11.0"
description = "pathlib.Path subclasses for local and cloud bucket storage"
optional = false
-python-versions = ">= 3.6"
+python-versions = ">= 3.8"
files = [
- {file = "pathy-0.10.3-py3-none-any.whl", hash = "sha256:c5fe70867c79037d5fb34bfeef57d5c19a0b948cdf9286894ca44d72dfa53066"},
- {file = "pathy-0.10.3.tar.gz", hash = "sha256:b45185d06f9b18c6d3346d3aab881ab96874553f661ee88ccd2e60246e103c22"},
+ {file = "pathy-0.11.0-py3-none-any.whl", hash = "sha256:5027f44744cdcd6b6ffd0b0570133dc1bc4af4b87a4f574ecdd810552b1a9fb0"},
+ {file = "pathy-0.11.0.tar.gz", hash = "sha256:bb3d0e6b0b8bf76ef4f63c7191e96e0af2ed65c8fdb5fa17488f9c879e63706d"},
]
[package.dependencies]
+pathlib-abc = "0.1.1"
smart-open = ">=5.2.1,<7.0.0"
typer = ">=0.3.0,<1.0.0"
@@ -3941,70 +4351,88 @@ ptyprocess = ">=0.5"
[[package]]
name = "pillow"
-version = "10.1.0"
+version = "10.2.0"
description = "Python Imaging Library (Fork)"
optional = false
python-versions = ">=3.8"
files = [
- {file = "Pillow-10.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106"},
- {file = "Pillow-10.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273"},
- {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666"},
- {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2"},
- {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593"},
- {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db"},
- {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f"},
- {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818"},
- {file = "Pillow-10.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57"},
- {file = "Pillow-10.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7"},
- {file = "Pillow-10.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7"},
- {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610"},
- {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839"},
- {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172"},
- {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061"},
- {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262"},
- {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992"},
- {file = "Pillow-10.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a"},
- {file = "Pillow-10.1.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b"},
- {file = "Pillow-10.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d"},
- {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27"},
- {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312"},
- {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de"},
- {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651"},
- {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b"},
- {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f"},
- {file = "Pillow-10.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996"},
- {file = "Pillow-10.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793"},
- {file = "Pillow-10.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e"},
- {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2"},
- {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a"},
- {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01"},
- {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d"},
- {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80"},
- {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212"},
- {file = "Pillow-10.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14"},
- {file = "Pillow-10.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099"},
- {file = "Pillow-10.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616"},
- {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb"},
- {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219"},
- {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34"},
- {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd"},
- {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28"},
- {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2"},
- {file = "Pillow-10.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256"},
- {file = "Pillow-10.1.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7"},
- {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba"},
- {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4"},
- {file = "Pillow-10.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9"},
- {file = "Pillow-10.1.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e"},
- {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412"},
- {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b"},
- {file = "Pillow-10.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f"},
- {file = "Pillow-10.1.0.tar.gz", hash = "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38"},
+ {file = "pillow-10.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e"},
+ {file = "pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2"},
+ {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c"},
+ {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0"},
+ {file = "pillow-10.2.0-cp310-cp310-win32.whl", hash = "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023"},
+ {file = "pillow-10.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72"},
+ {file = "pillow-10.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad"},
+ {file = "pillow-10.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5"},
+ {file = "pillow-10.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311"},
+ {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1"},
+ {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757"},
+ {file = "pillow-10.2.0-cp311-cp311-win32.whl", hash = "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068"},
+ {file = "pillow-10.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56"},
+ {file = "pillow-10.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1"},
+ {file = "pillow-10.2.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef"},
+ {file = "pillow-10.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04"},
+ {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f"},
+ {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb"},
+ {file = "pillow-10.2.0-cp312-cp312-win32.whl", hash = "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f"},
+ {file = "pillow-10.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9"},
+ {file = "pillow-10.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48"},
+ {file = "pillow-10.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9"},
+ {file = "pillow-10.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d"},
+ {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6"},
+ {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe"},
+ {file = "pillow-10.2.0-cp38-cp38-win32.whl", hash = "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e"},
+ {file = "pillow-10.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39"},
+ {file = "pillow-10.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67"},
+ {file = "pillow-10.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13"},
+ {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7"},
+ {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591"},
+ {file = "pillow-10.2.0-cp39-cp39-win32.whl", hash = "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516"},
+ {file = "pillow-10.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8"},
+ {file = "pillow-10.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6"},
+ {file = "pillow-10.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"},
+ {file = "pillow-10.2.0.tar.gz", hash = "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e"},
]
[package.extras]
docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"]
+fpx = ["olefile"]
+mic = ["olefile"]
tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
+typing = ["typing-extensions"]
+xmp = ["defusedxml"]
[[package]]
name = "pinecone-client"
@@ -4073,13 +4501,13 @@ testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "posthog"
-version = "3.1.0"
+version = "3.3.1"
description = "Integrate PostHog into any python application."
optional = false
python-versions = "*"
files = [
- {file = "posthog-3.1.0-py2.py3-none-any.whl", hash = "sha256:acd033530bdfc275dce5587f205f62378991ecb9b7cd5479e79c7f4ac575d319"},
- {file = "posthog-3.1.0.tar.gz", hash = "sha256:db17a2c511e18757aec12b6632ddcc1fa318743dad88a4666010467a3d9468da"},
+ {file = "posthog-3.3.1-py2.py3-none-any.whl", hash = "sha256:5f53b232acb680a0389e372db5f786061a18386b8b5324bddcc64eff9fdb319b"},
+ {file = "posthog-3.3.1.tar.gz", hash = "sha256:252cb6ab5cbe7ff002753f34fb647721b3af75034b4a5a631317ebf3db58fe59"},
]
[package.dependencies]
@@ -4173,7 +4601,7 @@ files = [
name = "prompt-toolkit"
version = "3.0.43"
description = "Library for building powerful interactive command lines in Python"
-optional = false
+optional = true
python-versions = ">=3.7.0"
files = [
{file = "prompt_toolkit-3.0.43-py3-none-any.whl", hash = "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6"},
@@ -4202,47 +4630,47 @@ testing = ["google-api-core[grpc] (>=1.31.5)"]
[[package]]
name = "protobuf"
-version = "4.25.1"
+version = "4.25.2"
description = ""
optional = false
python-versions = ">=3.8"
files = [
- {file = "protobuf-4.25.1-cp310-abi3-win32.whl", hash = "sha256:193f50a6ab78a970c9b4f148e7c750cfde64f59815e86f686c22e26b4fe01ce7"},
- {file = "protobuf-4.25.1-cp310-abi3-win_amd64.whl", hash = "sha256:3497c1af9f2526962f09329fd61a36566305e6c72da2590ae0d7d1322818843b"},
- {file = "protobuf-4.25.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:0bf384e75b92c42830c0a679b0cd4d6e2b36ae0cf3dbb1e1dfdda48a244f4bcd"},
- {file = "protobuf-4.25.1-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:0f881b589ff449bf0b931a711926e9ddaad3b35089cc039ce1af50b21a4ae8cb"},
- {file = "protobuf-4.25.1-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:ca37bf6a6d0046272c152eea90d2e4ef34593aaa32e8873fc14c16440f22d4b7"},
- {file = "protobuf-4.25.1-cp38-cp38-win32.whl", hash = "sha256:abc0525ae2689a8000837729eef7883b9391cd6aa7950249dcf5a4ede230d5dd"},
- {file = "protobuf-4.25.1-cp38-cp38-win_amd64.whl", hash = "sha256:1484f9e692091450e7edf418c939e15bfc8fc68856e36ce399aed6889dae8bb0"},
- {file = "protobuf-4.25.1-cp39-cp39-win32.whl", hash = "sha256:8bdbeaddaac52d15c6dce38c71b03038ef7772b977847eb6d374fc86636fa510"},
- {file = "protobuf-4.25.1-cp39-cp39-win_amd64.whl", hash = "sha256:becc576b7e6b553d22cbdf418686ee4daa443d7217999125c045ad56322dda10"},
- {file = "protobuf-4.25.1-py3-none-any.whl", hash = "sha256:a19731d5e83ae4737bb2a089605e636077ac001d18781b3cf489b9546c7c80d6"},
- {file = "protobuf-4.25.1.tar.gz", hash = "sha256:57d65074b4f5baa4ab5da1605c02be90ac20c8b40fb137d6a8df9f416b0d0ce2"},
+ {file = "protobuf-4.25.2-cp310-abi3-win32.whl", hash = "sha256:b50c949608682b12efb0b2717f53256f03636af5f60ac0c1d900df6213910fd6"},
+ {file = "protobuf-4.25.2-cp310-abi3-win_amd64.whl", hash = "sha256:8f62574857ee1de9f770baf04dde4165e30b15ad97ba03ceac65f760ff018ac9"},
+ {file = "protobuf-4.25.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:2db9f8fa64fbdcdc93767d3cf81e0f2aef176284071507e3ede160811502fd3d"},
+ {file = "protobuf-4.25.2-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:10894a2885b7175d3984f2be8d9850712c57d5e7587a2410720af8be56cdaf62"},
+ {file = "protobuf-4.25.2-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:fc381d1dd0516343f1440019cedf08a7405f791cd49eef4ae1ea06520bc1c020"},
+ {file = "protobuf-4.25.2-cp38-cp38-win32.whl", hash = "sha256:33a1aeef4b1927431d1be780e87b641e322b88d654203a9e9d93f218ee359e61"},
+ {file = "protobuf-4.25.2-cp38-cp38-win_amd64.whl", hash = "sha256:47f3de503fe7c1245f6f03bea7e8d3ec11c6c4a2ea9ef910e3221c8a15516d62"},
+ {file = "protobuf-4.25.2-cp39-cp39-win32.whl", hash = "sha256:5e5c933b4c30a988b52e0b7c02641760a5ba046edc5e43d3b94a74c9fc57c1b3"},
+ {file = "protobuf-4.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:d66a769b8d687df9024f2985d5137a337f957a0916cf5464d1513eee96a63ff0"},
+ {file = "protobuf-4.25.2-py3-none-any.whl", hash = "sha256:a8b7a98d4ce823303145bf3c1a8bdb0f2f4642a414b196f04ad9853ed0c8f830"},
+ {file = "protobuf-4.25.2.tar.gz", hash = "sha256:fe599e175cb347efc8ee524bcd4b902d11f7262c0e569ececcb89995c15f0a5e"},
]
[[package]]
name = "psutil"
-version = "5.9.6"
+version = "5.9.7"
description = "Cross-platform lib for process and system monitoring in Python."
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
- {file = "psutil-5.9.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d"},
- {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c"},
- {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28"},
- {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017"},
- {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c"},
- {file = "psutil-5.9.6-cp27-none-win32.whl", hash = "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9"},
- {file = "psutil-5.9.6-cp27-none-win_amd64.whl", hash = "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac"},
- {file = "psutil-5.9.6-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a"},
- {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c"},
- {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4"},
- {file = "psutil-5.9.6-cp36-cp36m-win32.whl", hash = "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602"},
- {file = "psutil-5.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa"},
- {file = "psutil-5.9.6-cp37-abi3-win32.whl", hash = "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c"},
- {file = "psutil-5.9.6-cp37-abi3-win_amd64.whl", hash = "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a"},
- {file = "psutil-5.9.6-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57"},
- {file = "psutil-5.9.6.tar.gz", hash = "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a"},
+ {file = "psutil-5.9.7-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0bd41bf2d1463dfa535942b2a8f0e958acf6607ac0be52265ab31f7923bcd5e6"},
+ {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:5794944462509e49d4d458f4dbfb92c47539e7d8d15c796f141f474010084056"},
+ {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:fe361f743cb3389b8efda21980d93eb55c1f1e3898269bc9a2a1d0bb7b1f6508"},
+ {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:e469990e28f1ad738f65a42dcfc17adaed9d0f325d55047593cb9033a0ab63df"},
+ {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:3c4747a3e2ead1589e647e64aad601981f01b68f9398ddf94d01e3dc0d1e57c7"},
+ {file = "psutil-5.9.7-cp27-none-win32.whl", hash = "sha256:1d4bc4a0148fdd7fd8f38e0498639ae128e64538faa507df25a20f8f7fb2341c"},
+ {file = "psutil-5.9.7-cp27-none-win_amd64.whl", hash = "sha256:4c03362e280d06bbbfcd52f29acd79c733e0af33d707c54255d21029b8b32ba6"},
+ {file = "psutil-5.9.7-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ea36cc62e69a13ec52b2f625c27527f6e4479bca2b340b7a452af55b34fcbe2e"},
+ {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1132704b876e58d277168cd729d64750633d5ff0183acf5b3c986b8466cd0284"},
+ {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe8b7f07948f1304497ce4f4684881250cd859b16d06a1dc4d7941eeb6233bfe"},
+ {file = "psutil-5.9.7-cp36-cp36m-win32.whl", hash = "sha256:b27f8fdb190c8c03914f908a4555159327d7481dac2f01008d483137ef3311a9"},
+ {file = "psutil-5.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:44969859757f4d8f2a9bd5b76eba8c3099a2c8cf3992ff62144061e39ba8568e"},
+ {file = "psutil-5.9.7-cp37-abi3-win32.whl", hash = "sha256:c727ca5a9b2dd5193b8644b9f0c883d54f1248310023b5ad3e92036c5e2ada68"},
+ {file = "psutil-5.9.7-cp37-abi3-win_amd64.whl", hash = "sha256:f37f87e4d73b79e6c5e749440c3113b81d1ee7d26f21c19c47371ddea834f414"},
+ {file = "psutil-5.9.7-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:032f4f2c909818c86cea4fe2cc407f1c0f0cde8e6c6d702b28b8ce0c0d143340"},
+ {file = "psutil-5.9.7.tar.gz", hash = "sha256:3f02134e82cfb5d089fddf20bb2e03fd5cd52395321d1c8458a9e58500ff417c"},
]
[package.extras]
@@ -4342,50 +4770,50 @@ files = [
[[package]]
name = "pulsar-client"
-version = "3.3.0"
+version = "3.4.0"
description = "Apache Pulsar Python client library"
optional = false
python-versions = "*"
files = [
- {file = "pulsar_client-3.3.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:c31afd3e67a044ff93177df89e08febf214cc965e95ede097d9fe8755af00e01"},
- {file = "pulsar_client-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f66982284571674b215324cc26b5c2f7c56c7043113c47a7084cb70d67a8afb"},
- {file = "pulsar_client-3.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fe50a06f81c48a75a9b95c27a6446260039adca71d9face273740de96b2efca"},
- {file = "pulsar_client-3.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d4c46a4b96a6e9919cfe220156d69a2ede8053d9ea1add4ada108abcf2ba9775"},
- {file = "pulsar_client-3.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1e4b5d44b992c9b036286b483f3588c10b89c6047fb59d80c7474445997f4e10"},
- {file = "pulsar_client-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:497a59ac6b650835a3b2c502f53477e5c98e5226998ca3f17c0b0a3eb4d67d08"},
- {file = "pulsar_client-3.3.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:386e78ff52058d881780bae1f6e84ac9434ae0b01a8581755ca8cc0dc844a332"},
- {file = "pulsar_client-3.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e4ecb780df58bcfd3918590bd3ff31ed79bccfbef3a1a60370642eb1e14a9d2"},
- {file = "pulsar_client-3.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ce1e215c252f22a6f26ca5e9076826041a04d88dc213b92c86b524be2774a64"},
- {file = "pulsar_client-3.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:88b0fd5be73a4103986b9dbe3a66468cf8829371e34af87ff8f216e3980f4cbe"},
- {file = "pulsar_client-3.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33656450536d83eed1563ff09692c2c415fb199d88e9ed97d701ca446a119e1b"},
- {file = "pulsar_client-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:ce33de700b06583df8777e139d68cb4b4b3d0a2eac168d74278d8935f357fb10"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-macosx_10_15_universal2.whl", hash = "sha256:7b5dd25cf778d6c980d36c53081e843ea272afe7af4f0ad6394ae9513f94641b"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33c4e6865fda62a2e460f823dce4d49ac2973a4459b8ff99eda5fdd6aaaebf46"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1810ddc623c8de2675d17405ce47057a9a2b92298e708ce4d9564847f5ad904"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8259c3b856eb6deaa1f93dce893ab18d99d36d102da5612c8e97a4fb41b70ab1"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5e7a48b2e505cde758fd51a601b5da0671fa98c9baee38362aaaa3ab2b930c28"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ede264385d47257b2f2b08ecde9181ec5338bea5639cc543d1856f01736778d2"},
- {file = "pulsar_client-3.3.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:0f64c62746ccd5b65a0c505f5f40b9af1f147eb1fa2d8f9c90cd5c8b92dd8597"},
- {file = "pulsar_client-3.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b84a20c9012e3c4ef1b7085acd7467197118c090b378dec27d773fb79d91556"},
- {file = "pulsar_client-3.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4e15fa696e275ccb66d0791fdc19c4dea0420d81349c8055e485b134125e14f"},
- {file = "pulsar_client-3.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:72cbb1bdcba2dd1265296b5ba65331622ee89c16db75edaad46dd7b90c6dd447"},
- {file = "pulsar_client-3.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d54dd12955bf587dd46d9184444af5e853d9da2a14bbfb739ed2c7c3b78ce280"},
- {file = "pulsar_client-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:43f98afdf0334b2b957a4d96f97a1fe8a7f7fd1e2631d40c3f00b4162f396485"},
- {file = "pulsar_client-3.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:efe7c1e6a96daccc522c3567b6847ffa54c13e0f510d9a427b4aeff9fbebe54b"},
- {file = "pulsar_client-3.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f28e94420090fceeb38e23fc744f3edf8710e48314ef5927d2b674a1d1e43ee0"},
- {file = "pulsar_client-3.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42c8f3eaa98e2351805ecb6efb6d5fedf47a314a3ce6af0e05ea1449ea7244ed"},
- {file = "pulsar_client-3.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5e69750f8ae57e55fddf97b459ce0d8b38b2bb85f464a71e871ee6a86d893be7"},
- {file = "pulsar_client-3.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7e147e5ba460c1818bc05254279a885b4e552bcafb8961d40e31f98d5ff46628"},
- {file = "pulsar_client-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:694530af1d6c75fb81456fb509778c1868adee31e997ddece6e21678200182ea"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:ebf99db5244ff69479283b25621b070492acc4bb643d162d86b90387cb6fdb2a"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6cb5d8e1482a8aea758633be23717e0c4bb7dc53784e37915c0048c0382f134"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b30a7592e42c76034e9a8d64d42dd5bab361425f869de562e9ccad698e19cd88"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5963090a78a5644ba25f41da3a6d49ea3f00c972b095baff365916dc246426a"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:419cdcf577f755e3f31bf264300d9ba158325edb2ee9cee555d81ba1909c094e"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:4c93c35ee97307dae153e748b33dcd3d4f06da34bca373321aa2df73f1535705"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:11952fb022ee72debf53b169f4482f9dc5c890be0149ae98779864b3a21f1bd3"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8743c320aa96798d20cafa98ea97a68c4295fc4872c23acd5e012fd36cb06ba"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33571de99cd898349f17978ba62e2b839ea0275fb7067f31bf5f6ebfeae0987d"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a60c03c3e70f018538e7cd3fa84d95e283b610272b744166dbc48960a809fa07"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c47041267b5843ffec54352d842156c279945f3e976d7025ffa89875ff76390"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:49fe4ab04004b476c87ab3ad22fe87346fca564a3e3ca9c0ac58fee45a895d81"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:1e077a4839be3ead3de3f05b4c244269dca2df07f47cea0b90544c7e9dc1642f"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f202b84e1f683d64672dd1971114600ae2e5c3735587286ff9bfb431385f08e8"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c606c04f357341042fa6c75477de7d2204f7ae50aa29c2f74b24e54c85f47f96"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c67b25ede3a578f5a7dc30230e52609ef38191f74b47e5cbdbc98c42df556927"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b7f8211cc9460cdf4d06e4e1cb878689d2aa4a7e4027bd2a2f1419a79ade16a6"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:c5399e9780d6951c69808c0b6175311a966af82fb08addf6e741ae37b1bee7ef"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:a2d6c850b60106dc915d3476a490fba547c6748a5f742b68abd30d1a35355b82"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a52ea8294a9f30eb6f0a2db5dc16e3aad7ff2284f818c48ad3a6b601723be02b"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eeeede40108be12222e009285c971e5b8f6433d9f0f8ef934d6a131585921c4"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9409066c600f2b6f220552c5dfe08aeeabcf07fe0e76367aa5816b2e87a5cf72"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:58e2f886e6dab43e66c3ce990fe96209e55ab46350506829a637b77b74125fb9"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:b57dfa5063b0d9dc7664896c55605eac90753e35e80db5a959d3be2be0ab0d48"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:7704c664aa2c801af4c2d3a58e9d8ffaeef12ce8a0f71712e9187f9a96da856f"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0364db563e27442053bdbb8655e7ffb420f491690bc2c78da5a58bd35c658ad"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3e34de19e0744d8aa3538cb2172076bccd0761b3e94ebadb7bd59765ae3d1ed"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:dc8be41dec8cb052fb1837550f495e9b73a8b3cf85e07157904ec84832758a65"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b49d669bed15b7edb9c936704310d57808f1d01c511b94d866f54fe8ffe1752d"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:88c93e5fbfc349f3967e931f7a908d15fd4fd725ebdd842423ac9cd961fe293f"},
]
[package.dependencies]
certifi = "*"
[package.extras]
-all = ["apache-bookkeeper-client (>=4.16.1)", "fastavro (==1.7.3)", "grpcio (>=1.8.2)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"]
-avro = ["fastavro (==1.7.3)"]
-functions = ["apache-bookkeeper-client (>=4.16.1)", "grpcio (>=1.8.2)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"]
+all = ["apache-bookkeeper-client (>=4.16.1)", "fastavro (>=1.9.2)", "grpcio (>=1.60.0)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"]
+avro = ["fastavro (>=1.9.2)"]
+functions = ["apache-bookkeeper-client (>=4.16.1)", "grpcio (>=1.60.0)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"]
[[package]]
name = "pure-eval"
@@ -4513,13 +4941,13 @@ email = ["email-validator (>=1.0.3)"]
[[package]]
name = "pyflakes"
-version = "3.1.0"
+version = "3.2.0"
description = "passive checker of Python programs"
optional = false
python-versions = ">=3.8"
files = [
- {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"},
- {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"},
+ {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"},
+ {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"},
]
[[package]]
@@ -4538,17 +4966,6 @@ plugins = ["importlib-metadata"]
windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
-name = "pyhumps"
-version = "3.8.0"
-description = "🐫 Convert strings (and dictionary keys) between snake case, camel case and pascal case in Python. Inspired by Humps for Node"
-optional = true
-python-versions = "*"
-files = [
- {file = "pyhumps-3.8.0-py3-none-any.whl", hash = "sha256:060e1954d9069f428232a1adda165db0b9d8dfdce1d265d36df7fbff540acfd6"},
- {file = "pyhumps-3.8.0.tar.gz", hash = "sha256:498026258f7ee1a8e447c2e28526c0bea9407f9a59c03260aee4bd6c04d681a3"},
-]
-
-[[package]]
name = "pylatexenc"
version = "2.10"
description = "Simple LaTeX parser providing latex-to-unicode and unicode-to-latex conversion"
@@ -4574,13 +4991,13 @@ diagrams = ["jinja2", "railroad-diagrams"]
[[package]]
name = "pypdf"
-version = "3.17.2"
+version = "3.17.4"
description = "A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files"
optional = false
python-versions = ">=3.6"
files = [
- {file = "pypdf-3.17.2-py3-none-any.whl", hash = "sha256:e149ed50aa41e04b176246714806cd8d6c6c6d68b528508f849642959041963a"},
- {file = "pypdf-3.17.2.tar.gz", hash = "sha256:d6f077060912f8292d7db3da04f7bf2428ac974781e11eef219193a22120f649"},
+ {file = "pypdf-3.17.4-py3-none-any.whl", hash = "sha256:6aa0f61b33779b64486de3f42835d3668badd48dac4a536aeb87da187a5eacd2"},
+ {file = "pypdf-3.17.4.tar.gz", hash = "sha256:ec96e2e4fc9648ac609d19c00d41e9d606e0ae2ce5a0bbe7691426f5f157166a"},
]
[package.extras]
@@ -4601,6 +5018,20 @@ files = [
]
[[package]]
+name = "pyproject-hooks"
+version = "1.0.0"
+description = "Wrappers to call pyproject.toml-based build backend hooks."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pyproject_hooks-1.0.0-py3-none-any.whl", hash = "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8"},
+ {file = "pyproject_hooks-1.0.0.tar.gz", hash = "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5"},
+]
+
+[package.dependencies]
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+
+[[package]]
name = "pyreadline3"
version = "3.4.1"
description = "A python implementation of GNU readline."
@@ -4625,13 +5056,13 @@ files = [
[[package]]
name = "pytest"
-version = "7.4.3"
+version = "7.4.4"
description = "pytest: simple powerful testing with Python"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"},
- {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"},
+ {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"},
+ {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"},
]
[package.dependencies]
@@ -4813,17 +5244,17 @@ cli = ["click (>=5.0)"]
[[package]]
name = "python-multipart"
-version = "0.0.6"
+version = "0.0.7"
description = "A streaming multipart parser for Python"
optional = false
python-versions = ">=3.7"
files = [
- {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"},
- {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"},
+ {file = "python_multipart-0.0.7-py3-none-any.whl", hash = "sha256:b1fef9a53b74c795e2347daac8c54b252d9e0df9c619712691c1cc8021bd3c49"},
+ {file = "python_multipart-0.0.7.tar.gz", hash = "sha256:288a6c39b06596c1b988bb6794c6fbc80e6c369e35e5062637df256bee0c9af9"},
]
[package.extras]
-dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"]
+dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==2.2.0)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"]
[[package]]
name = "pytz"
@@ -4973,13 +5404,13 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"
[[package]]
name = "referencing"
-version = "0.32.0"
+version = "0.32.1"
description = "JSON Referencing + Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "referencing-0.32.0-py3-none-any.whl", hash = "sha256:bdcd3efb936f82ff86f993093f6da7435c7de69a3b3a5a06678a6050184bee99"},
- {file = "referencing-0.32.0.tar.gz", hash = "sha256:689e64fe121843dcfd57b71933318ef1f91188ffb45367332700a86ac8fd6161"},
+ {file = "referencing-0.32.1-py3-none-any.whl", hash = "sha256:7e4dc12271d8e15612bfe35792f5ea1c40970dadf8624602e33db2758f7ee554"},
+ {file = "referencing-0.32.1.tar.gz", hash = "sha256:3c57da0513e9563eb7e203ebe9bb3a1b509b042016433bd1e45a2853466c3dd3"},
]
[package.dependencies]
@@ -4988,99 +5419,104 @@ rpds-py = ">=0.7.0"
[[package]]
name = "regex"
-version = "2023.10.3"
+version = "2023.12.25"
description = "Alternative regular expression module, to replace re."
optional = false
python-versions = ">=3.7"
files = [
- {file = "regex-2023.10.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4c34d4f73ea738223a094d8e0ffd6d2c1a1b4c175da34d6b0de3d8d69bee6bcc"},
- {file = "regex-2023.10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8f4e49fc3ce020f65411432183e6775f24e02dff617281094ba6ab079ef0915"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cd1bccf99d3ef1ab6ba835308ad85be040e6a11b0977ef7ea8c8005f01a3c29"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81dce2ddc9f6e8f543d94b05d56e70d03a0774d32f6cca53e978dc01e4fc75b8"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c6b4d23c04831e3ab61717a707a5d763b300213db49ca680edf8bf13ab5d91b"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c15ad0aee158a15e17e0495e1e18741573d04eb6da06d8b84af726cfc1ed02ee"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6239d4e2e0b52c8bd38c51b760cd870069f0bdf99700a62cd509d7a031749a55"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4a8bf76e3182797c6b1afa5b822d1d5802ff30284abe4599e1247be4fd6b03be"},
- {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9c727bbcf0065cbb20f39d2b4f932f8fa1631c3e01fcedc979bd4f51fe051c5"},
- {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3ccf2716add72f80714b9a63899b67fa711b654be3fcdd34fa391d2d274ce767"},
- {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:107ac60d1bfdc3edb53be75e2a52aff7481b92817cfdddd9b4519ccf0e54a6ff"},
- {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:00ba3c9818e33f1fa974693fb55d24cdc8ebafcb2e4207680669d8f8d7cca79a"},
- {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f0a47efb1dbef13af9c9a54a94a0b814902e547b7f21acb29434504d18f36e3a"},
- {file = "regex-2023.10.3-cp310-cp310-win32.whl", hash = "sha256:36362386b813fa6c9146da6149a001b7bd063dabc4d49522a1f7aa65b725c7ec"},
- {file = "regex-2023.10.3-cp310-cp310-win_amd64.whl", hash = "sha256:c65a3b5330b54103e7d21cac3f6bf3900d46f6d50138d73343d9e5b2900b2353"},
- {file = "regex-2023.10.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90a79bce019c442604662d17bf69df99090e24cdc6ad95b18b6725c2988a490e"},
- {file = "regex-2023.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c7964c2183c3e6cce3f497e3a9f49d182e969f2dc3aeeadfa18945ff7bdd7051"},
- {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ef80829117a8061f974b2fda8ec799717242353bff55f8a29411794d635d964"},
- {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5addc9d0209a9afca5fc070f93b726bf7003bd63a427f65ef797a931782e7edc"},
- {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c148bec483cc4b421562b4bcedb8e28a3b84fcc8f0aa4418e10898f3c2c0eb9b"},
- {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d1f21af4c1539051049796a0f50aa342f9a27cde57318f2fc41ed50b0dbc4ac"},
- {file = "regex-2023.10.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b9ac09853b2a3e0d0082104036579809679e7715671cfbf89d83c1cb2a30f58"},
- {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ebedc192abbc7fd13c5ee800e83a6df252bec691eb2c4bedc9f8b2e2903f5e2a"},
- {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d8a993c0a0ffd5f2d3bda23d0cd75e7086736f8f8268de8a82fbc4bd0ac6791e"},
- {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:be6b7b8d42d3090b6c80793524fa66c57ad7ee3fe9722b258aec6d0672543fd0"},
- {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4023e2efc35a30e66e938de5aef42b520c20e7eda7bb5fb12c35e5d09a4c43f6"},
- {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0d47840dc05e0ba04fe2e26f15126de7c755496d5a8aae4a08bda4dd8d646c54"},
- {file = "regex-2023.10.3-cp311-cp311-win32.whl", hash = "sha256:9145f092b5d1977ec8c0ab46e7b3381b2fd069957b9862a43bd383e5c01d18c2"},
- {file = "regex-2023.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:b6104f9a46bd8743e4f738afef69b153c4b8b592d35ae46db07fc28ae3d5fb7c"},
- {file = "regex-2023.10.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bff507ae210371d4b1fe316d03433ac099f184d570a1a611e541923f78f05037"},
- {file = "regex-2023.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be5e22bbb67924dea15039c3282fa4cc6cdfbe0cbbd1c0515f9223186fc2ec5f"},
- {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a992f702c9be9c72fa46f01ca6e18d131906a7180950958f766c2aa294d4b41"},
- {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7434a61b158be563c1362d9071358f8ab91b8d928728cd2882af060481244c9e"},
- {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2169b2dcabf4e608416f7f9468737583ce5f0a6e8677c4efbf795ce81109d7c"},
- {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9e908ef5889cda4de038892b9accc36d33d72fb3e12c747e2799a0e806ec841"},
- {file = "regex-2023.10.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12bd4bc2c632742c7ce20db48e0d99afdc05e03f0b4c1af90542e05b809a03d9"},
- {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bc72c231f5449d86d6c7d9cc7cd819b6eb30134bb770b8cfdc0765e48ef9c420"},
- {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bce8814b076f0ce5766dc87d5a056b0e9437b8e0cd351b9a6c4e1134a7dfbda9"},
- {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:ba7cd6dc4d585ea544c1412019921570ebd8a597fabf475acc4528210d7c4a6f"},
- {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b0c7d2f698e83f15228ba41c135501cfe7d5740181d5903e250e47f617eb4292"},
- {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5a8f91c64f390ecee09ff793319f30a0f32492e99f5dc1c72bc361f23ccd0a9a"},
- {file = "regex-2023.10.3-cp312-cp312-win32.whl", hash = "sha256:ad08a69728ff3c79866d729b095872afe1e0557251da4abb2c5faff15a91d19a"},
- {file = "regex-2023.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:39cdf8d141d6d44e8d5a12a8569d5a227f645c87df4f92179bd06e2e2705e76b"},
- {file = "regex-2023.10.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4a3ee019a9befe84fa3e917a2dd378807e423d013377a884c1970a3c2792d293"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76066d7ff61ba6bf3cb5efe2428fc82aac91802844c022d849a1f0f53820502d"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe50b61bab1b1ec260fa7cd91106fa9fece57e6beba05630afe27c71259c59b"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fd88f373cb71e6b59b7fa597e47e518282455c2734fd4306a05ca219a1991b0"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ab05a182c7937fb374f7e946f04fb23a0c0699c0450e9fb02ef567412d2fa3"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dac37cf08fcf2094159922edc7a2784cfcc5c70f8354469f79ed085f0328ebdf"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e54ddd0bb8fb626aa1f9ba7b36629564544954fff9669b15da3610c22b9a0991"},
- {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3367007ad1951fde612bf65b0dffc8fd681a4ab98ac86957d16491400d661302"},
- {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:16f8740eb6dbacc7113e3097b0a36065a02e37b47c936b551805d40340fb9971"},
- {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:f4f2ca6df64cbdd27f27b34f35adb640b5d2d77264228554e68deda54456eb11"},
- {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:39807cbcbe406efca2a233884e169d056c35aa7e9f343d4e78665246a332f597"},
- {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7eece6fbd3eae4a92d7c748ae825cbc1ee41a89bb1c3db05b5578ed3cfcfd7cb"},
- {file = "regex-2023.10.3-cp37-cp37m-win32.whl", hash = "sha256:ce615c92d90df8373d9e13acddd154152645c0dc060871abf6bd43809673d20a"},
- {file = "regex-2023.10.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f649fa32fe734c4abdfd4edbb8381c74abf5f34bc0b3271ce687b23729299ed"},
- {file = "regex-2023.10.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b98b7681a9437262947f41c7fac567c7e1f6eddd94b0483596d320092004533"},
- {file = "regex-2023.10.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:91dc1d531f80c862441d7b66c4505cd6ea9d312f01fb2f4654f40c6fdf5cc37a"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82fcc1f1cc3ff1ab8a57ba619b149b907072e750815c5ba63e7aa2e1163384a4"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7979b834ec7a33aafae34a90aad9f914c41fd6eaa8474e66953f3f6f7cbd4368"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef71561f82a89af6cfcbee47f0fabfdb6e63788a9258e913955d89fdd96902ab"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd829712de97753367153ed84f2de752b86cd1f7a88b55a3a775eb52eafe8a94"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00e871d83a45eee2f8688d7e6849609c2ca2a04a6d48fba3dff4deef35d14f07"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:706e7b739fdd17cb89e1fbf712d9dc21311fc2333f6d435eac2d4ee81985098c"},
- {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cc3f1c053b73f20c7ad88b0d1d23be7e7b3901229ce89f5000a8399746a6e039"},
- {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6f85739e80d13644b981a88f529d79c5bdf646b460ba190bffcaf6d57b2a9863"},
- {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:741ba2f511cc9626b7561a440f87d658aabb3d6b744a86a3c025f866b4d19e7f"},
- {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e77c90ab5997e85901da85131fd36acd0ed2221368199b65f0d11bca44549711"},
- {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:979c24cbefaf2420c4e377ecd1f165ea08cc3d1fbb44bdc51bccbbf7c66a2cb4"},
- {file = "regex-2023.10.3-cp38-cp38-win32.whl", hash = "sha256:58837f9d221744d4c92d2cf7201c6acd19623b50c643b56992cbd2b745485d3d"},
- {file = "regex-2023.10.3-cp38-cp38-win_amd64.whl", hash = "sha256:c55853684fe08d4897c37dfc5faeff70607a5f1806c8be148f1695be4a63414b"},
- {file = "regex-2023.10.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2c54e23836650bdf2c18222c87f6f840d4943944146ca479858404fedeb9f9af"},
- {file = "regex-2023.10.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:69c0771ca5653c7d4b65203cbfc5e66db9375f1078689459fe196fe08b7b4930"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ac965a998e1388e6ff2e9781f499ad1eaa41e962a40d11c7823c9952c77123e"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c0e8fae5b27caa34177bdfa5a960c46ff2f78ee2d45c6db15ae3f64ecadde14"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c56c3d47da04f921b73ff9415fbaa939f684d47293f071aa9cbb13c94afc17d"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ef1e014eed78ab650bef9a6a9cbe50b052c0aebe553fb2881e0453717573f52"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d29338556a59423d9ff7b6eb0cb89ead2b0875e08fe522f3e068b955c3e7b59b"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9c6d0ced3c06d0f183b73d3c5920727268d2201aa0fe6d55c60d68c792ff3588"},
- {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:994645a46c6a740ee8ce8df7911d4aee458d9b1bc5639bc968226763d07f00fa"},
- {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:66e2fe786ef28da2b28e222c89502b2af984858091675044d93cb50e6f46d7af"},
- {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:11175910f62b2b8c055f2b089e0fedd694fe2be3941b3e2633653bc51064c528"},
- {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:06e9abc0e4c9ab4779c74ad99c3fc10d3967d03114449acc2c2762ad4472b8ca"},
- {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fb02e4257376ae25c6dd95a5aec377f9b18c09be6ebdefa7ad209b9137b73d48"},
- {file = "regex-2023.10.3-cp39-cp39-win32.whl", hash = "sha256:3b2c3502603fab52d7619b882c25a6850b766ebd1b18de3df23b2f939360e1bd"},
- {file = "regex-2023.10.3-cp39-cp39-win_amd64.whl", hash = "sha256:adbccd17dcaff65704c856bd29951c58a1bd4b2b0f8ad6b826dbd543fe740988"},
- {file = "regex-2023.10.3.tar.gz", hash = "sha256:3fef4f844d2290ee0ba57addcec17eec9e3df73f10a2748485dfd6a3a188cc0f"},
+ {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"},
+ {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"},
+ {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"},
+ {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"},
+ {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"},
+ {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"},
+ {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"},
+ {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"},
+ {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"},
+ {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"},
+ {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"},
+ {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"},
+ {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"},
+ {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"},
+ {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"},
+ {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"},
+ {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"},
+ {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"},
+ {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"},
+ {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"},
+ {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"},
+ {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"},
+ {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"},
+ {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"},
+ {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"},
+ {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"},
+ {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"},
+ {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"},
+ {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"},
+ {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"},
+ {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"},
+ {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"},
+ {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"},
+ {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"},
+ {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"},
+ {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"},
+ {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"},
+ {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"},
+ {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"},
+ {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"},
+ {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"},
+ {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"},
+ {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"},
+ {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"},
+ {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"},
+ {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"},
+ {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"},
+ {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"},
+ {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"},
+ {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"},
+ {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"},
+ {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"},
+ {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"},
+ {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"},
+ {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"},
+ {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"},
+ {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"},
+ {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"},
+ {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"},
+ {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"},
+ {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"},
+ {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"},
+ {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"},
+ {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"},
+ {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"},
+ {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"},
+ {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"},
+ {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"},
+ {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"},
]
[[package]]
@@ -5105,111 +5541,129 @@ socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
+name = "requests-oauthlib"
+version = "1.3.1"
+description = "OAuthlib authentication support for Requests."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"},
+ {file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"},
+]
+
+[package.dependencies]
+oauthlib = ">=3.0.0"
+requests = ">=2.0.0"
+
+[package.extras]
+rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
+
+[[package]]
name = "rpds-py"
-version = "0.13.2"
+version = "0.17.1"
description = "Python bindings to Rust's persistent data structures (rpds)"
optional = false
python-versions = ">=3.8"
files = [
- {file = "rpds_py-0.13.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1ceebd0ae4f3e9b2b6b553b51971921853ae4eebf3f54086be0565d59291e53d"},
- {file = "rpds_py-0.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:46e1ed994a0920f350a4547a38471217eb86f57377e9314fbaaa329b71b7dfe3"},
- {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee353bb51f648924926ed05e0122b6a0b1ae709396a80eb583449d5d477fcdf7"},
- {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:530190eb0cd778363bbb7596612ded0bb9fef662daa98e9d92a0419ab27ae914"},
- {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d311e44dd16d2434d5506d57ef4d7036544fc3c25c14b6992ef41f541b10fb"},
- {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e72f750048b32d39e87fc85c225c50b2a6715034848dbb196bf3348aa761fa1"},
- {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db09b98c7540df69d4b47218da3fbd7cb466db0fb932e971c321f1c76f155266"},
- {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2ac26f50736324beb0282c819668328d53fc38543fa61eeea2c32ea8ea6eab8d"},
- {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:12ecf89bd54734c3c2c79898ae2021dca42750c7bcfb67f8fb3315453738ac8f"},
- {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a44c8440183b43167fd1a0819e8356692bf5db1ad14ce140dbd40a1485f2dea"},
- {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bcef4f2d3dc603150421de85c916da19471f24d838c3c62a4f04c1eb511642c1"},
- {file = "rpds_py-0.13.2-cp310-none-win32.whl", hash = "sha256:ee6faebb265e28920a6f23a7d4c362414b3f4bb30607141d718b991669e49ddc"},
- {file = "rpds_py-0.13.2-cp310-none-win_amd64.whl", hash = "sha256:ac96d67b37f28e4b6ecf507c3405f52a40658c0a806dffde624a8fcb0314d5fd"},
- {file = "rpds_py-0.13.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:b5f6328e8e2ae8238fc767703ab7b95785521c42bb2b8790984e3477d7fa71ad"},
- {file = "rpds_py-0.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:729408136ef8d45a28ee9a7411917c9e3459cf266c7e23c2f7d4bb8ef9e0da42"},
- {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65cfed9c807c27dee76407e8bb29e6f4e391e436774bcc769a037ff25ad8646e"},
- {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aefbdc934115d2f9278f153952003ac52cd2650e7313750390b334518c589568"},
- {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d48db29bd47814671afdd76c7652aefacc25cf96aad6daefa82d738ee87461e2"},
- {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3c55d7f2d817183d43220738270efd3ce4e7a7b7cbdaefa6d551ed3d6ed89190"},
- {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6aadae3042f8e6db3376d9e91f194c606c9a45273c170621d46128f35aef7cd0"},
- {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5feae2f9aa7270e2c071f488fab256d768e88e01b958f123a690f1cc3061a09c"},
- {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:51967a67ea0d7b9b5cd86036878e2d82c0b6183616961c26d825b8c994d4f2c8"},
- {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d0c10d803549427f427085ed7aebc39832f6e818a011dcd8785e9c6a1ba9b3e"},
- {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:603d5868f7419081d616dab7ac3cfa285296735e7350f7b1e4f548f6f953ee7d"},
- {file = "rpds_py-0.13.2-cp311-none-win32.whl", hash = "sha256:b8996ffb60c69f677245f5abdbcc623e9442bcc91ed81b6cd6187129ad1fa3e7"},
- {file = "rpds_py-0.13.2-cp311-none-win_amd64.whl", hash = "sha256:5379e49d7e80dca9811b36894493d1c1ecb4c57de05c36f5d0dd09982af20211"},
- {file = "rpds_py-0.13.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8a776a29b77fe0cc28fedfd87277b0d0f7aa930174b7e504d764e0b43a05f381"},
- {file = "rpds_py-0.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2a1472956c5bcc49fb0252b965239bffe801acc9394f8b7c1014ae9258e4572b"},
- {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f252dfb4852a527987a9156cbcae3022a30f86c9d26f4f17b8c967d7580d65d2"},
- {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f0d320e70b6b2300ff6029e234e79fe44e9dbbfc7b98597ba28e054bd6606a57"},
- {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ade2ccb937060c299ab0dfb2dea3d2ddf7e098ed63ee3d651ebfc2c8d1e8632a"},
- {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9d121be0217787a7d59a5c6195b0842d3f701007333426e5154bf72346aa658"},
- {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fa6bd071ec6d90f6e7baa66ae25820d57a8ab1b0a3c6d3edf1834d4b26fafa2"},
- {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c918621ee0a3d1fe61c313f2489464f2ae3d13633e60f520a8002a5e910982ee"},
- {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:25b28b3d33ec0a78e944aaaed7e5e2a94ac811bcd68b557ca48a0c30f87497d2"},
- {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:31e220a040b89a01505128c2f8a59ee74732f666439a03e65ccbf3824cdddae7"},
- {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:15253fff410873ebf3cfba1cc686a37711efcd9b8cb30ea21bb14a973e393f60"},
- {file = "rpds_py-0.13.2-cp312-none-win32.whl", hash = "sha256:b981a370f8f41c4024c170b42fbe9e691ae2dbc19d1d99151a69e2c84a0d194d"},
- {file = "rpds_py-0.13.2-cp312-none-win_amd64.whl", hash = "sha256:4c4e314d36d4f31236a545696a480aa04ea170a0b021e9a59ab1ed94d4c3ef27"},
- {file = "rpds_py-0.13.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:80e5acb81cb49fd9f2d5c08f8b74ffff14ee73b10ca88297ab4619e946bcb1e1"},
- {file = "rpds_py-0.13.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:efe093acc43e869348f6f2224df7f452eab63a2c60a6c6cd6b50fd35c4e075ba"},
- {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c2a61c0e4811012b0ba9f6cdcb4437865df5d29eab5d6018ba13cee1c3064a0"},
- {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:751758d9dd04d548ec679224cc00e3591f5ebf1ff159ed0d4aba6a0746352452"},
- {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ba8858933f0c1a979781272a5f65646fca8c18c93c99c6ddb5513ad96fa54b1"},
- {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bfdfbe6a36bc3059fff845d64c42f2644cf875c65f5005db54f90cdfdf1df815"},
- {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa0379c1935c44053c98826bc99ac95f3a5355675a297ac9ce0dfad0ce2d50ca"},
- {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5593855b5b2b73dd8413c3fdfa5d95b99d657658f947ba2c4318591e745d083"},
- {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2a7bef6977043673750a88da064fd513f89505111014b4e00fbdd13329cd4e9a"},
- {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:3ab96754d23372009638a402a1ed12a27711598dd49d8316a22597141962fe66"},
- {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e06cfea0ece444571d24c18ed465bc93afb8c8d8d74422eb7026662f3d3f779b"},
- {file = "rpds_py-0.13.2-cp38-none-win32.whl", hash = "sha256:5493569f861fb7b05af6d048d00d773c6162415ae521b7010197c98810a14cab"},
- {file = "rpds_py-0.13.2-cp38-none-win_amd64.whl", hash = "sha256:b07501b720cf060c5856f7b5626e75b8e353b5f98b9b354a21eb4bfa47e421b1"},
- {file = "rpds_py-0.13.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:881df98f0a8404d32b6de0fd33e91c1b90ed1516a80d4d6dc69d414b8850474c"},
- {file = "rpds_py-0.13.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d79c159adea0f1f4617f54aa156568ac69968f9ef4d1e5fefffc0a180830308e"},
- {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38d4f822ee2f338febcc85aaa2547eb5ba31ba6ff68d10b8ec988929d23bb6b4"},
- {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5d75d6d220d55cdced2f32cc22f599475dbe881229aeddba6c79c2e9df35a2b3"},
- {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d97e9ae94fb96df1ee3cb09ca376c34e8a122f36927230f4c8a97f469994bff"},
- {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67a429520e97621a763cf9b3ba27574779c4e96e49a27ff8a1aa99ee70beb28a"},
- {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:188435794405c7f0573311747c85a96b63c954a5f2111b1df8018979eca0f2f0"},
- {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:38f9bf2ad754b4a45b8210a6c732fe876b8a14e14d5992a8c4b7c1ef78740f53"},
- {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6ba2cb7d676e9415b9e9ac7e2aae401dc1b1e666943d1f7bc66223d3d73467b"},
- {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:eaffbd8814bb1b5dc3ea156a4c5928081ba50419f9175f4fc95269e040eff8f0"},
- {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a4c1058cdae6237d97af272b326e5f78ee7ee3bbffa6b24b09db4d828810468"},
- {file = "rpds_py-0.13.2-cp39-none-win32.whl", hash = "sha256:b5267feb19070bef34b8dea27e2b504ebd9d31748e3ecacb3a4101da6fcb255c"},
- {file = "rpds_py-0.13.2-cp39-none-win_amd64.whl", hash = "sha256:ddf23960cb42b69bce13045d5bc66f18c7d53774c66c13f24cf1b9c144ba3141"},
- {file = "rpds_py-0.13.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:97163a1ab265a1073a6372eca9f4eeb9f8c6327457a0b22ddfc4a17dcd613e74"},
- {file = "rpds_py-0.13.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:25ea41635d22b2eb6326f58e608550e55d01df51b8a580ea7e75396bafbb28e9"},
- {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d59d4d451ba77f08cb4cd9268dec07be5bc65f73666302dbb5061989b17198"},
- {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7c564c58cf8f248fe859a4f0fe501b050663f3d7fbc342172f259124fb59933"},
- {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61dbc1e01dc0c5875da2f7ae36d6e918dc1b8d2ce04e871793976594aad8a57a"},
- {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdb82eb60d31b0c033a8e8ee9f3fc7dfbaa042211131c29da29aea8531b4f18f"},
- {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d204957169f0b3511fb95395a9da7d4490fb361763a9f8b32b345a7fe119cb45"},
- {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c45008ca79bad237cbc03c72bc5205e8c6f66403773929b1b50f7d84ef9e4d07"},
- {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:79bf58c08f0756adba691d480b5a20e4ad23f33e1ae121584cf3a21717c36dfa"},
- {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e86593bf8637659e6a6ed58854b6c87ec4e9e45ee8a4adfd936831cef55c2d21"},
- {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d329896c40d9e1e5c7715c98529e4a188a1f2df51212fd65102b32465612b5dc"},
- {file = "rpds_py-0.13.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4a5375c5fff13f209527cd886dc75394f040c7d1ecad0a2cb0627f13ebe78a12"},
- {file = "rpds_py-0.13.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:06d218e4464d31301e943b65b2c6919318ea6f69703a351961e1baaf60347276"},
- {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1f41d32a2ddc5a94df4b829b395916a4b7f103350fa76ba6de625fcb9e773ac"},
- {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6bc568b05e02cd612be53900c88aaa55012e744930ba2eeb56279db4c6676eb3"},
- {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d94d78418203904730585efa71002286ac4c8ac0689d0eb61e3c465f9e608ff"},
- {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bed0252c85e21cf73d2d033643c945b460d6a02fc4a7d644e3b2d6f5f2956c64"},
- {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:244e173bb6d8f3b2f0c4d7370a1aa341f35da3e57ffd1798e5b2917b91731fd3"},
- {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7f55cd9cf1564b7b03f238e4c017ca4794c05b01a783e9291065cb2858d86ce4"},
- {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:f03a1b3a4c03e3e0161642ac5367f08479ab29972ea0ffcd4fa18f729cd2be0a"},
- {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:f5f4424cb87a20b016bfdc157ff48757b89d2cc426256961643d443c6c277007"},
- {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c82bbf7e03748417c3a88c1b0b291288ce3e4887a795a3addaa7a1cfd9e7153e"},
- {file = "rpds_py-0.13.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c0095b8aa3e432e32d372e9a7737e65b58d5ed23b9620fea7cb81f17672f1fa1"},
- {file = "rpds_py-0.13.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:4c2d26aa03d877c9730bf005621c92da263523a1e99247590abbbe252ccb7824"},
- {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96f2975fb14f39c5fe75203f33dd3010fe37d1c4e33177feef1107b5ced750e3"},
- {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4dcc5ee1d0275cb78d443fdebd0241e58772a354a6d518b1d7af1580bbd2c4e8"},
- {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61d42d2b08430854485135504f672c14d4fc644dd243a9c17e7c4e0faf5ed07e"},
- {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d3a61e928feddc458a55110f42f626a2a20bea942ccedb6fb4cee70b4830ed41"},
- {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7de12b69d95072394998c622cfd7e8cea8f560db5fca6a62a148f902a1029f8b"},
- {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:87a90f5545fd61f6964e65eebde4dc3fa8660bb7d87adb01d4cf17e0a2b484ad"},
- {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:9c95a1a290f9acf7a8f2ebbdd183e99215d491beea52d61aa2a7a7d2c618ddc6"},
- {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:35f53c76a712e323c779ca39b9a81b13f219a8e3bc15f106ed1e1462d56fcfe9"},
- {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:96fb0899bb2ab353f42e5374c8f0789f54e0a94ef2f02b9ac7149c56622eaf31"},
- {file = "rpds_py-0.13.2.tar.gz", hash = "sha256:f8eae66a1304de7368932b42d801c67969fd090ddb1a7a24f27b435ed4bed68f"},
+ {file = "rpds_py-0.17.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4128980a14ed805e1b91a7ed551250282a8ddf8201a4e9f8f5b7e6225f54170d"},
+ {file = "rpds_py-0.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ff1dcb8e8bc2261a088821b2595ef031c91d499a0c1b031c152d43fe0a6ecec8"},
+ {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d65e6b4f1443048eb7e833c2accb4fa7ee67cc7d54f31b4f0555b474758bee55"},
+ {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a71169d505af63bb4d20d23a8fbd4c6ce272e7bce6cc31f617152aa784436f29"},
+ {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:436474f17733c7dca0fbf096d36ae65277e8645039df12a0fa52445ca494729d"},
+ {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10162fe3f5f47c37ebf6d8ff5a2368508fe22007e3077bf25b9c7d803454d921"},
+ {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:720215373a280f78a1814becb1312d4e4d1077b1202a56d2b0815e95ccb99ce9"},
+ {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70fcc6c2906cfa5c6a552ba7ae2ce64b6c32f437d8f3f8eea49925b278a61453"},
+ {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:91e5a8200e65aaac342a791272c564dffcf1281abd635d304d6c4e6b495f29dc"},
+ {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:99f567dae93e10be2daaa896e07513dd4bf9c2ecf0576e0533ac36ba3b1d5394"},
+ {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24e4900a6643f87058a27320f81336d527ccfe503984528edde4bb660c8c8d59"},
+ {file = "rpds_py-0.17.1-cp310-none-win32.whl", hash = "sha256:0bfb09bf41fe7c51413f563373e5f537eaa653d7adc4830399d4e9bdc199959d"},
+ {file = "rpds_py-0.17.1-cp310-none-win_amd64.whl", hash = "sha256:20de7b7179e2031a04042e85dc463a93a82bc177eeba5ddd13ff746325558aa6"},
+ {file = "rpds_py-0.17.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:65dcf105c1943cba45d19207ef51b8bc46d232a381e94dd38719d52d3980015b"},
+ {file = "rpds_py-0.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:01f58a7306b64e0a4fe042047dd2b7d411ee82e54240284bab63e325762c1147"},
+ {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:071bc28c589b86bc6351a339114fb7a029f5cddbaca34103aa573eba7b482382"},
+ {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae35e8e6801c5ab071b992cb2da958eee76340e6926ec693b5ff7d6381441745"},
+ {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149c5cd24f729e3567b56e1795f74577aa3126c14c11e457bec1b1c90d212e38"},
+ {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e796051f2070f47230c745d0a77a91088fbee2cc0502e9b796b9c6471983718c"},
+ {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e820ee1004327609b28db8307acc27f5f2e9a0b185b2064c5f23e815f248f8"},
+ {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1957a2ab607f9added64478a6982742eb29f109d89d065fa44e01691a20fc20a"},
+ {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8587fd64c2a91c33cdc39d0cebdaf30e79491cc029a37fcd458ba863f8815383"},
+ {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4dc889a9d8a34758d0fcc9ac86adb97bab3fb7f0c4d29794357eb147536483fd"},
+ {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2953937f83820376b5979318840f3ee47477d94c17b940fe31d9458d79ae7eea"},
+ {file = "rpds_py-0.17.1-cp311-none-win32.whl", hash = "sha256:1bfcad3109c1e5ba3cbe2f421614e70439f72897515a96c462ea657261b96518"},
+ {file = "rpds_py-0.17.1-cp311-none-win_amd64.whl", hash = "sha256:99da0a4686ada4ed0f778120a0ea8d066de1a0a92ab0d13ae68492a437db78bf"},
+ {file = "rpds_py-0.17.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1dc29db3900cb1bb40353772417800f29c3d078dbc8024fd64655a04ee3c4bdf"},
+ {file = "rpds_py-0.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82ada4a8ed9e82e443fcef87e22a3eed3654dd3adf6e3b3a0deb70f03e86142a"},
+ {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d36b2b59e8cc6e576f8f7b671e32f2ff43153f0ad6d0201250a7c07f25d570e"},
+ {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3677fcca7fb728c86a78660c7fb1b07b69b281964673f486ae72860e13f512ad"},
+ {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:516fb8c77805159e97a689e2f1c80655c7658f5af601c34ffdb916605598cda2"},
+ {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df3b6f45ba4515632c5064e35ca7f31d51d13d1479673185ba8f9fefbbed58b9"},
+ {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a967dd6afda7715d911c25a6ba1517975acd8d1092b2f326718725461a3d33f9"},
+ {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dbbb95e6fc91ea3102505d111b327004d1c4ce98d56a4a02e82cd451f9f57140"},
+ {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02866e060219514940342a1f84303a1ef7a1dad0ac311792fbbe19b521b489d2"},
+ {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2528ff96d09f12e638695f3a2e0c609c7b84c6df7c5ae9bfeb9252b6fa686253"},
+ {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd345a13ce06e94c753dab52f8e71e5252aec1e4f8022d24d56decd31e1b9b23"},
+ {file = "rpds_py-0.17.1-cp312-none-win32.whl", hash = "sha256:2a792b2e1d3038daa83fa474d559acfd6dc1e3650ee93b2662ddc17dbff20ad1"},
+ {file = "rpds_py-0.17.1-cp312-none-win_amd64.whl", hash = "sha256:292f7344a3301802e7c25c53792fae7d1593cb0e50964e7bcdcc5cf533d634e3"},
+ {file = "rpds_py-0.17.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:8ffe53e1d8ef2520ebcf0c9fec15bb721da59e8ef283b6ff3079613b1e30513d"},
+ {file = "rpds_py-0.17.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4341bd7579611cf50e7b20bb8c2e23512a3dc79de987a1f411cb458ab670eb90"},
+ {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4eb548daf4836e3b2c662033bfbfc551db58d30fd8fe660314f86bf8510b93"},
+ {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b686f25377f9c006acbac63f61614416a6317133ab7fafe5de5f7dc8a06d42eb"},
+ {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e21b76075c01d65d0f0f34302b5a7457d95721d5e0667aea65e5bb3ab415c25"},
+ {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b86b21b348f7e5485fae740d845c65a880f5d1eda1e063bc59bef92d1f7d0c55"},
+ {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f175e95a197f6a4059b50757a3dca33b32b61691bdbd22c29e8a8d21d3914cae"},
+ {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1701fc54460ae2e5efc1dd6350eafd7a760f516df8dbe51d4a1c79d69472fbd4"},
+ {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9051e3d2af8f55b42061603e29e744724cb5f65b128a491446cc029b3e2ea896"},
+ {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:7450dbd659fed6dd41d1a7d47ed767e893ba402af8ae664c157c255ec6067fde"},
+ {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5a024fa96d541fd7edaa0e9d904601c6445e95a729a2900c5aec6555fe921ed6"},
+ {file = "rpds_py-0.17.1-cp38-none-win32.whl", hash = "sha256:da1ead63368c04a9bded7904757dfcae01eba0e0f9bc41d3d7f57ebf1c04015a"},
+ {file = "rpds_py-0.17.1-cp38-none-win_amd64.whl", hash = "sha256:841320e1841bb53fada91c9725e766bb25009cfd4144e92298db296fb6c894fb"},
+ {file = "rpds_py-0.17.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:f6c43b6f97209e370124baf2bf40bb1e8edc25311a158867eb1c3a5d449ebc7a"},
+ {file = "rpds_py-0.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7d63ec01fe7c76c2dbb7e972fece45acbb8836e72682bde138e7e039906e2c"},
+ {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81038ff87a4e04c22e1d81f947c6ac46f122e0c80460b9006e6517c4d842a6ec"},
+ {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:810685321f4a304b2b55577c915bece4c4a06dfe38f6e62d9cc1d6ca8ee86b99"},
+ {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25f071737dae674ca8937a73d0f43f5a52e92c2d178330b4c0bb6ab05586ffa6"},
+ {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa5bfb13f1e89151ade0eb812f7b0d7a4d643406caaad65ce1cbabe0a66d695f"},
+ {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfe07308b311a8293a0d5ef4e61411c5c20f682db6b5e73de6c7c8824272c256"},
+ {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a000133a90eea274a6f28adc3084643263b1e7c1a5a66eb0a0a7a36aa757ed74"},
+ {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d0e8a6434a3fbf77d11448c9c25b2f25244226cfbec1a5159947cac5b8c5fa4"},
+ {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:efa767c220d94aa4ac3a6dd3aeb986e9f229eaf5bce92d8b1b3018d06bed3772"},
+ {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dbc56680ecf585a384fbd93cd42bc82668b77cb525343170a2d86dafaed2a84b"},
+ {file = "rpds_py-0.17.1-cp39-none-win32.whl", hash = "sha256:270987bc22e7e5a962b1094953ae901395e8c1e1e83ad016c5cfcfff75a15a3f"},
+ {file = "rpds_py-0.17.1-cp39-none-win_amd64.whl", hash = "sha256:2a7b2f2f56a16a6d62e55354dd329d929560442bd92e87397b7a9586a32e3e76"},
+ {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3264e3e858de4fc601741498215835ff324ff2482fd4e4af61b46512dd7fc83"},
+ {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f2f3b28b40fddcb6c1f1f6c88c6f3769cd933fa493ceb79da45968a21dccc920"},
+ {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9584f8f52010295a4a417221861df9bea4c72d9632562b6e59b3c7b87a1522b7"},
+ {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c64602e8be701c6cfe42064b71c84ce62ce66ddc6422c15463fd8127db3d8066"},
+ {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:060f412230d5f19fc8c8b75f315931b408d8ebf56aec33ef4168d1b9e54200b1"},
+ {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9412abdf0ba70faa6e2ee6c0cc62a8defb772e78860cef419865917d86c7342"},
+ {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9737bdaa0ad33d34c0efc718741abaafce62fadae72c8b251df9b0c823c63b22"},
+ {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9f0e4dc0f17dcea4ab9d13ac5c666b6b5337042b4d8f27e01b70fae41dd65c57"},
+ {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1db228102ab9d1ff4c64148c96320d0be7044fa28bd865a9ce628ce98da5973d"},
+ {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:d8bbd8e56f3ba25a7d0cf980fc42b34028848a53a0e36c9918550e0280b9d0b6"},
+ {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:be22ae34d68544df293152b7e50895ba70d2a833ad9566932d750d3625918b82"},
+ {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bf046179d011e6114daf12a534d874958b039342b347348a78b7cdf0dd9d6041"},
+ {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:1a746a6d49665058a5896000e8d9d2f1a6acba8a03b389c1e4c06e11e0b7f40d"},
+ {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0b8bf5b8db49d8fd40f54772a1dcf262e8be0ad2ab0206b5a2ec109c176c0a4"},
+ {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7f4cb1f173385e8a39c29510dd11a78bf44e360fb75610594973f5ea141028b"},
+ {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7fbd70cb8b54fe745301921b0816c08b6d917593429dfc437fd024b5ba713c58"},
+ {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bdf1303df671179eaf2cb41e8515a07fc78d9d00f111eadbe3e14262f59c3d0"},
+ {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad059a4bd14c45776600d223ec194e77db6c20255578bb5bcdd7c18fd169361"},
+ {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3664d126d3388a887db44c2e293f87d500c4184ec43d5d14d2d2babdb4c64cad"},
+ {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:698ea95a60c8b16b58be9d854c9f993c639f5c214cf9ba782eca53a8789d6b19"},
+ {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:c3d2010656999b63e628a3c694f23020322b4178c450dc478558a2b6ef3cb9bb"},
+ {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:938eab7323a736533f015e6069a7d53ef2dcc841e4e533b782c2bfb9fb12d84b"},
+ {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e626b365293a2142a62b9a614e1f8e331b28f3ca57b9f05ebbf4cf2a0f0bdc5"},
+ {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:380e0df2e9d5d5d339803cfc6d183a5442ad7ab3c63c2a0982e8c824566c5ccc"},
+ {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b760a56e080a826c2e5af09002c1a037382ed21d03134eb6294812dda268c811"},
+ {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5576ee2f3a309d2bb403ec292d5958ce03953b0e57a11d224c1f134feaf8c40f"},
+ {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3c3461ebb4c4f1bbc70b15d20b565759f97a5aaf13af811fcefc892e9197ba"},
+ {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:637b802f3f069a64436d432117a7e58fab414b4e27a7e81049817ae94de45d8d"},
+ {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffee088ea9b593cc6160518ba9bd319b5475e5f3e578e4552d63818773c6f56a"},
+ {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ac732390d529d8469b831949c78085b034bff67f584559340008d0f6041a049"},
+ {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:93432e747fb07fa567ad9cc7aaadd6e29710e515aabf939dfbed8046041346c6"},
+ {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7b7d9ca34542099b4e185b3c2a2b2eda2e318a7dbde0b0d83357a6d4421b5296"},
+ {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:0387ce69ba06e43df54e43968090f3626e231e4bc9150e4c3246947567695f68"},
+ {file = "rpds_py-0.17.1.tar.gz", hash = "sha256:0210b2668f24c078307260bf88bdac9d6f1093635df5123789bfee4d8d7fc8e7"},
]
[[package]]
@@ -5228,13 +5682,13 @@ pyasn1 = ">=0.1.3"
[[package]]
name = "s3transfer"
-version = "0.8.2"
+version = "0.10.0"
description = "An Amazon S3 Transfer Manager"
optional = false
-python-versions = ">= 3.7"
+python-versions = ">= 3.8"
files = [
- {file = "s3transfer-0.8.2-py3-none-any.whl", hash = "sha256:c9e56cbe88b28d8e197cf841f1f0c130f246595e77ae5b5a05b69fe7cb83de76"},
- {file = "s3transfer-0.8.2.tar.gz", hash = "sha256:368ac6876a9e9ed91f6bc86581e319be08188dc60d50e0d56308ed5765446283"},
+ {file = "s3transfer-0.10.0-py3-none-any.whl", hash = "sha256:3cdb40f5cfa6966e812209d0994f2a4709b561c88e90cf00c2696d2df4e56b2e"},
+ {file = "s3transfer-0.10.0.tar.gz", hash = "sha256:d0c8bbf672d5eebbe4e57945e23b972d963f07d82f661cabf678a5c88831595b"},
]
[package.dependencies]
@@ -5261,14 +5715,59 @@ trio-websocket = ">=0.9,<1.0"
urllib3 = {version = ">=1.26,<3", extras = ["socks"]}
[[package]]
+name = "sentry-sdk"
+version = "1.40.4"
+description = "Python client for Sentry (https://sentry.io)"
+optional = false
+python-versions = "*"
+files = [
+ {file = "sentry-sdk-1.40.4.tar.gz", hash = "sha256:657abae98b0050a0316f0873d7149f951574ae6212f71d2e3a1c4c88f62d6456"},
+ {file = "sentry_sdk-1.40.4-py2.py3-none-any.whl", hash = "sha256:ac5cf56bb897ec47135d239ddeedf7c1c12d406fb031a4c0caa07399ed014d7e"},
+]
+
+[package.dependencies]
+certifi = "*"
+urllib3 = {version = ">=1.26.11", markers = "python_version >= \"3.6\""}
+
+[package.extras]
+aiohttp = ["aiohttp (>=3.5)"]
+arq = ["arq (>=0.23)"]
+asyncpg = ["asyncpg (>=0.23)"]
+beam = ["apache-beam (>=2.12)"]
+bottle = ["bottle (>=0.12.13)"]
+celery = ["celery (>=3)"]
+chalice = ["chalice (>=1.16.0)"]
+clickhouse-driver = ["clickhouse-driver (>=0.2.0)"]
+django = ["django (>=1.8)"]
+falcon = ["falcon (>=1.4)"]
+fastapi = ["fastapi (>=0.79.0)"]
+flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"]
+grpcio = ["grpcio (>=1.21.1)"]
+httpx = ["httpx (>=0.16.0)"]
+huey = ["huey (>=2)"]
+loguru = ["loguru (>=0.5)"]
+opentelemetry = ["opentelemetry-distro (>=0.35b0)"]
+opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"]
+pure-eval = ["asttokens", "executing", "pure_eval"]
+pymongo = ["pymongo (>=3.1)"]
+pyspark = ["pyspark (>=2.4.4)"]
+quart = ["blinker (>=1.1)", "quart (>=0.16.1)"]
+rq = ["rq (>=0.6)"]
+sanic = ["sanic (>=0.8)"]
+sqlalchemy = ["sqlalchemy (>=1.2)"]
+starlette = ["starlette (>=0.19.1)"]
+starlite = ["starlite (>=1.48)"]
+tornado = ["tornado (>=5)"]
+
+[[package]]
name = "setuptools"
-version = "69.0.2"
+version = "69.0.3"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"},
- {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"},
+ {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"},
+ {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"},
]
[package.extras]
@@ -5473,70 +5972,70 @@ files = [
[[package]]
name = "sqlalchemy"
-version = "2.0.23"
+version = "2.0.25"
description = "Database Abstraction Library"
optional = false
python-versions = ">=3.7"
files = [
- {file = "SQLAlchemy-2.0.23-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:638c2c0b6b4661a4fd264f6fb804eccd392745c5887f9317feb64bb7cb03b3ea"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3b5036aa326dc2df50cba3c958e29b291a80f604b1afa4c8ce73e78e1c9f01d"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:787af80107fb691934a01889ca8f82a44adedbf5ef3d6ad7d0f0b9ac557e0c34"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c14eba45983d2f48f7546bb32b47937ee2cafae353646295f0e99f35b14286ab"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0666031df46b9badba9bed00092a1ffa3aa063a5e68fa244acd9f08070e936d3"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:89a01238fcb9a8af118eaad3ffcc5dedaacbd429dc6fdc43fe430d3a941ff965"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-win32.whl", hash = "sha256:cabafc7837b6cec61c0e1e5c6d14ef250b675fa9c3060ed8a7e38653bd732ff8"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-win_amd64.whl", hash = "sha256:87a3d6b53c39cd173990de2f5f4b83431d534a74f0e2f88bd16eabb5667e65c6"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d5578e6863eeb998980c212a39106ea139bdc0b3f73291b96e27c929c90cd8e1"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62d9e964870ea5ade4bc870ac4004c456efe75fb50404c03c5fd61f8bc669a72"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c80c38bd2ea35b97cbf7c21aeb129dcbebbf344ee01a7141016ab7b851464f8e"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75eefe09e98043cff2fb8af9796e20747ae870c903dc61d41b0c2e55128f958d"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd45a5b6c68357578263d74daab6ff9439517f87da63442d244f9f23df56138d"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a86cb7063e2c9fb8e774f77fbf8475516d270a3e989da55fa05d08089d77f8c4"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-win32.whl", hash = "sha256:b41f5d65b54cdf4934ecede2f41b9c60c9f785620416e8e6c48349ab18643855"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-win_amd64.whl", hash = "sha256:9ca922f305d67605668e93991aaf2c12239c78207bca3b891cd51a4515c72e22"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d0f7fb0c7527c41fa6fcae2be537ac137f636a41b4c5a4c58914541e2f436b45"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7c424983ab447dab126c39d3ce3be5bee95700783204a72549c3dceffe0fc8f4"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f508ba8f89e0a5ecdfd3761f82dda2a3d7b678a626967608f4273e0dba8f07ac"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6463aa765cf02b9247e38b35853923edbf2f6fd1963df88706bc1d02410a5577"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e599a51acf3cc4d31d1a0cf248d8f8d863b6386d2b6782c5074427ebb7803bda"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fd54601ef9cc455a0c61e5245f690c8a3ad67ddb03d3b91c361d076def0b4c60"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-win32.whl", hash = "sha256:42d0b0290a8fb0165ea2c2781ae66e95cca6e27a2fbe1016ff8db3112ac1e846"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-win_amd64.whl", hash = "sha256:227135ef1e48165f37590b8bfc44ed7ff4c074bf04dc8d6f8e7f1c14a94aa6ca"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:14aebfe28b99f24f8a4c1346c48bc3d63705b1f919a24c27471136d2f219f02d"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e983fa42164577d073778d06d2cc5d020322425a509a08119bdcee70ad856bf"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e0dc9031baa46ad0dd5a269cb7a92a73284d1309228be1d5935dac8fb3cae24"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5f94aeb99f43729960638e7468d4688f6efccb837a858b34574e01143cf11f89"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:63bfc3acc970776036f6d1d0e65faa7473be9f3135d37a463c5eba5efcdb24c8"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-win32.whl", hash = "sha256:f48ed89dd11c3c586f45e9eec1e437b355b3b6f6884ea4a4c3111a3358fd0c18"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-win_amd64.whl", hash = "sha256:1e018aba8363adb0599e745af245306cb8c46b9ad0a6fc0a86745b6ff7d940fc"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:64ac935a90bc479fee77f9463f298943b0e60005fe5de2aa654d9cdef46c54df"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c4722f3bc3c1c2fcc3702dbe0016ba31148dd6efcd2a2fd33c1b4897c6a19693"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4af79c06825e2836de21439cb2a6ce22b2ca129bad74f359bddd173f39582bf5"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:683ef58ca8eea4747737a1c35c11372ffeb84578d3aab8f3e10b1d13d66f2bc4"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d4041ad05b35f1f4da481f6b811b4af2f29e83af253bf37c3c4582b2c68934ab"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aeb397de65a0a62f14c257f36a726945a7f7bb60253462e8602d9b97b5cbe204"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-win32.whl", hash = "sha256:42ede90148b73fe4ab4a089f3126b2cfae8cfefc955c8174d697bb46210c8306"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-win_amd64.whl", hash = "sha256:964971b52daab357d2c0875825e36584d58f536e920f2968df8d581054eada4b"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:616fe7bcff0a05098f64b4478b78ec2dfa03225c23734d83d6c169eb41a93e55"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e680527245895aba86afbd5bef6c316831c02aa988d1aad83c47ffe92655e74"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9585b646ffb048c0250acc7dad92536591ffe35dba624bb8fd9b471e25212a35"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4895a63e2c271ffc7a81ea424b94060f7b3b03b4ea0cd58ab5bb676ed02f4221"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cc1d21576f958c42d9aec68eba5c1a7d715e5fc07825a629015fe8e3b0657fb0"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:967c0b71156f793e6662dd839da54f884631755275ed71f1539c95bbada9aaab"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-win32.whl", hash = "sha256:0a8c6aa506893e25a04233bc721c6b6cf844bafd7250535abb56cb6cc1368884"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-win_amd64.whl", hash = "sha256:f3420d00d2cb42432c1d0e44540ae83185ccbbc67a6054dcc8ab5387add6620b"},
- {file = "SQLAlchemy-2.0.23-py3-none-any.whl", hash = "sha256:31952bbc527d633b9479f5f81e8b9dfada00b91d6baba021a869095f1a97006d"},
- {file = "SQLAlchemy-2.0.23.tar.gz", hash = "sha256:c1bda93cbbe4aa2aa0aa8655c5aeda505cd219ff3e8da91d1d329e143e4aff69"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4344d059265cc8b1b1be351bfb88749294b87a8b2bbe21dfbe066c4199541ebd"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9e2e59cbcc6ba1488404aad43de005d05ca56e069477b33ff74e91b6319735"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84daa0a2055df9ca0f148a64fdde12ac635e30edbca80e87df9b3aaf419e144a"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc8b7dabe8e67c4832891a5d322cec6d44ef02f432b4588390017f5cec186a84"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f5693145220517b5f42393e07a6898acdfe820e136c98663b971906120549da5"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db854730a25db7c956423bb9fb4bdd1216c839a689bf9cc15fada0a7fb2f4570"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-win32.whl", hash = "sha256:14a6f68e8fc96e5e8f5647ef6cda6250c780612a573d99e4d881581432ef1669"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-win_amd64.whl", hash = "sha256:87f6e732bccd7dcf1741c00f1ecf33797383128bd1c90144ac8adc02cbb98643"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:342d365988ba88ada8af320d43df4e0b13a694dbd75951f537b2d5e4cb5cd002"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f37c0caf14b9e9b9e8f6dbc81bc56db06acb4363eba5a633167781a48ef036ed"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa9373708763ef46782d10e950b49d0235bfe58facebd76917d3f5cbf5971aed"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d24f571990c05f6b36a396218f251f3e0dda916e0c687ef6fdca5072743208f5"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75432b5b14dc2fff43c50435e248b45c7cdadef73388e5610852b95280ffd0e9"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:884272dcd3ad97f47702965a0e902b540541890f468d24bd1d98bcfe41c3f018"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-win32.whl", hash = "sha256:e607cdd99cbf9bb80391f54446b86e16eea6ad309361942bf88318bcd452363c"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d505815ac340568fd03f719446a589162d55c52f08abd77ba8964fbb7eb5b5f"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0dacf67aee53b16f365c589ce72e766efaabd2b145f9de7c917777b575e3659d"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b801154027107461ee992ff4b5c09aa7cc6ec91ddfe50d02bca344918c3265c6"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59a21853f5daeb50412d459cfb13cb82c089ad4c04ec208cd14dddd99fc23b39"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29049e2c299b5ace92cbed0c1610a7a236f3baf4c6b66eb9547c01179f638ec5"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b64b183d610b424a160b0d4d880995e935208fc043d0302dd29fee32d1ee3f95"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4f7a7d7fcc675d3d85fbf3b3828ecd5990b8d61bd6de3f1b260080b3beccf215"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-win32.whl", hash = "sha256:cf18ff7fc9941b8fc23437cc3e68ed4ebeff3599eec6ef5eebf305f3d2e9a7c2"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-win_amd64.whl", hash = "sha256:91f7d9d1c4dd1f4f6e092874c128c11165eafcf7c963128f79e28f8445de82d5"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bb209a73b8307f8fe4fe46f6ad5979649be01607f11af1eb94aa9e8a3aaf77f0"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:798f717ae7c806d67145f6ae94dc7c342d3222d3b9a311a784f371a4333212c7"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fdd402169aa00df3142149940b3bf9ce7dde075928c1886d9a1df63d4b8de62"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0d3cab3076af2e4aa5693f89622bef7fa770c6fec967143e4da7508b3dceb9b9"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:74b080c897563f81062b74e44f5a72fa44c2b373741a9ade701d5f789a10ba23"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-win32.whl", hash = "sha256:87d91043ea0dc65ee583026cb18e1b458d8ec5fc0a93637126b5fc0bc3ea68c4"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-win_amd64.whl", hash = "sha256:75f99202324383d613ddd1f7455ac908dca9c2dd729ec8584c9541dd41822a2c"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:420362338681eec03f53467804541a854617faed7272fe71a1bfdb07336a381e"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c88f0c7dcc5f99bdb34b4fd9b69b93c89f893f454f40219fe923a3a2fd11625"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3be4987e3ee9d9a380b66393b77a4cd6d742480c951a1c56a23c335caca4ce3"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a159111a0f58fb034c93eeba211b4141137ec4b0a6e75789ab7a3ef3c7e7e3"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8b8cb63d3ea63b29074dcd29da4dc6a97ad1349151f2d2949495418fd6e48db9"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:736ea78cd06de6c21ecba7416499e7236a22374561493b456a1f7ffbe3f6cdb4"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-win32.whl", hash = "sha256:10331f129982a19df4284ceac6fe87353ca3ca6b4ca77ff7d697209ae0a5915e"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-win_amd64.whl", hash = "sha256:c55731c116806836a5d678a70c84cb13f2cedba920212ba7dcad53260997666d"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:605b6b059f4b57b277f75ace81cc5bc6335efcbcc4ccb9066695e515dbdb3900"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:665f0a3954635b5b777a55111ababf44b4fc12b1f3ba0a435b602b6387ffd7cf"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecf6d4cda1f9f6cb0b45803a01ea7f034e2f1aed9475e883410812d9f9e3cfcf"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c51db269513917394faec5e5c00d6f83829742ba62e2ac4fa5c98d58be91662f"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:790f533fa5c8901a62b6fef5811d48980adeb2f51f1290ade8b5e7ba990ba3de"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1b1180cda6df7af84fe72e4530f192231b1f29a7496951db4ff38dac1687202d"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-win32.whl", hash = "sha256:555651adbb503ac7f4cb35834c5e4ae0819aab2cd24857a123370764dc7d7e24"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-win_amd64.whl", hash = "sha256:dc55990143cbd853a5d038c05e79284baedf3e299661389654551bd02a6a68d7"},
+ {file = "SQLAlchemy-2.0.25-py3-none-any.whl", hash = "sha256:a86b4240e67d4753dc3092d9511886795b3c2852abe599cffe108952f7af7ac3"},
+ {file = "SQLAlchemy-2.0.25.tar.gz", hash = "sha256:a2c69a7664fb2d54b8682dd774c3b54f67f84fa123cf84dda2a5f40dcaa04e08"},
]
[package.dependencies]
greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""}
-typing-extensions = ">=4.2.0"
+typing-extensions = ">=4.6.0"
[package.extras]
aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"]
aioodbc = ["aioodbc", "greenlet (!=0.4.17)"]
-aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"]
+aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"]
asyncio = ["greenlet (!=0.4.17)"]
asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"]
mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"]
@@ -5546,7 +6045,7 @@ mssql-pyodbc = ["pyodbc"]
mypy = ["mypy (>=0.910)"]
mysql = ["mysqlclient (>=1.4.0)"]
mysql-connector = ["mysql-connector-python"]
-oracle = ["cx-oracle (>=8)"]
+oracle = ["cx_oracle (>=8)"]
oracle-oracledb = ["oracledb (>=1.0.1)"]
postgresql = ["psycopg2 (>=2.7)"]
postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
@@ -5556,7 +6055,7 @@ postgresql-psycopg2binary = ["psycopg2-binary"]
postgresql-psycopg2cffi = ["psycopg2cffi"]
postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"]
pymysql = ["pymysql"]
-sqlcipher = ["sqlcipher3-binary"]
+sqlcipher = ["sqlcipher3_binary"]
[[package]]
name = "srsly"
@@ -5625,20 +6124,20 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
[[package]]
name = "starlette"
-version = "0.27.0"
+version = "0.36.3"
description = "The little ASGI library that shines."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"},
- {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"},
+ {file = "starlette-0.36.3-py3-none-any.whl", hash = "sha256:13d429aa93a61dc40bf503e8c801db1f1bca3dc706b10ef2434a36123568f044"},
+ {file = "starlette-0.36.3.tar.gz", hash = "sha256:90a671733cfb35771d8cc605e0b679d23b992f8dcfad48cc60b38cb29aeb7080"},
]
[package.dependencies]
anyio = ">=3.4.0,<5"
[package.extras]
-full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"]
+full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"]
[[package]]
name = "sympy"
@@ -5655,6 +6154,20 @@ files = [
mpmath = ">=0.19"
[[package]]
+name = "tabulate"
+version = "0.9.0"
+description = "Pretty-print tabular data"
+optional = true
+python-versions = ">=3.7"
+files = [
+ {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"},
+ {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"},
+]
+
+[package.extras]
+widechars = ["wcwidth"]
+
+[[package]]
name = "tenacity"
version = "8.2.3"
description = "Retry code until it succeeds"
@@ -5954,13 +6467,13 @@ telegram = ["requests"]
[[package]]
name = "traitlets"
-version = "5.14.0"
+version = "5.14.1"
description = "Traitlets Python configuration system"
optional = true
python-versions = ">=3.8"
files = [
- {file = "traitlets-5.14.0-py3-none-any.whl", hash = "sha256:f14949d23829023013c47df20b4a76ccd1a85effb786dc060f34de7948361b33"},
- {file = "traitlets-5.14.0.tar.gz", hash = "sha256:fcdaa8ac49c04dfa0ed3ee3384ef6dfdb5d6f3741502be247279407679296772"},
+ {file = "traitlets-5.14.1-py3-none-any.whl", hash = "sha256:2e5a030e6eff91737c643231bfcf04a65b0132078dad75e4936700b213652e74"},
+ {file = "traitlets-5.14.1.tar.gz", hash = "sha256:8585105b371a04b8316a43d5ce29c098575c2e477850b62b848b964f1444527e"},
]
[package.extras]
@@ -5969,19 +6482,19 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,
[[package]]
name = "trio"
-version = "0.23.1"
+version = "0.24.0"
description = "A friendly Python library for async concurrency and I/O"
optional = false
python-versions = ">=3.8"
files = [
- {file = "trio-0.23.1-py3-none-any.whl", hash = "sha256:bb4abb3f4af23f96679e7c8cdabb8b234520f2498550d2cf63ebfd95f2ce27fe"},
- {file = "trio-0.23.1.tar.gz", hash = "sha256:16f89f7dcc8f7b9dcdec1fcd863e0c039af6d0f9a22f8dfd56f75d75ec73fd48"},
+ {file = "trio-0.24.0-py3-none-any.whl", hash = "sha256:c3bd3a4e3e3025cd9a2241eae75637c43fe0b9e88b4c97b9161a55b9e54cd72c"},
+ {file = "trio-0.24.0.tar.gz", hash = "sha256:ffa09a74a6bf81b84f8613909fb0beaee84757450183a7a2e0b47b455c0cac5d"},
]
[package.dependencies]
attrs = ">=20.1.0"
cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""}
-exceptiongroup = {version = ">=1.0.0rc9", markers = "python_version < \"3.11\""}
+exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
idna = "*"
outcome = "*"
sniffio = ">=1.3.0"
@@ -6026,24 +6539,24 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.
[[package]]
name = "types-awscrt"
-version = "0.19.19"
+version = "0.20.0"
description = "Type annotations and code completion for awscrt"
optional = false
python-versions = ">=3.7,<4.0"
files = [
- {file = "types_awscrt-0.19.19-py3-none-any.whl", hash = "sha256:a577c4d60a7fb7e21b436a73207a66f6ba50329d578b347934c5d99d4d612901"},
- {file = "types_awscrt-0.19.19.tar.gz", hash = "sha256:850d5ad95d8f337b15fb154790f39af077faf5c08d43758fd750f379a87d5f73"},
+ {file = "types_awscrt-0.20.0-py3-none-any.whl", hash = "sha256:e872b65d041687ec7fb49fb4dcb871ff10ade5efeca02722e037a03bff81db7e"},
+ {file = "types_awscrt-0.20.0.tar.gz", hash = "sha256:99778c952e1eae10cc7a53468413001177026c9434345bf00120bb2ea5b79109"},
]
[[package]]
name = "types-beautifulsoup4"
-version = "4.12.0.7"
+version = "4.12.0.20240106"
description = "Typing stubs for beautifulsoup4"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "types-beautifulsoup4-4.12.0.7.tar.gz", hash = "sha256:59980028d29bf55d0db359efa305b75bacf0cb92e3f3f6b3fd408f2531df274c"},
- {file = "types_beautifulsoup4-4.12.0.7-py3-none-any.whl", hash = "sha256:8b03b054cb2e62abf82bbbeda57a07257026f4ed9010ef17d8f8eff43bb1f9b7"},
+ {file = "types-beautifulsoup4-4.12.0.20240106.tar.gz", hash = "sha256:98d628985b71b140bd3bc22a8cb0ab603c2f2d08f20d37925965eb4a21739be8"},
+ {file = "types_beautifulsoup4-4.12.0.20240106-py3-none-any.whl", hash = "sha256:cbdd60ab8aeac737ac014431b6e921b43e84279c0405fdd25a6900bb0e71da5b"},
]
[package.dependencies]
@@ -6051,71 +6564,82 @@ types-html5lib = "*"
[[package]]
name = "types-colorama"
-version = "0.4.15.12"
+version = "0.4.15.20240106"
description = "Typing stubs for colorama"
optional = false
-python-versions = "*"
+python-versions = ">=3.8"
files = [
- {file = "types-colorama-0.4.15.12.tar.gz", hash = "sha256:fbdfc5d9d24d85c33bd054fbe33adc6cec44eedb19cfbbabfbbb57dc257ae4b8"},
- {file = "types_colorama-0.4.15.12-py3-none-any.whl", hash = "sha256:23c9d4a00961227f7ef018d5a1c190c4bbc282119c3ee76a17677a793f13bb82"},
+ {file = "types-colorama-0.4.15.20240106.tar.gz", hash = "sha256:49096b4c4cbfcaa11699a0470c36e4f5631f193fb980188e013ea64445d35656"},
+ {file = "types_colorama-0.4.15.20240106-py3-none-any.whl", hash = "sha256:18294bc18f60dc0b4895de8119964a5d895f5e180c2d1308fdd33009c0fa0f38"},
]
[[package]]
name = "types-html5lib"
-version = "1.1.11.15"
+version = "1.1.11.20240106"
description = "Typing stubs for html5lib"
optional = false
-python-versions = "*"
+python-versions = ">=3.8"
files = [
- {file = "types-html5lib-1.1.11.15.tar.gz", hash = "sha256:80e1a2062d22a3affe5c28d97da30bffbf3a076d393c80fc6f1671216c1bd492"},
- {file = "types_html5lib-1.1.11.15-py3-none-any.whl", hash = "sha256:16fe936d99b9f7fc210e2e21a2aed1b6bbbc554ad8242a6ef75f6f2bddb27e58"},
+ {file = "types-html5lib-1.1.11.20240106.tar.gz", hash = "sha256:fc3a1b18eb601b3eeaf92c900bd67675c0a4fa1dd1d2a2893ebdb46923547ee9"},
+ {file = "types_html5lib-1.1.11.20240106-py3-none-any.whl", hash = "sha256:61993cb89220107481e0f1da65c388ff8cf3d8c5f6e8483c97559639a596b697"},
]
[[package]]
name = "types-markdown"
-version = "3.5.0.3"
+version = "3.5.0.20240106"
description = "Typing stubs for Markdown"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "types-Markdown-3.5.0.3.tar.gz", hash = "sha256:9afd38a8f53e19d43de3f8d89742b3674b5736767806ed9356d64ccb09f76439"},
- {file = "types_Markdown-3.5.0.3-py3-none-any.whl", hash = "sha256:2299b9086c695f408a3ebabf820f1fba3b239f1b3bfdbb32bf42d530b42cdd83"},
+ {file = "types-Markdown-3.5.0.20240106.tar.gz", hash = "sha256:be47d35cbe61d458bd17aec127f1da233cd6ed96fa9a131c710378a4e8857030"},
+ {file = "types_Markdown-3.5.0.20240106-py3-none-any.whl", hash = "sha256:c23569d33718475dfae25c0036c6e6866f409e7077ee8a0728ab3db263d8e4a5"},
]
[[package]]
name = "types-pillow"
-version = "10.1.0.2"
+version = "10.2.0.20240111"
description = "Typing stubs for Pillow"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "types-Pillow-10.1.0.2.tar.gz", hash = "sha256:525c1c5ee67b0ac1721c40d2bc618226ef2123c347e527e14e05b920721a13b9"},
- {file = "types_Pillow-10.1.0.2-py3-none-any.whl", hash = "sha256:131078ffa547bf9a201d39ffcdc65633e108148085f4f1b07d4647fcfec6e923"},
+ {file = "types-Pillow-10.2.0.20240111.tar.gz", hash = "sha256:e8d359bfdc5a149a3c90a7e153cb2d0750ddf7fc3508a20dfadabd8a9435e354"},
+ {file = "types_Pillow-10.2.0.20240111-py3-none-any.whl", hash = "sha256:1f4243b30c143b56b0646626f052e4269123e550f9096cdfb5fbd999daee7dbb"},
]
[[package]]
name = "types-requests"
-version = "2.31.0.10"
+version = "2.31.0.6"
description = "Typing stubs for requests"
optional = true
python-versions = ">=3.7"
files = [
- {file = "types-requests-2.31.0.10.tar.gz", hash = "sha256:dc5852a76f1eaf60eafa81a2e50aefa3d1f015c34cf0cba130930866b1b22a92"},
- {file = "types_requests-2.31.0.10-py3-none-any.whl", hash = "sha256:b32b9a86beffa876c0c3ac99a4cd3b8b51e973fb8e3bd4e0a6bb32c7efad80fc"},
+ {file = "types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0"},
+ {file = "types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9"},
]
[package.dependencies]
-urllib3 = ">=2"
+types-urllib3 = "*"
[[package]]
name = "types-s3transfer"
-version = "0.8.2"
+version = "0.10.0"
description = "Type annotations and code completion for s3transfer"
optional = false
python-versions = ">=3.7,<4.0"
files = [
- {file = "types_s3transfer-0.8.2-py3-none-any.whl", hash = "sha256:5e084ebcf2704281c71b19d5da6e1544b50859367d034b50080d5316a76a9418"},
- {file = "types_s3transfer-0.8.2.tar.gz", hash = "sha256:2e41756fcf94775a9949afa856489ac4570308609b0493dfbd7b4d333eb423e6"},
+ {file = "types_s3transfer-0.10.0-py3-none-any.whl", hash = "sha256:44fcdf0097b924a9aab1ee4baa1179081a9559ca62a88c807e2b256893ce688f"},
+ {file = "types_s3transfer-0.10.0.tar.gz", hash = "sha256:35e4998c25df7f8985ad69dedc8e4860e8af3b43b7615e940d53c00d413bdc69"},
+]
+
+[[package]]
+name = "types-urllib3"
+version = "1.26.25.14"
+description = "Typing stubs for urllib3"
+optional = true
+python-versions = "*"
+files = [
+ {file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"},
+ {file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"},
]
[[package]]
@@ -6131,13 +6655,13 @@ files = [
[[package]]
name = "tzdata"
-version = "2023.3"
+version = "2023.4"
description = "Provider of IANA time zone data"
optional = true
python-versions = ">=2"
files = [
- {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"},
- {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"},
+ {file = "tzdata-2023.4-py2.py3-none-any.whl", hash = "sha256:aa3ace4329eeacda5b7beb7ea08ece826c28d761cda36e747cfbf97996d39bf3"},
+ {file = "tzdata-2023.4.tar.gz", hash = "sha256:dd54c94f294765522c77399649b4fefd95522479a664a0cec87f41bebc6148c9"},
]
[[package]]
@@ -6153,23 +6677,22 @@ files = [
[[package]]
name = "urllib3"
-version = "2.0.7"
+version = "1.26.18"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
- {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"},
- {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"},
+ {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"},
+ {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"},
]
[package.dependencies]
-pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""}
+PySocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""}
[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
-secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"]
-socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
-zstd = ["zstandard (>=0.18.0)"]
+brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
+secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
+socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "uvicorn"
@@ -6384,13 +6907,13 @@ anyio = ">=3.0.0"
[[package]]
name = "wcwidth"
-version = "0.2.12"
+version = "0.2.13"
description = "Measures the displayed width of unicode strings in a terminal"
optional = false
python-versions = "*"
files = [
- {file = "wcwidth-0.2.12-py2.py3-none-any.whl", hash = "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c"},
- {file = "wcwidth-0.2.12.tar.gz", hash = "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02"},
+ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
+ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
]
[[package]]
@@ -6410,6 +6933,22 @@ python-dotenv = "*"
requests = "*"
[[package]]
+name = "websocket-client"
+version = "1.7.0"
+description = "WebSocket client for Python with low level API options"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "websocket-client-1.7.0.tar.gz", hash = "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6"},
+ {file = "websocket_client-1.7.0-py3-none-any.whl", hash = "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588"},
+]
+
+[package.extras]
+docs = ["Sphinx (>=6.0)", "sphinx-rtd-theme (>=1.1.0)"]
+optional = ["python-socks", "wsaccel"]
+test = ["websockets"]
+
+[[package]]
name = "websockets"
version = "12.0"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
@@ -6721,4 +7260,4 @@ benchmark = ["agbenchmark"]
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
-content-hash = "bd520cc56d67eb631b6a9569e18934c08c5d302761c589c74a4839a805039137"
+content-hash = "afa9674e032573e483e977e818766efe18ea4f52efa1ce6dfc71686772371b5b"
diff --git a/autogpts/autogpt/pyproject.toml b/autogpts/autogpt/pyproject.toml
index df81c3b00..404bffaaa 100644
--- a/autogpts/autogpt/pyproject.toml
+++ b/autogpts/autogpt/pyproject.toml
@@ -24,17 +24,18 @@ serve = "autogpt.app.cli:serve"
python = "^3.10"
auto-gpt-plugin-template = {git = "https://github.com/Significant-Gravitas/Auto-GPT-Plugin-Template", rev = "0.1.0"}
# autogpt-forge = { path = "../forge" }
-autogpt-forge = {git = "https://github.com/Significant-Gravitas/AutoGPT.git", subdirectory = "autogpts/forge"}
+autogpt-forge = {git = "https://github.com/Significant-Gravitas/AutoGPT.git", rev = "ab05b7ae70754c063909", subdirectory = "autogpts/forge"}
beautifulsoup4 = "^4.12.2"
boto3 = "^1.33.6"
charset-normalizer = "^3.1.0"
click = "*"
colorama = "^0.4.6"
+demjson3 = "^3.0.0"
distro = "^1.8.0"
docker = "*"
-duckduckgo-search = "^4.0.0"
+duckduckgo-search = "^5.0.0"
en-core-web-sm = {url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.5.0/en_core_web_sm-3.5.0-py3-none-any.whl"}
-fastapi = "*"
+fastapi = "^0.109.1"
ftfy = "^6.1.1"
gitpython = "^3.1.32"
google-api-python-client = "*"
@@ -43,12 +44,11 @@ hypercorn = "^0.14.4"
inflection = "*"
jsonschema = "*"
numpy = "*"
-openai = "^0.27.10"
+openai = "^1.7.2"
orjson = "^3.8.10"
Pillow = "*"
pinecone-client = "^2.2.1"
playsound = "~1.2.2"
-prompt_toolkit = "^3.0.38"
pydantic = "*"
pylatexenc = "*"
pypdf = "^3.1.0"
@@ -59,7 +59,9 @@ readability-lxml = "^0.8.1"
redis = "*"
requests = "*"
selenium = "^4.11.2"
+sentry-sdk = "^1.40.4"
spacy = "^3.0.0"
+tenacity = "^8.2.2"
tiktoken = "^0.5.0"
webdriver-manager = "*"
@@ -67,8 +69,8 @@ webdriver-manager = "*"
openapi-python-client = "^0.14.0"
# Benchmarking
-# agbenchmark = { path = "../../benchmark", optional = true }
-agbenchmark = {git = "https://github.com/Significant-Gravitas/AutoGPT.git", subdirectory = "benchmark", optional = true}
+agbenchmark = { path = "../../benchmark", optional = true }
+# agbenchmark = {git = "https://github.com/Significant-Gravitas/AutoGPT.git", subdirectory = "benchmark", optional = true}
google-cloud-logging = "^3.8.0"
google-cloud-storage = "^2.13.0"
psycopg2-binary = "^2.9.9"
diff --git a/autogpts/autogpt/tests/conftest.py b/autogpts/autogpt/tests/conftest.py
index 3aabf2e82..6f796c2b5 100644
--- a/autogpts/autogpt/tests/conftest.py
+++ b/autogpts/autogpt/tests/conftest.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
import os
import uuid
from pathlib import Path
@@ -11,12 +13,11 @@ from autogpt.agents.agent import Agent, AgentConfiguration, AgentSettings
from autogpt.app.main import _configure_openai_provider
from autogpt.config import AIProfile, Config, ConfigBuilder
from autogpt.core.resource.model_providers import ChatModelProvider, OpenAIProvider
-from autogpt.file_workspace.local import (
- FileWorkspace,
- FileWorkspaceConfiguration,
- LocalFileWorkspace,
+from autogpt.file_storage.local import (
+ FileStorage,
+ FileStorageConfiguration,
+ LocalFileStorage,
)
-from autogpt.llm.api_manager import ApiManager
from autogpt.logs.config import configure_logging
from autogpt.models.command_registry import CommandRegistry
@@ -40,20 +41,12 @@ def app_data_dir(tmp_project_root: Path) -> Path:
@pytest.fixture()
-def agent_data_dir(app_data_dir: Path) -> Path:
- return app_data_dir / "agents/AutoGPT"
-
-
-@pytest.fixture()
-def workspace_root(agent_data_dir: Path) -> Path:
- return agent_data_dir / "workspace"
-
-
-@pytest.fixture()
-def workspace(workspace_root: Path) -> FileWorkspace:
- workspace = LocalFileWorkspace(FileWorkspaceConfiguration(root=workspace_root))
- workspace.initialize()
- return workspace
+def storage(app_data_dir: Path) -> FileStorage:
+ storage = LocalFileStorage(
+ FileStorageConfiguration(root=app_data_dir, restrict_to_root=False)
+ )
+ storage.initialize()
+ return storage
@pytest.fixture
@@ -70,7 +63,7 @@ def temp_plugins_config_file():
yield config_file
-@pytest.fixture()
+@pytest.fixture(scope="function")
def config(
temp_plugins_config_file: Path,
tmp_project_root: Path,
@@ -86,8 +79,6 @@ def config(
config.plugins_dir = "tests/unit/data/test_plugins"
config.plugins_config_file = temp_plugins_config_file
- config.logging.log_dir = Path(__file__).parent / "logs"
- config.logging.plain_console_output = True
config.noninteractive_mode = True
# avoid circular dependency
@@ -103,14 +94,11 @@ def config(
@pytest.fixture(scope="session")
def setup_logger(config: Config):
- configure_logging(**config.logging.dict())
-
-
-@pytest.fixture()
-def api_manager() -> ApiManager:
- if ApiManager in ApiManager._instances:
- del ApiManager._instances[ApiManager]
- return ApiManager()
+ configure_logging(
+ debug=True,
+ log_dir=Path(__file__).parent / "logs",
+ plain_console_output=True,
+ )
@pytest.fixture
@@ -120,7 +108,7 @@ def llm_provider(config: Config) -> OpenAIProvider:
@pytest.fixture
def agent(
- agent_data_dir: Path, config: Config, llm_provider: ChatModelProvider
+ config: Config, llm_provider: ChatModelProvider, storage: FileStorage
) -> Agent:
ai_profile = AIProfile(
ai_name="Base",
@@ -153,7 +141,7 @@ def agent(
settings=agent_settings,
llm_provider=llm_provider,
command_registry=command_registry,
+ file_storage=storage,
legacy_config=config,
)
- agent.attach_fs(agent_data_dir)
return agent
diff --git a/autogpts/autogpt/tests/integration/memory/_test_json_file_memory.py b/autogpts/autogpt/tests/integration/memory/_test_json_file_memory.py
index 9fb88f9f7..94bf0d1bd 100644
--- a/autogpts/autogpt/tests/integration/memory/_test_json_file_memory.py
+++ b/autogpts/autogpt/tests/integration/memory/_test_json_file_memory.py
@@ -4,14 +4,12 @@ import orjson
import pytest
from autogpt.config import Config
-from autogpt.file_workspace import FileWorkspace
+from autogpt.file_storage import FileStorage
from autogpt.memory.vector import JSONFileMemory, MemoryItem
-def test_json_memory_init_without_backing_file(
- config: Config, workspace: FileWorkspace
-):
- index_file = workspace.root / f"{config.memory_index}.json"
+def test_json_memory_init_without_backing_file(config: Config, storage: FileStorage):
+ index_file = storage.root / f"{config.memory_index}.json"
assert not index_file.exists()
JSONFileMemory(config)
@@ -19,10 +17,8 @@ def test_json_memory_init_without_backing_file(
assert index_file.read_text() == "[]"
-def test_json_memory_init_with_backing_empty_file(
- config: Config, workspace: FileWorkspace
-):
- index_file = workspace.root / f"{config.memory_index}.json"
+def test_json_memory_init_with_backing_empty_file(config: Config, storage: FileStorage):
+ index_file = storage.root / f"{config.memory_index}.json"
index_file.touch()
assert index_file.exists()
@@ -32,9 +28,9 @@ def test_json_memory_init_with_backing_empty_file(
def test_json_memory_init_with_backing_invalid_file(
- config: Config, workspace: FileWorkspace
+ config: Config, storage: FileStorage
):
- index_file = workspace.root / f"{config.memory_index}.json"
+ index_file = storage.root / f"{config.memory_index}.json"
index_file.touch()
raw_data = {"texts": ["test"]}
@@ -97,7 +93,7 @@ def test_json_memory_load_index(config: Config, memory_item: MemoryItem):
@pytest.mark.vcr
@pytest.mark.requires_openai_api_key
-def test_json_memory_get_relevant(config: Config, patched_api_requestor: None) -> None:
+def test_json_memory_get_relevant(config: Config, cached_openai_client: None) -> None:
index = JSONFileMemory(config)
mem1 = MemoryItem.from_text_file("Sample text", "sample.txt", config)
mem2 = MemoryItem.from_text_file(
diff --git a/autogpts/autogpt/tests/integration/test_execute_code.py b/autogpts/autogpt/tests/integration/test_execute_code.py
index 1c980e025..b8667b475 100644
--- a/autogpts/autogpt/tests/integration/test_execute_code.py
+++ b/autogpts/autogpt/tests/integration/test_execute_code.py
@@ -44,6 +44,9 @@ def random_string():
def test_execute_python_file(python_test_file: Path, random_string: str, agent: Agent):
+ if not (sut.is_docker_available() or sut.we_are_running_in_a_docker_container()):
+ pytest.skip("Docker is not available")
+
result: str = sut.execute_python_file(python_test_file, agent=agent)
assert result.replace("\r", "") == f"Hello {random_string}!\n"
@@ -51,6 +54,9 @@ def test_execute_python_file(python_test_file: Path, random_string: str, agent:
def test_execute_python_file_args(
python_test_args_file: Path, random_string: str, agent: Agent
):
+ if not (sut.is_docker_available() or sut.we_are_running_in_a_docker_container()):
+ pytest.skip("Docker is not available")
+
random_args = [random_string] * 2
random_args_string = " ".join(random_args)
result = sut.execute_python_file(
@@ -60,6 +66,9 @@ def test_execute_python_file_args(
def test_execute_python_code(random_code: str, random_string: str, agent: Agent):
+ if not (sut.is_docker_available() or sut.we_are_running_in_a_docker_container()):
+ pytest.skip("Docker is not available")
+
result: str = sut.execute_python_code(random_code, agent=agent)
assert result.replace("\r", "") == f"Hello {random_string}!\n"
diff --git a/autogpts/autogpt/tests/integration/test_image_gen.py b/autogpts/autogpt/tests/integration/test_image_gen.py
index a747ee785..e5c1c555e 100644
--- a/autogpts/autogpt/tests/integration/test_image_gen.py
+++ b/autogpts/autogpt/tests/integration/test_image_gen.py
@@ -18,11 +18,11 @@ def image_size(request):
@pytest.mark.requires_openai_api_key
@pytest.mark.vcr
-def test_dalle(agent: Agent, workspace, image_size, patched_api_requestor):
+def test_dalle(agent: Agent, storage, image_size, cached_openai_client):
"""Test DALL-E image generation."""
generate_and_validate(
agent,
- workspace,
+ storage,
image_provider="dalle",
image_size=image_size,
)
@@ -37,11 +37,11 @@ def test_dalle(agent: Agent, workspace, image_size, patched_api_requestor):
"image_model",
["CompVis/stable-diffusion-v1-4", "stabilityai/stable-diffusion-2-1"],
)
-def test_huggingface(agent: Agent, workspace, image_size, image_model):
+def test_huggingface(agent: Agent, storage, image_size, image_model):
"""Test HuggingFace image generation."""
generate_and_validate(
agent,
- workspace,
+ storage,
image_provider="huggingface",
image_size=image_size,
hugging_face_image_model=image_model,
@@ -49,18 +49,18 @@ def test_huggingface(agent: Agent, workspace, image_size, image_model):
@pytest.mark.xfail(reason="SD WebUI call does not work.")
-def test_sd_webui(agent: Agent, workspace, image_size):
+def test_sd_webui(agent: Agent, storage, image_size):
"""Test SD WebUI image generation."""
generate_and_validate(
agent,
- workspace,
+ storage,
image_provider="sd_webui",
image_size=image_size,
)
@pytest.mark.xfail(reason="SD WebUI call does not work.")
-def test_sd_webui_negative_prompt(agent: Agent, workspace, image_size):
+def test_sd_webui_negative_prompt(agent: Agent, storage, image_size):
gen_image = functools.partial(
generate_image_with_sd_webui,
prompt="astronaut riding a horse",
@@ -91,7 +91,7 @@ def lst(txt):
def generate_and_validate(
agent: Agent,
- workspace,
+ storage,
image_size,
image_provider,
hugging_face_image_model=None,
@@ -125,7 +125,7 @@ def generate_and_validate(
)
@pytest.mark.parametrize("delay", [10, 0])
def test_huggingface_fail_request_with_delay(
- agent: Agent, workspace, image_size, image_model, return_text, delay
+ agent: Agent, storage, image_size, image_model, return_text, delay
):
return_text = return_text.replace("[model]", image_model).replace(
"[delay]", str(delay)
diff --git a/autogpts/autogpt/tests/integration/test_web_selenium.py b/autogpts/autogpt/tests/integration/test_web_selenium.py
index 5a014efe1..1d904b855 100644
--- a/autogpts/autogpt/tests/integration/test_web_selenium.py
+++ b/autogpts/autogpt/tests/integration/test_web_selenium.py
@@ -7,9 +7,7 @@ from autogpt.commands.web_selenium import BrowsingError, read_webpage
@pytest.mark.vcr
@pytest.mark.requires_openai_api_key
@pytest.mark.asyncio
-async def test_browse_website_nonexistent_url(
- agent: Agent, patched_api_requestor: None
-):
+async def test_browse_website_nonexistent_url(agent: Agent, cached_openai_client: None):
url = "https://auto-gpt-thinks-this-website-does-not-exist.com"
question = "How to execute a barrel roll"
diff --git a/autogpts/autogpt/tests/unit/test_ai_profile.py b/autogpts/autogpt/tests/unit/test_ai_profile.py
index ae31b9332..a60de4d9d 100644
--- a/autogpts/autogpt/tests/unit/test_ai_profile.py
+++ b/autogpts/autogpt/tests/unit/test_ai_profile.py
@@ -1,4 +1,5 @@
from autogpt.config.ai_profile import AIProfile
+from autogpt.file_storage.base import FileStorage
"""
Test cases for the AIProfile class, which handles loads the AI configuration
@@ -45,10 +46,10 @@ api_budget: 0.0
assert ai_settings_file.read_text() == yaml_content2
-def test_ai_profile_file_not_exists(workspace):
+def test_ai_profile_file_not_exists(storage: FileStorage):
"""Test if file does not exist."""
- ai_settings_file = workspace.get_path("ai_settings.yaml")
+ ai_settings_file = storage.get_path("ai_settings.yaml")
ai_profile = AIProfile.load(str(ai_settings_file))
assert ai_profile.ai_name == ""
@@ -57,10 +58,10 @@ def test_ai_profile_file_not_exists(workspace):
assert ai_profile.api_budget == 0.0
-def test_ai_profile_file_is_empty(workspace):
+def test_ai_profile_file_is_empty(storage: FileStorage):
"""Test if file does not exist."""
- ai_settings_file = workspace.get_path("ai_settings.yaml")
+ ai_settings_file = storage.get_path("ai_settings.yaml")
ai_settings_file.write_text("")
ai_profile = AIProfile.load(str(ai_settings_file))
diff --git a/autogpts/autogpt/tests/unit/test_api_manager.py b/autogpts/autogpt/tests/unit/test_api_manager.py
deleted file mode 100644
index da9b0c3d8..000000000
--- a/autogpts/autogpt/tests/unit/test_api_manager.py
+++ /dev/null
@@ -1,89 +0,0 @@
-from unittest.mock import patch
-
-import pytest
-from pytest_mock import MockerFixture
-
-from autogpt.core.resource.model_providers import (
- OPEN_AI_CHAT_MODELS,
- OPEN_AI_EMBEDDING_MODELS,
-)
-from autogpt.llm.api_manager import ApiManager
-
-api_manager = ApiManager()
-
-
-@pytest.fixture(autouse=True)
-def reset_api_manager():
- api_manager.reset()
- yield
-
-
-@pytest.fixture(autouse=True)
-def mock_costs(mocker: MockerFixture):
- mocker.patch.multiple(
- OPEN_AI_CHAT_MODELS["gpt-3.5-turbo"],
- prompt_token_cost=0.0013,
- completion_token_cost=0.0025,
- )
- mocker.patch.multiple(
- OPEN_AI_EMBEDDING_MODELS["text-embedding-ada-002"],
- prompt_token_cost=0.0004,
- )
- yield
-
-
-class TestApiManager:
- def test_getter_methods(self):
- """Test the getter methods for total tokens, cost, and budget."""
- api_manager.update_cost(600, 1200, "gpt-3.5-turbo")
- api_manager.set_total_budget(10.0)
- assert api_manager.get_total_prompt_tokens() == 600
- assert api_manager.get_total_completion_tokens() == 1200
- assert api_manager.get_total_cost() == (600 * 0.0013 + 1200 * 0.0025) / 1000
- assert api_manager.get_total_budget() == 10.0
-
- @staticmethod
- def test_set_total_budget():
- """Test if setting the total budget works correctly."""
- total_budget = 10.0
- api_manager.set_total_budget(total_budget)
-
- assert api_manager.get_total_budget() == total_budget
-
- @staticmethod
- def test_update_cost_completion_model():
- """Test if updating the cost works correctly."""
- prompt_tokens = 50
- completion_tokens = 100
- model = "gpt-3.5-turbo"
-
- api_manager.update_cost(prompt_tokens, completion_tokens, model)
-
- assert api_manager.get_total_prompt_tokens() == prompt_tokens
- assert api_manager.get_total_completion_tokens() == completion_tokens
- assert (
- api_manager.get_total_cost()
- == (prompt_tokens * 0.0013 + completion_tokens * 0.0025) / 1000
- )
-
- @staticmethod
- def test_update_cost_embedding_model():
- """Test if updating the cost works correctly."""
- prompt_tokens = 1337
- model = "text-embedding-ada-002"
-
- api_manager.update_cost(prompt_tokens, 0, model)
-
- assert api_manager.get_total_prompt_tokens() == prompt_tokens
- assert api_manager.get_total_completion_tokens() == 0
- assert api_manager.get_total_cost() == (prompt_tokens * 0.0004) / 1000
-
- @staticmethod
- def test_get_models():
- """Test if getting models works correctly."""
- with patch("openai.Model.list") as mock_list_models:
- mock_list_models.return_value = {"data": [{"id": "gpt-3.5-turbo"}]}
- result = api_manager.get_models()
-
- assert result[0]["id"] == "gpt-3.5-turbo"
- assert api_manager.models[0]["id"] == "gpt-3.5-turbo"
diff --git a/autogpts/autogpt/tests/unit/test_config.py b/autogpts/autogpt/tests/unit/test_config.py
index 059a6ddd3..70d1b65b0 100644
--- a/autogpts/autogpt/tests/unit/test_config.py
+++ b/autogpts/autogpt/tests/unit/test_config.py
@@ -2,16 +2,23 @@
Test cases for the config class, which handles the configuration settings
for the AI and ensures it behaves as a singleton.
"""
+import asyncio
import os
from typing import Any
from unittest import mock
-from unittest.mock import patch
import pytest
+from openai.pagination import AsyncPage
+from openai.types import Model
from pydantic import SecretStr
from autogpt.app.configurator import GPT_3_MODEL, GPT_4_MODEL, apply_overrides_to_config
from autogpt.config import Config, ConfigBuilder
+from autogpt.core.resource.model_providers.openai import OpenAIModelName
+from autogpt.core.resource.model_providers.schema import (
+ ChatModelInfo,
+ ModelProviderName,
+)
def test_initial_values(config: Config) -> None:
@@ -20,80 +27,30 @@ def test_initial_values(config: Config) -> None:
"""
assert config.continuous_mode is False
assert config.tts_config.speak_mode is False
- assert config.fast_llm == "gpt-3.5-turbo-16k"
+ assert config.fast_llm.startswith("gpt-3.5-turbo")
assert config.smart_llm.startswith("gpt-4")
-def test_set_continuous_mode(config: Config) -> None:
- """
- Test if the set_continuous_mode() method updates the continuous_mode attribute.
- """
- # Store continuous mode to reset it after the test
- continuous_mode = config.continuous_mode
-
- config.continuous_mode = True
- assert config.continuous_mode is True
-
- # Reset continuous mode
- config.continuous_mode = continuous_mode
-
-
-def test_set_speak_mode(config: Config) -> None:
- """
- Test if the set_speak_mode() method updates the speak_mode attribute.
- """
- # Store speak mode to reset it after the test
- speak_mode = config.tts_config.speak_mode
-
- config.tts_config.speak_mode = True
- assert config.tts_config.speak_mode is True
-
- # Reset speak mode
- config.tts_config.speak_mode = speak_mode
-
-
-def test_set_fast_llm(config: Config) -> None:
- """
- Test if the set_fast_llm() method updates the fast_llm attribute.
- """
- # Store model name to reset it after the test
- fast_llm = config.fast_llm
-
- config.fast_llm = "gpt-3.5-turbo-test"
- assert config.fast_llm == "gpt-3.5-turbo-test"
-
- # Reset model name
- config.fast_llm = fast_llm
-
-
-def test_set_smart_llm(config: Config) -> None:
- """
- Test if the set_smart_llm() method updates the smart_llm attribute.
- """
- # Store model name to reset it after the test
- smart_llm = config.smart_llm
-
- config.smart_llm = "gpt-4-test"
- assert config.smart_llm == "gpt-4-test"
-
- # Reset model name
- config.smart_llm = smart_llm
-
-
-@patch("openai.Model.list")
-def test_smart_and_fast_llms_set_to_gpt4(mock_list_models: Any, config: Config) -> None:
+@pytest.mark.asyncio
+@mock.patch("openai.resources.models.AsyncModels.list")
+async def test_fallback_to_gpt3_if_gpt4_not_available(
+ mock_list_models: Any, config: Config
+) -> None:
"""
Test if models update to gpt-3.5-turbo if gpt-4 is not available.
"""
- fast_llm = config.fast_llm
- smart_llm = config.smart_llm
-
- config.fast_llm = "gpt-4"
- config.smart_llm = "gpt-4"
-
- mock_list_models.return_value = {"data": [{"id": "gpt-3.5-turbo"}]}
+ config.fast_llm = OpenAIModelName.GPT4_TURBO
+ config.smart_llm = OpenAIModelName.GPT4_TURBO
+
+ mock_list_models.return_value = asyncio.Future()
+ mock_list_models.return_value.set_result(
+ AsyncPage(
+ data=[Model(id=GPT_3_MODEL, created=0, object="model", owned_by="AutoGPT")],
+ object="Models", # no idea what this should be, but irrelevant
+ )
+ )
- apply_overrides_to_config(
+ await apply_overrides_to_config(
config=config,
gpt3only=False,
gpt4only=False,
@@ -102,10 +59,6 @@ def test_smart_and_fast_llms_set_to_gpt4(mock_list_models: Any, config: Config)
assert config.fast_llm == "gpt-3.5-turbo"
assert config.smart_llm == "gpt-3.5-turbo"
- # Reset config
- config.fast_llm = fast_llm
- config.smart_llm = smart_llm
-
def test_missing_azure_config(config: Config) -> None:
assert config.openai_credentials is not None
@@ -123,75 +76,88 @@ def test_missing_azure_config(config: Config) -> None:
assert config.openai_credentials.azure_model_to_deploy_id_map is None
-def test_azure_config(config: Config) -> None:
+@pytest.fixture
+def config_with_azure(config: Config):
config_file = config.app_data_dir / "azure_config.yaml"
config_file.write_text(
f"""
azure_api_type: azure
-azure_api_base: https://dummy.openai.azure.com
azure_api_version: 2023-06-01-preview
+azure_endpoint: https://dummy.openai.azure.com
azure_model_map:
{config.fast_llm}: FAST-LLM_ID
{config.smart_llm}: SMART-LLM_ID
{config.embedding_model}: embedding-deployment-id-for-azure
"""
)
-
os.environ["USE_AZURE"] = "True"
os.environ["AZURE_CONFIG_FILE"] = str(config_file)
- config = ConfigBuilder.build_config_from_env(project_root=config.project_root)
+ config_with_azure = ConfigBuilder.build_config_from_env(
+ project_root=config.project_root
+ )
+ yield config_with_azure
+ del os.environ["USE_AZURE"]
+ del os.environ["AZURE_CONFIG_FILE"]
- assert (credentials := config.openai_credentials) is not None
+
+def test_azure_config(config_with_azure: Config) -> None:
+ assert (credentials := config_with_azure.openai_credentials) is not None
assert credentials.api_type == "azure"
- assert credentials.api_base == SecretStr("https://dummy.openai.azure.com")
assert credentials.api_version == "2023-06-01-preview"
+ assert credentials.azure_endpoint == SecretStr("https://dummy.openai.azure.com")
assert credentials.azure_model_to_deploy_id_map == {
- config.fast_llm: "FAST-LLM_ID",
- config.smart_llm: "SMART-LLM_ID",
- config.embedding_model: "embedding-deployment-id-for-azure",
+ config_with_azure.fast_llm: "FAST-LLM_ID",
+ config_with_azure.smart_llm: "SMART-LLM_ID",
+ config_with_azure.embedding_model: "embedding-deployment-id-for-azure",
}
- fast_llm = config.fast_llm
- smart_llm = config.smart_llm
+ fast_llm = config_with_azure.fast_llm
+ smart_llm = config_with_azure.smart_llm
assert (
- credentials.get_api_access_kwargs(config.fast_llm)["deployment_id"]
+ credentials.get_model_access_kwargs(config_with_azure.fast_llm)["model"]
== "FAST-LLM_ID"
)
assert (
- credentials.get_api_access_kwargs(config.smart_llm)["deployment_id"]
+ credentials.get_model_access_kwargs(config_with_azure.smart_llm)["model"]
== "SMART-LLM_ID"
)
# Emulate --gpt4only
- config.fast_llm = smart_llm
+ config_with_azure.fast_llm = smart_llm
assert (
- credentials.get_api_access_kwargs(config.fast_llm)["deployment_id"]
+ credentials.get_model_access_kwargs(config_with_azure.fast_llm)["model"]
== "SMART-LLM_ID"
)
assert (
- credentials.get_api_access_kwargs(config.smart_llm)["deployment_id"]
+ credentials.get_model_access_kwargs(config_with_azure.smart_llm)["model"]
== "SMART-LLM_ID"
)
# Emulate --gpt3only
- config.fast_llm = config.smart_llm = fast_llm
+ config_with_azure.fast_llm = config_with_azure.smart_llm = fast_llm
assert (
- credentials.get_api_access_kwargs(config.fast_llm)["deployment_id"]
+ credentials.get_model_access_kwargs(config_with_azure.fast_llm)["model"]
== "FAST-LLM_ID"
)
assert (
- credentials.get_api_access_kwargs(config.smart_llm)["deployment_id"]
+ credentials.get_model_access_kwargs(config_with_azure.smart_llm)["model"]
== "FAST-LLM_ID"
)
- del os.environ["USE_AZURE"]
- del os.environ["AZURE_CONFIG_FILE"]
-
-def test_create_config_gpt4only(config: Config) -> None:
- with mock.patch("autogpt.llm.api_manager.ApiManager.get_models") as mock_get_models:
- mock_get_models.return_value = [{"id": GPT_4_MODEL}]
- apply_overrides_to_config(
+@pytest.mark.asyncio
+async def test_create_config_gpt4only(config: Config) -> None:
+ with mock.patch(
+ "autogpt.core.resource.model_providers.openai.OpenAIProvider.get_available_models"
+ ) as mock_get_models:
+ mock_get_models.return_value = [
+ ChatModelInfo(
+ name=GPT_4_MODEL,
+ provider_name=ModelProviderName.OPENAI,
+ max_tokens=4096,
+ )
+ ]
+ await apply_overrides_to_config(
config=config,
gpt4only=True,
)
@@ -199,10 +165,19 @@ def test_create_config_gpt4only(config: Config) -> None:
assert config.smart_llm == GPT_4_MODEL
-def test_create_config_gpt3only(config: Config) -> None:
- with mock.patch("autogpt.llm.api_manager.ApiManager.get_models") as mock_get_models:
- mock_get_models.return_value = [{"id": GPT_3_MODEL}]
- apply_overrides_to_config(
+@pytest.mark.asyncio
+async def test_create_config_gpt3only(config: Config) -> None:
+ with mock.patch(
+ "autogpt.core.resource.model_providers.openai.OpenAIProvider.get_available_models"
+ ) as mock_get_models:
+ mock_get_models.return_value = [
+ ChatModelInfo(
+ name=GPT_3_MODEL,
+ provider_name=ModelProviderName.OPENAI,
+ max_tokens=4096,
+ )
+ ]
+ await apply_overrides_to_config(
config=config,
gpt3only=True,
)
diff --git a/autogpts/autogpt/tests/unit/test_file_operations.py b/autogpts/autogpt/tests/unit/test_file_operations.py
index 21ebd0b32..94bff3c7f 100644
--- a/autogpts/autogpt/tests/unit/test_file_operations.py
+++ b/autogpts/autogpt/tests/unit/test_file_operations.py
@@ -1,7 +1,5 @@
-import hashlib
import os
import re
-from io import TextIOWrapper
from pathlib import Path
import pytest
@@ -11,7 +9,7 @@ import autogpt.commands.file_operations as file_ops
from autogpt.agents.agent import Agent
from autogpt.agents.utils.exceptions import DuplicateOperationError
from autogpt.config import Config
-from autogpt.file_workspace import FileWorkspace
+from autogpt.file_storage import FileStorage
from autogpt.memory.vector.memory_item import MemoryItem
from autogpt.memory.vector.utils import Embedding
@@ -46,40 +44,22 @@ def test_file_name():
@pytest.fixture
-def test_file_path(test_file_name: Path, workspace: FileWorkspace):
- return workspace.get_path(test_file_name)
+def test_file_path(test_file_name: Path, storage: FileStorage):
+ return storage.get_path(test_file_name)
@pytest.fixture()
-def test_file(test_file_path: Path):
- file = open(test_file_path, "w")
- yield file
- if not file.closed:
- file.close()
+def test_directory(storage: FileStorage):
+ return storage.get_path("test_directory")
@pytest.fixture()
-def test_file_with_content_path(test_file: TextIOWrapper, file_content, agent: Agent):
- test_file.write(file_content)
- test_file.close()
- file_ops.log_operation(
- "write", Path(test_file.name), agent, file_ops.text_checksum(file_content)
- )
- return Path(test_file.name)
-
-
-@pytest.fixture()
-def test_directory(workspace: FileWorkspace):
- return workspace.get_path("test_directory")
-
+def test_nested_file(storage: FileStorage):
+ return storage.get_path("nested/test_file.txt")
-@pytest.fixture()
-def test_nested_file(workspace: FileWorkspace):
- return workspace.get_path("nested/test_file.txt")
-
-def test_file_operations_log(test_file: TextIOWrapper):
- log_file_content = (
+def test_file_operations_log():
+ all_logs = (
"File Operation Logger\n"
"write: path/to/file1.txt #checksum1\n"
"write: path/to/file2.txt #checksum2\n"
@@ -87,8 +67,7 @@ def test_file_operations_log(test_file: TextIOWrapper):
"append: path/to/file2.txt #checksum4\n"
"delete: path/to/file3.txt\n"
)
- test_file.write(log_file_content)
- test_file.close()
+ logs = all_logs.split("\n")
expected = [
("write", "path/to/file1.txt", "checksum1"),
@@ -97,28 +76,7 @@ def test_file_operations_log(test_file: TextIOWrapper):
("append", "path/to/file2.txt", "checksum4"),
("delete", "path/to/file3.txt", None),
]
- assert list(file_ops.operations_from_log(test_file.name)) == expected
-
-
-def test_file_operations_state(test_file: TextIOWrapper):
- # Prepare a fake log file
- log_file_content = (
- "File Operation Logger\n"
- "write: path/to/file1.txt #checksum1\n"
- "write: path/to/file2.txt #checksum2\n"
- "write: path/to/file3.txt #checksum3\n"
- "append: path/to/file2.txt #checksum4\n"
- "delete: path/to/file3.txt\n"
- )
- test_file.write(log_file_content)
- test_file.close()
-
- # Call the function and check the returned dictionary
- expected_state = {
- "path/to/file1.txt": "checksum1",
- "path/to/file2.txt": "checksum4",
- }
- assert file_ops.file_operations_state(test_file.name) == expected_state
+ assert list(file_ops.operations_from_log(logs)) == expected
def test_is_duplicate_operation(agent: Agent, mocker: MockerFixture):
@@ -167,11 +125,11 @@ def test_is_duplicate_operation(agent: Agent, mocker: MockerFixture):
# Test logging a file operation
-def test_log_operation(agent: Agent):
- file_ops.log_operation("log_test", Path("path/to/test"), agent=agent)
- with open(agent.file_manager.file_ops_log_path, "r", encoding="utf-8") as f:
- content = f.read()
- assert "log_test: path/to/test\n" in content
+@pytest.mark.asyncio
+async def test_log_operation(agent: Agent):
+ await file_ops.log_operation("log_test", Path("path/to/test"), agent=agent)
+ log_entry = agent.get_file_operation_lines()[-1]
+ assert "log_test: path/to/test" in log_entry
def test_text_checksum(file_content: str):
@@ -181,22 +139,27 @@ def test_text_checksum(file_content: str):
assert checksum != different_checksum
-def test_log_operation_with_checksum(agent: Agent):
- file_ops.log_operation(
+@pytest.mark.asyncio
+async def test_log_operation_with_checksum(agent: Agent):
+ await file_ops.log_operation(
"log_test", Path("path/to/test"), agent=agent, checksum="ABCDEF"
)
- with open(agent.file_manager.file_ops_log_path, "r", encoding="utf-8") as f:
- content = f.read()
- assert "log_test: path/to/test #ABCDEF\n" in content
+ log_entry = agent.get_file_operation_lines()[-1]
+ assert "log_test: path/to/test #ABCDEF" in log_entry
-def test_read_file(
+@pytest.mark.asyncio
+async def test_read_file(
mock_MemoryItem_from_text,
- test_file_with_content_path: Path,
+ test_file_path: Path,
file_content,
agent: Agent,
):
- content = file_ops.read_file(test_file_with_content_path, agent=agent)
+ await agent.workspace.write_file(test_file_path.name, file_content)
+ await file_ops.log_operation(
+ "write", Path(test_file_path.name), agent, file_ops.text_checksum(file_content)
+ )
+ content = file_ops.read_file(test_file_path.name, agent=agent)
assert content.replace("\r", "") == file_content
@@ -229,15 +192,14 @@ async def test_write_file_logs_checksum(test_file_name: Path, agent: Agent):
new_content = "This is new content.\n"
new_checksum = file_ops.text_checksum(new_content)
await file_ops.write_to_file(test_file_name, new_content, agent=agent)
- with open(agent.file_manager.file_ops_log_path, "r", encoding="utf-8") as f:
- log_entry = f.read()
- assert log_entry == f"write: {test_file_name} #{new_checksum}\n"
+ log_entry = agent.get_file_operation_lines()[-1]
+ assert log_entry == f"write: {test_file_name} #{new_checksum}"
@pytest.mark.asyncio
async def test_write_file_fails_if_content_exists(test_file_name: Path, agent: Agent):
new_content = "This is new content.\n"
- file_ops.log_operation(
+ await file_ops.log_operation(
"write",
test_file_name,
agent=agent,
@@ -249,81 +211,42 @@ async def test_write_file_fails_if_content_exists(test_file_name: Path, agent: A
@pytest.mark.asyncio
async def test_write_file_succeeds_if_content_different(
- test_file_with_content_path: Path, agent: Agent
+ test_file_path: Path, file_content: str, agent: Agent
):
+ await agent.workspace.write_file(test_file_path.name, file_content)
+ await file_ops.log_operation(
+ "write", Path(test_file_path.name), agent, file_ops.text_checksum(file_content)
+ )
new_content = "This is different content.\n"
- await file_ops.write_to_file(test_file_with_content_path, new_content, agent=agent)
+ await file_ops.write_to_file(test_file_path.name, new_content, agent=agent)
@pytest.mark.asyncio
-async def test_append_to_file(test_nested_file: Path, agent: Agent):
- append_text = "This is appended text.\n"
- await file_ops.write_to_file(test_nested_file, append_text, agent=agent)
-
- file_ops.append_to_file(test_nested_file, append_text, agent=agent)
+async def test_list_files(agent: Agent):
+ # Create files A and B
+ file_a_name = "file_a.txt"
+ file_b_name = "file_b.txt"
+ test_directory = Path("test_directory")
- with open(test_nested_file, "r") as f:
- content_after = f.read()
-
- assert content_after == append_text + append_text
-
-
-def test_append_to_file_uses_checksum_from_appended_file(
- test_file_name: Path, agent: Agent
-):
- append_text = "This is appended text.\n"
- file_ops.append_to_file(
- agent.workspace.get_path(test_file_name),
- append_text,
- agent=agent,
- )
- file_ops.append_to_file(
- agent.workspace.get_path(test_file_name),
- append_text,
- agent=agent,
- )
- with open(agent.file_manager.file_ops_log_path, "r", encoding="utf-8") as f:
- log_contents = f.read()
-
- digest = hashlib.md5()
- digest.update(append_text.encode("utf-8"))
- checksum1 = digest.hexdigest()
- digest.update(append_text.encode("utf-8"))
- checksum2 = digest.hexdigest()
- assert log_contents == (
- f"append: {test_file_name} #{checksum1}\n"
- f"append: {test_file_name} #{checksum2}\n"
- )
-
-
-def test_list_files(workspace: FileWorkspace, test_directory: Path, agent: Agent):
- # Case 1: Create files A and B, search for A, and ensure we don't return A and B
- file_a = workspace.get_path("file_a.txt")
- file_b = workspace.get_path("file_b.txt")
-
- with open(file_a, "w") as f:
- f.write("This is file A.")
-
- with open(file_b, "w") as f:
- f.write("This is file B.")
+ await agent.workspace.write_file(file_a_name, "This is file A.")
+ await agent.workspace.write_file(file_b_name, "This is file B.")
# Create a subdirectory and place a copy of file_a in it
- if not os.path.exists(test_directory):
- os.makedirs(test_directory)
-
- with open(os.path.join(test_directory, file_a.name), "w") as f:
- f.write("This is file A in the subdirectory.")
+ agent.workspace.make_dir(test_directory)
+ await agent.workspace.write_file(
+ test_directory / file_a_name, "This is file A in the subdirectory."
+ )
- files = file_ops.list_folder(str(workspace.root), agent=agent)
- assert file_a.name in files
- assert file_b.name in files
- assert os.path.join(Path(test_directory).name, file_a.name) in files
+ files = file_ops.list_folder(".", agent=agent)
+ assert file_a_name in files
+ assert file_b_name in files
+ assert os.path.join(test_directory, file_a_name) in files
# Clean up
- os.remove(file_a)
- os.remove(file_b)
- os.remove(os.path.join(test_directory, file_a.name))
- os.rmdir(test_directory)
+ agent.workspace.delete_file(file_a_name)
+ agent.workspace.delete_file(file_b_name)
+ agent.workspace.delete_file(test_directory / file_a_name)
+ agent.workspace.delete_dir(test_directory)
# Case 2: Search for a file that does not exist and make sure we don't throw
non_existent_file = "non_existent_file.txt"
diff --git a/autogpts/autogpt/tests/unit/test_gcs_file_storage.py b/autogpts/autogpt/tests/unit/test_gcs_file_storage.py
new file mode 100644
index 000000000..a9dcd0103
--- /dev/null
+++ b/autogpts/autogpt/tests/unit/test_gcs_file_storage.py
@@ -0,0 +1,200 @@
+import os
+import uuid
+from pathlib import Path
+
+import pytest
+import pytest_asyncio
+from google.auth.exceptions import GoogleAuthError
+from google.cloud import storage
+from google.cloud.exceptions import NotFound
+
+from autogpt.file_storage.gcs import GCSFileStorage, GCSFileStorageConfiguration
+
+try:
+ storage.Client()
+except GoogleAuthError:
+ pytest.skip("Google Cloud Authentication not configured", allow_module_level=True)
+
+
+@pytest.fixture(scope="module")
+def gcs_bucket_name() -> str:
+ return f"test-bucket-{str(uuid.uuid4())[:8]}"
+
+
+@pytest.fixture(scope="module")
+def gcs_root() -> Path:
+ return Path("/workspaces/AutoGPT-some-unique-task-id")
+
+
+@pytest.fixture(scope="module")
+def gcs_storage_uninitialized(gcs_bucket_name: str, gcs_root: Path) -> GCSFileStorage:
+ os.environ["STORAGE_BUCKET"] = gcs_bucket_name
+ storage_config = GCSFileStorageConfiguration.from_env()
+ storage_config.root = gcs_root
+ storage = GCSFileStorage(storage_config)
+ yield storage # type: ignore
+ del os.environ["STORAGE_BUCKET"]
+
+
+def test_initialize(gcs_bucket_name: str, gcs_storage_uninitialized: GCSFileStorage):
+ gcs = gcs_storage_uninitialized._gcs
+
+ # test that the bucket doesn't exist yet
+ with pytest.raises(NotFound):
+ gcs.get_bucket(gcs_bucket_name)
+
+ gcs_storage_uninitialized.initialize()
+
+ # test that the bucket has been created
+ bucket = gcs.get_bucket(gcs_bucket_name)
+
+ # clean up
+ bucket.delete(force=True)
+
+
+@pytest.fixture(scope="module")
+def gcs_storage(gcs_storage_uninitialized: GCSFileStorage) -> GCSFileStorage:
+ (gcs_storage := gcs_storage_uninitialized).initialize()
+ yield gcs_storage # type: ignore
+
+ # Empty & delete the test bucket
+ gcs_storage._bucket.delete(force=True)
+
+
+def test_workspace_bucket_name(
+ gcs_storage: GCSFileStorage,
+ gcs_bucket_name: str,
+):
+ assert gcs_storage._bucket.name == gcs_bucket_name
+
+
+NESTED_DIR = "existing/test/dir"
+TEST_FILES: list[tuple[str | Path, str]] = [
+ ("existing_test_file_1", "test content 1"),
+ ("existing_test_file_2.txt", "test content 2"),
+ (Path("existing_test_file_3"), "test content 3"),
+ (Path(f"{NESTED_DIR}/test_file_4"), "test content 4"),
+]
+
+
+@pytest_asyncio.fixture
+async def gcs_storage_with_files(gcs_storage: GCSFileStorage) -> GCSFileStorage:
+ for file_name, file_content in TEST_FILES:
+ gcs_storage._bucket.blob(
+ str(gcs_storage.get_path(file_name))
+ ).upload_from_string(file_content)
+ yield gcs_storage # type: ignore
+
+
+@pytest.mark.asyncio
+async def test_read_file(gcs_storage_with_files: GCSFileStorage):
+ for file_name, file_content in TEST_FILES:
+ content = gcs_storage_with_files.read_file(file_name)
+ assert content == file_content
+
+ with pytest.raises(NotFound):
+ gcs_storage_with_files.read_file("non_existent_file")
+
+
+def test_list_files(gcs_storage_with_files: GCSFileStorage):
+ # List at root level
+ assert (
+ files := gcs_storage_with_files.list_files()
+ ) == gcs_storage_with_files.list_files()
+ assert len(files) > 0
+ assert set(files) == set(Path(file_name) for file_name, _ in TEST_FILES)
+
+ # List at nested path
+ assert (
+ nested_files := gcs_storage_with_files.list_files(NESTED_DIR)
+ ) == gcs_storage_with_files.list_files(NESTED_DIR)
+ assert len(nested_files) > 0
+ assert set(nested_files) == set(
+ p.relative_to(NESTED_DIR)
+ for file_name, _ in TEST_FILES
+ if (p := Path(file_name)).is_relative_to(NESTED_DIR)
+ )
+
+
+def test_list_folders(gcs_storage_with_files: GCSFileStorage):
+ # List recursive
+ folders = gcs_storage_with_files.list_folders(recursive=True)
+ assert len(folders) > 0
+ assert set(folders) == {
+ Path("existing"),
+ Path("existing/test"),
+ Path("existing/test/dir"),
+ }
+ # List non-recursive
+ folders = gcs_storage_with_files.list_folders(recursive=False)
+ assert len(folders) > 0
+ assert set(folders) == {Path("existing")}
+
+
+@pytest.mark.asyncio
+async def test_write_read_file(gcs_storage: GCSFileStorage):
+ await gcs_storage.write_file("test_file", "test_content")
+ assert gcs_storage.read_file("test_file") == "test_content"
+
+
+@pytest.mark.asyncio
+async def test_overwrite_file(gcs_storage_with_files: GCSFileStorage):
+ for file_name, _ in TEST_FILES:
+ await gcs_storage_with_files.write_file(file_name, "new content")
+ assert gcs_storage_with_files.read_file(file_name) == "new content"
+
+
+def test_delete_file(gcs_storage_with_files: GCSFileStorage):
+ for file_to_delete, _ in TEST_FILES:
+ gcs_storage_with_files.delete_file(file_to_delete)
+ assert not gcs_storage_with_files.exists(file_to_delete)
+
+
+def test_exists(gcs_storage_with_files: GCSFileStorage):
+ for file_name, _ in TEST_FILES:
+ assert gcs_storage_with_files.exists(file_name)
+
+ assert not gcs_storage_with_files.exists("non_existent_file")
+
+
+def test_rename_file(gcs_storage_with_files: GCSFileStorage):
+ for file_name, _ in TEST_FILES:
+ new_name = str(file_name) + "_renamed"
+ gcs_storage_with_files.rename(file_name, new_name)
+ assert gcs_storage_with_files.exists(new_name)
+ assert not gcs_storage_with_files.exists(file_name)
+
+
+def test_rename_dir(gcs_storage_with_files: GCSFileStorage):
+ gcs_storage_with_files.rename(NESTED_DIR, "existing/test/dir_renamed")
+ assert gcs_storage_with_files.exists("existing/test/dir_renamed")
+ assert not gcs_storage_with_files.exists(NESTED_DIR)
+
+
+def test_clone(gcs_storage_with_files: GCSFileStorage, gcs_root: Path):
+ cloned = gcs_storage_with_files.clone_with_subroot("existing/test")
+ assert cloned.root == gcs_root / Path("existing/test")
+ assert cloned._bucket.name == gcs_storage_with_files._bucket.name
+ assert cloned.exists("dir")
+ assert cloned.exists("dir/test_file_4")
+
+
+@pytest.mark.asyncio
+async def test_copy_file(storage: GCSFileStorage):
+ await storage.write_file("test_file.txt", "test content")
+ storage.copy("test_file.txt", "test_file_copy.txt")
+ storage.make_dir("dir")
+ storage.copy("test_file.txt", "dir/test_file_copy.txt")
+ assert storage.read_file("test_file_copy.txt") == "test content"
+ assert storage.read_file("dir/test_file_copy.txt") == "test content"
+
+
+@pytest.mark.asyncio
+async def test_copy_dir(storage: GCSFileStorage):
+ storage.make_dir("dir")
+ storage.make_dir("dir/sub_dir")
+ await storage.write_file("dir/test_file.txt", "test content")
+ await storage.write_file("dir/sub_dir/test_file.txt", "test content")
+ storage.copy("dir", "dir_copy")
+ assert storage.read_file("dir_copy/test_file.txt") == "test content"
+ assert storage.read_file("dir_copy/sub_dir/test_file.txt") == "test content"
diff --git a/autogpts/autogpt/tests/unit/test_gcs_file_workspace.py b/autogpts/autogpt/tests/unit/test_gcs_file_workspace.py
deleted file mode 100644
index 6372a91cd..000000000
--- a/autogpts/autogpt/tests/unit/test_gcs_file_workspace.py
+++ /dev/null
@@ -1,131 +0,0 @@
-import os
-import uuid
-from pathlib import Path
-
-import pytest
-import pytest_asyncio
-from google.auth.exceptions import GoogleAuthError
-from google.cloud import storage
-from google.cloud.exceptions import NotFound
-
-from autogpt.file_workspace.gcs import GCSFileWorkspace, GCSFileWorkspaceConfiguration
-
-try:
- storage.Client()
-except GoogleAuthError:
- pytest.skip("Google Cloud Authentication not configured", allow_module_level=True)
-
-
-@pytest.fixture
-def gcs_bucket_name() -> str:
- return f"test-bucket-{str(uuid.uuid4())[:8]}"
-
-
-@pytest.fixture
-def gcs_workspace_uninitialized(gcs_bucket_name: str) -> GCSFileWorkspace:
- os.environ["WORKSPACE_STORAGE_BUCKET"] = gcs_bucket_name
- ws_config = GCSFileWorkspaceConfiguration.from_env()
- ws_config.root = Path("/workspaces/AutoGPT-some-unique-task-id")
- workspace = GCSFileWorkspace(ws_config)
- yield workspace # type: ignore
- del os.environ["WORKSPACE_STORAGE_BUCKET"]
-
-
-def test_initialize(
- gcs_bucket_name: str, gcs_workspace_uninitialized: GCSFileWorkspace
-):
- gcs = gcs_workspace_uninitialized._gcs
-
- # test that the bucket doesn't exist yet
- with pytest.raises(NotFound):
- gcs.get_bucket(gcs_bucket_name)
-
- gcs_workspace_uninitialized.initialize()
-
- # test that the bucket has been created
- bucket = gcs.get_bucket(gcs_bucket_name)
-
- # clean up
- bucket.delete(force=True)
-
-
-@pytest.fixture
-def gcs_workspace(gcs_workspace_uninitialized: GCSFileWorkspace) -> GCSFileWorkspace:
- (gcs_workspace := gcs_workspace_uninitialized).initialize()
- yield gcs_workspace # type: ignore
-
- # Empty & delete the test bucket
- gcs_workspace._bucket.delete(force=True)
-
-
-def test_workspace_bucket_name(
- gcs_workspace: GCSFileWorkspace,
- gcs_bucket_name: str,
-):
- assert gcs_workspace._bucket.name == gcs_bucket_name
-
-
-NESTED_DIR = "existing/test/dir"
-TEST_FILES: list[tuple[str | Path, str]] = [
- ("existing_test_file_1", "test content 1"),
- ("existing_test_file_2.txt", "test content 2"),
- (Path("existing_test_file_3"), "test content 3"),
- (Path(f"{NESTED_DIR}/test/file/4"), "test content 4"),
-]
-
-
-@pytest_asyncio.fixture
-async def gcs_workspace_with_files(gcs_workspace: GCSFileWorkspace) -> GCSFileWorkspace:
- for file_name, file_content in TEST_FILES:
- gcs_workspace._bucket.blob(
- str(gcs_workspace.get_path(file_name))
- ).upload_from_string(file_content)
- yield gcs_workspace # type: ignore
-
-
-@pytest.mark.asyncio
-async def test_read_file(gcs_workspace_with_files: GCSFileWorkspace):
- for file_name, file_content in TEST_FILES:
- content = gcs_workspace_with_files.read_file(file_name)
- assert content == file_content
-
- with pytest.raises(NotFound):
- gcs_workspace_with_files.read_file("non_existent_file")
-
-
-def test_list_files(gcs_workspace_with_files: GCSFileWorkspace):
- # List at root level
- assert (files := gcs_workspace_with_files.list()) == gcs_workspace_with_files.list()
- assert len(files) > 0
- assert set(files) == set(Path(file_name) for file_name, _ in TEST_FILES)
-
- # List at nested path
- assert (
- nested_files := gcs_workspace_with_files.list(NESTED_DIR)
- ) == gcs_workspace_with_files.list(NESTED_DIR)
- assert len(nested_files) > 0
- assert set(nested_files) == set(
- p.relative_to(NESTED_DIR)
- for file_name, _ in TEST_FILES
- if (p := Path(file_name)).is_relative_to(NESTED_DIR)
- )
-
-
-@pytest.mark.asyncio
-async def test_write_read_file(gcs_workspace: GCSFileWorkspace):
- await gcs_workspace.write_file("test_file", "test_content")
- assert gcs_workspace.read_file("test_file") == "test_content"
-
-
-@pytest.mark.asyncio
-async def test_overwrite_file(gcs_workspace_with_files: GCSFileWorkspace):
- for file_name, _ in TEST_FILES:
- await gcs_workspace_with_files.write_file(file_name, "new content")
- assert gcs_workspace_with_files.read_file(file_name) == "new content"
-
-
-def test_delete_file(gcs_workspace_with_files: GCSFileWorkspace):
- for file_to_delete, _ in TEST_FILES:
- gcs_workspace_with_files.delete_file(file_to_delete)
- with pytest.raises(NotFound):
- gcs_workspace_with_files.read_file(file_to_delete)
diff --git a/autogpts/autogpt/tests/unit/test_git_commands.py b/autogpts/autogpt/tests/unit/test_git_commands.py
index 42bcd7b99..31272fb93 100644
--- a/autogpts/autogpt/tests/unit/test_git_commands.py
+++ b/autogpts/autogpt/tests/unit/test_git_commands.py
@@ -5,6 +5,7 @@ from git.repo.base import Repo
from autogpt.agents.agent import Agent
from autogpt.agents.utils.exceptions import CommandExecutionError
from autogpt.commands.git_operations import clone_repository
+from autogpt.file_storage.base import FileStorage
@pytest.fixture
@@ -12,13 +13,13 @@ def mock_clone_from(mocker):
return mocker.patch.object(Repo, "clone_from")
-def test_clone_auto_gpt_repository(workspace, mock_clone_from, agent: Agent):
+def test_clone_auto_gpt_repository(storage: FileStorage, mock_clone_from, agent: Agent):
mock_clone_from.return_value = None
repo = "github.com/Significant-Gravitas/Auto-GPT.git"
scheme = "https://"
url = scheme + repo
- clone_path = workspace.get_path("auto-gpt-repo")
+ clone_path = storage.get_path("auto-gpt-repo")
expected_output = f"Cloned {url} to {clone_path}"
@@ -31,9 +32,9 @@ def test_clone_auto_gpt_repository(workspace, mock_clone_from, agent: Agent):
)
-def test_clone_repository_error(workspace, mock_clone_from, agent: Agent):
+def test_clone_repository_error(storage: FileStorage, mock_clone_from, agent: Agent):
url = "https://github.com/this-repository/does-not-exist.git"
- clone_path = workspace.get_path("does-not-exist")
+ clone_path = storage.get_path("does-not-exist")
mock_clone_from.side_effect = GitCommandError(
"clone", "fatal: repository not found", ""
diff --git a/autogpts/autogpt/tests/unit/test_json_utils.py b/autogpts/autogpt/tests/unit/test_json_utils.py
new file mode 100644
index 000000000..fdd1b0f08
--- /dev/null
+++ b/autogpts/autogpt/tests/unit/test_json_utils.py
@@ -0,0 +1,93 @@
+import json
+
+import pytest
+
+from autogpt.core.utils.json_utils import json_loads
+
+_JSON_FIXABLE: list[tuple[str, str]] = [
+ # Missing comma
+ ('{"name": "John Doe" "age": 30,}', '{"name": "John Doe", "age": 30}'),
+ ("[1, 2 3]", "[1, 2, 3]"),
+ # Trailing comma
+ ('{"name": "John Doe", "age": 30,}', '{"name": "John Doe", "age": 30}'),
+ ("[1, 2, 3,]", "[1, 2, 3]"),
+ # Extra comma in object
+ ('{"name": "John Doe",, "age": 30}', '{"name": "John Doe", "age": 30}'),
+ # Extra newlines
+ ('{"name": "John Doe",\n"age": 30}', '{"name": "John Doe", "age": 30}'),
+ ("[1, 2,\n3]", "[1, 2, 3]"),
+ # Missing closing brace or bracket
+ ('{"name": "John Doe", "age": 30', '{"name": "John Doe", "age": 30}'),
+ ("[1, 2, 3", "[1, 2, 3]"),
+ # Different numerals
+ ("[+1, ---2, .5, +-4.5, 123.]", "[1, -2, 0.5, -4.5, 123]"),
+ ('{"bin": 0b1001, "hex": 0x1A, "oct": 0o17}', '{"bin": 9, "hex": 26, "oct": 15}'),
+ # Broken array
+ (
+ '[1, 2 3, "yes" true, false null, 25, {"obj": "var"}',
+ '[1, 2, 3, "yes", true, false, null, 25, {"obj": "var"}]',
+ ),
+ # Codeblock
+ (
+ '```json\n{"name": "John Doe", "age": 30}\n```',
+ '{"name": "John Doe", "age": 30}',
+ ),
+ # Mutliple problems
+ (
+ '{"name":"John Doe" "age": 30\n "empty": "","address": '
+ "// random comment\n"
+ '{"city": "New York", "state": "NY"},'
+ '"skills": ["Python" "C++", "Java",""],',
+ '{"name": "John Doe", "age": 30, "empty": "", "address": '
+ '{"city": "New York", "state": "NY"}, '
+ '"skills": ["Python", "C++", "Java", ""]}',
+ ),
+ # All good
+ (
+ '{"name": "John Doe", "age": 30, "address": '
+ '{"city": "New York", "state": "NY"}, '
+ '"skills": ["Python", "C++", "Java"]}',
+ '{"name": "John Doe", "age": 30, "address": '
+ '{"city": "New York", "state": "NY"}, '
+ '"skills": ["Python", "C++", "Java"]}',
+ ),
+ ("true", "true"),
+ ("false", "false"),
+ ("null", "null"),
+ ("123.5", "123.5"),
+ ('"Hello, World!"', '"Hello, World!"'),
+ ("{}", "{}"),
+ ("[]", "[]"),
+]
+
+_JSON_UNFIXABLE: list[tuple[str, str]] = [
+ # Broken booleans and null
+ ("[TRUE, False, NULL]", "[true, false, null]"),
+ # Missing values in array
+ ("[1, , 3]", "[1, 3]"),
+ # Leading zeros (are treated as octal)
+ ("[0023, 015]", "[23, 15]"),
+ # Missing quotes
+ ('{"name": John Doe}', '{"name": "John Doe"}'),
+ # Missing opening braces or bracket
+ ('"name": "John Doe"}', '{"name": "John Doe"}'),
+ ("1, 2, 3]", "[1, 2, 3]"),
+]
+
+
+@pytest.fixture(params=_JSON_FIXABLE)
+def fixable_json(request: pytest.FixtureRequest) -> tuple[str, str]:
+ return request.param
+
+
+@pytest.fixture(params=_JSON_UNFIXABLE)
+def unfixable_json(request: pytest.FixtureRequest) -> tuple[str, str]:
+ return request.param
+
+
+def test_json_loads_fixable(fixable_json: tuple[str, str]):
+ assert json_loads(fixable_json[0]) == json.loads(fixable_json[1])
+
+
+def test_json_loads_unfixable(unfixable_json: tuple[str, str]):
+ assert json_loads(unfixable_json[0]) != json.loads(unfixable_json[1])
diff --git a/autogpts/autogpt/tests/unit/test_local_file_storage.py b/autogpts/autogpt/tests/unit/test_local_file_storage.py
new file mode 100644
index 000000000..971a2e421
--- /dev/null
+++ b/autogpts/autogpt/tests/unit/test_local_file_storage.py
@@ -0,0 +1,211 @@
+from pathlib import Path
+
+import pytest
+
+from autogpt.file_storage.local import FileStorageConfiguration, LocalFileStorage
+
+_ACCESSIBLE_PATHS = [
+ Path("."),
+ Path("test_file.txt"),
+ Path("test_folder"),
+ Path("test_folder/test_file.txt"),
+ Path("test_folder/.."),
+ Path("test_folder/../test_file.txt"),
+ Path("test_folder/../test_folder"),
+ Path("test_folder/../test_folder/test_file.txt"),
+]
+
+_INACCESSIBLE_PATHS = (
+ [
+ # Takes us out of the workspace
+ Path(".."),
+ Path("../test_file.txt"),
+ Path("../not_auto_gpt_workspace"),
+ Path("../not_auto_gpt_workspace/test_file.txt"),
+ Path("test_folder/../.."),
+ Path("test_folder/../../test_file.txt"),
+ Path("test_folder/../../not_auto_gpt_workspace"),
+ Path("test_folder/../../not_auto_gpt_workspace/test_file.txt"),
+ ]
+ + [
+ # Contains null byte
+ Path("\0"),
+ Path("\0test_file.txt"),
+ Path("test_folder/\0"),
+ Path("test_folder/\0test_file.txt"),
+ ]
+ + [
+ # Absolute paths
+ Path("/"),
+ Path("/test_file.txt"),
+ Path("/home"),
+ ]
+)
+
+_TEST_FILES = [
+ Path("test_file.txt"),
+ Path("dir/test_file.txt"),
+ Path("dir/test_file2.txt"),
+ Path("dir/sub_dir/test_file.txt"),
+]
+
+_TEST_DIRS = [
+ Path("dir"),
+ Path("dir/sub_dir"),
+]
+
+
+@pytest.fixture()
+def storage_root(tmp_path):
+ return tmp_path / "data"
+
+
+@pytest.fixture()
+def storage(storage_root):
+ return LocalFileStorage(
+ FileStorageConfiguration(root=storage_root, restrict_to_root=True)
+ )
+
+
+@pytest.fixture()
+def content():
+ return "test content"
+
+
+@pytest.fixture(params=_ACCESSIBLE_PATHS)
+def accessible_path(request):
+ return request.param
+
+
+@pytest.fixture(params=_INACCESSIBLE_PATHS)
+def inaccessible_path(request):
+ return request.param
+
+
+@pytest.fixture(params=_TEST_FILES)
+def file_path(request):
+ return request.param
+
+
+@pytest.mark.asyncio
+async def test_open_file(file_path: Path, content: str, storage: LocalFileStorage):
+ if file_path.parent:
+ storage.make_dir(file_path.parent)
+ await storage.write_file(file_path, content)
+ file = storage.open_file(file_path)
+ assert file.read() == content
+ file.close()
+ storage.delete_file(file_path)
+
+
+@pytest.mark.asyncio
+async def test_write_read_file(content: str, storage: LocalFileStorage):
+ await storage.write_file("test_file.txt", content)
+ assert storage.read_file("test_file.txt") == content
+
+
+@pytest.mark.asyncio
+async def test_list_files(content: str, storage: LocalFileStorage):
+ storage.make_dir("dir")
+ storage.make_dir("dir/sub_dir")
+ await storage.write_file("test_file.txt", content)
+ await storage.write_file("dir/test_file.txt", content)
+ await storage.write_file("dir/test_file2.txt", content)
+ await storage.write_file("dir/sub_dir/test_file.txt", content)
+ files = storage.list_files()
+ assert Path("test_file.txt") in files
+ assert Path("dir/test_file.txt") in files
+ assert Path("dir/test_file2.txt") in files
+ assert Path("dir/sub_dir/test_file.txt") in files
+ storage.delete_file("test_file.txt")
+ storage.delete_file("dir/test_file.txt")
+ storage.delete_file("dir/test_file2.txt")
+ storage.delete_file("dir/sub_dir/test_file.txt")
+ storage.delete_dir("dir/sub_dir")
+ storage.delete_dir("dir")
+
+
+@pytest.mark.asyncio
+async def test_list_folders(content: str, storage: LocalFileStorage):
+ storage.make_dir("dir")
+ storage.make_dir("dir/sub_dir")
+ await storage.write_file("dir/test_file.txt", content)
+ await storage.write_file("dir/sub_dir/test_file.txt", content)
+ folders = storage.list_folders(recursive=False)
+ folders_recursive = storage.list_folders(recursive=True)
+ assert Path("dir") in folders
+ assert Path("dir/sub_dir") not in folders
+ assert Path("dir") in folders_recursive
+ assert Path("dir/sub_dir") in folders_recursive
+ storage.delete_file("dir/test_file.txt")
+ storage.delete_file("dir/sub_dir/test_file.txt")
+ storage.delete_dir("dir/sub_dir")
+ storage.delete_dir("dir")
+
+
+@pytest.mark.asyncio
+async def test_exists_delete_file(
+ file_path: Path, content: str, storage: LocalFileStorage
+):
+ if file_path.parent:
+ storage.make_dir(file_path.parent)
+ await storage.write_file(file_path, content)
+ assert storage.exists(file_path)
+ storage.delete_file(file_path)
+ assert not storage.exists(file_path)
+
+
+@pytest.fixture(params=_TEST_DIRS)
+def test_make_delete_dir(request, storage: LocalFileStorage):
+ storage.make_dir(request)
+ assert storage.exists(request)
+ storage.delete_dir(request)
+ assert not storage.exists(request)
+
+
+@pytest.mark.asyncio
+async def test_rename(file_path: Path, content: str, storage: LocalFileStorage):
+ if file_path.parent:
+ storage.make_dir(file_path.parent)
+ await storage.write_file(file_path, content)
+ assert storage.exists(file_path)
+ storage.rename(file_path, Path(str(file_path) + "_renamed"))
+ assert not storage.exists(file_path)
+ assert storage.exists(Path(str(file_path) + "_renamed"))
+
+
+def test_clone_with_subroot(storage: LocalFileStorage):
+ subroot = storage.clone_with_subroot("dir")
+ assert subroot.root == storage.root / "dir"
+
+
+def test_get_path_accessible(accessible_path: Path, storage: LocalFileStorage):
+ full_path = storage.get_path(accessible_path)
+ assert full_path.is_absolute()
+ assert full_path.is_relative_to(storage.root)
+
+
+def test_get_path_inaccessible(inaccessible_path: Path, storage: LocalFileStorage):
+ with pytest.raises(ValueError):
+ storage.get_path(inaccessible_path)
+
+
+@pytest.mark.asyncio
+async def test_copy_file(storage: LocalFileStorage):
+ await storage.write_file("test_file.txt", "test content")
+ storage.copy("test_file.txt", "test_file_copy.txt")
+ storage.make_dir("dir")
+ storage.copy("test_file.txt", "dir/test_file_copy.txt")
+ assert storage.read_file("test_file_copy.txt") == "test content"
+ assert storage.read_file("dir/test_file_copy.txt") == "test content"
+
+
+@pytest.mark.asyncio
+async def test_copy_dir(storage: LocalFileStorage):
+ storage.make_dir("dir")
+ storage.make_dir("dir/sub_dir")
+ await storage.write_file("dir/test_file.txt", "test content")
+ await storage.write_file("dir/sub_dir/test_file.txt", "test content")
+ storage.copy("dir", "dir_copy")
+ assert storage.read_file("dir_copy/test_file.txt") == "test content"
+ assert storage.read_file("dir_copy/sub_dir/test_file.txt") == "test content"
diff --git a/autogpts/autogpt/tests/unit/test_local_file_workspace.py b/autogpts/autogpt/tests/unit/test_local_file_workspace.py
deleted file mode 100644
index 8f57d43b0..000000000
--- a/autogpts/autogpt/tests/unit/test_local_file_workspace.py
+++ /dev/null
@@ -1,92 +0,0 @@
-from pathlib import Path
-
-import pytest
-
-from autogpt.file_workspace.local import FileWorkspaceConfiguration, LocalFileWorkspace
-
-_WORKSPACE_ROOT = Path("home/users/monty/auto_gpt_workspace")
-
-_ACCESSIBLE_PATHS = [
- Path("."),
- Path("test_file.txt"),
- Path("test_folder"),
- Path("test_folder/test_file.txt"),
- Path("test_folder/.."),
- Path("test_folder/../test_file.txt"),
- Path("test_folder/../test_folder"),
- Path("test_folder/../test_folder/test_file.txt"),
-]
-
-_INACCESSIBLE_PATHS = (
- [
- # Takes us out of the workspace
- Path(".."),
- Path("../test_file.txt"),
- Path("../not_auto_gpt_workspace"),
- Path("../not_auto_gpt_workspace/test_file.txt"),
- Path("test_folder/../.."),
- Path("test_folder/../../test_file.txt"),
- Path("test_folder/../../not_auto_gpt_workspace"),
- Path("test_folder/../../not_auto_gpt_workspace/test_file.txt"),
- ]
- + [
- # Contains null byte
- Path("\0"),
- Path("\0test_file.txt"),
- Path("test_folder/\0"),
- Path("test_folder/\0test_file.txt"),
- ]
- + [
- # Absolute paths
- Path("/"),
- Path("/test_file.txt"),
- Path("/home"),
- ]
-)
-
-
-@pytest.fixture()
-def workspace_root(tmp_path):
- return tmp_path / _WORKSPACE_ROOT
-
-
-@pytest.fixture(params=_ACCESSIBLE_PATHS)
-def accessible_path(request):
- return request.param
-
-
-@pytest.fixture(params=_INACCESSIBLE_PATHS)
-def inaccessible_path(request):
- return request.param
-
-
-def test_sanitize_path_accessible(accessible_path, workspace_root):
- full_path = LocalFileWorkspace._sanitize_path(
- accessible_path,
- root=workspace_root,
- restrict_to_root=True,
- )
- assert full_path.is_absolute()
- assert full_path.is_relative_to(workspace_root)
-
-
-def test_sanitize_path_inaccessible(inaccessible_path, workspace_root):
- with pytest.raises(ValueError):
- LocalFileWorkspace._sanitize_path(
- inaccessible_path,
- root=workspace_root,
- restrict_to_root=True,
- )
-
-
-def test_get_path_accessible(accessible_path, workspace_root):
- workspace = LocalFileWorkspace(FileWorkspaceConfiguration(root=workspace_root))
- full_path = workspace.get_path(accessible_path)
- assert full_path.is_absolute()
- assert full_path.is_relative_to(workspace_root)
-
-
-def test_get_path_inaccessible(inaccessible_path, workspace_root):
- workspace = LocalFileWorkspace(FileWorkspaceConfiguration(root=workspace_root))
- with pytest.raises(ValueError):
- workspace.get_path(inaccessible_path)
diff --git a/autogpts/autogpt/tests/unit/test_plugins.py b/autogpts/autogpt/tests/unit/test_plugins.py
index d7f57c91b..f180d92bc 100644
--- a/autogpts/autogpt/tests/unit/test_plugins.py
+++ b/autogpts/autogpt/tests/unit/test_plugins.py
@@ -88,7 +88,7 @@ def test_create_base_config(config: Config):
# Check the saved config file
with open(config.plugins_config_file, "r") as saved_config_file:
- saved_config = yaml.load(saved_config_file, Loader=yaml.FullLoader)
+ saved_config = yaml.load(saved_config_file, Loader=yaml.SafeLoader)
assert saved_config == {
"a": {"enabled": True, "config": {}},
diff --git a/autogpts/autogpt/tests/unit/test_s3_file_storage.py b/autogpts/autogpt/tests/unit/test_s3_file_storage.py
new file mode 100644
index 000000000..82bd5428c
--- /dev/null
+++ b/autogpts/autogpt/tests/unit/test_s3_file_storage.py
@@ -0,0 +1,195 @@
+import os
+import uuid
+from pathlib import Path
+
+import pytest
+import pytest_asyncio
+from botocore.exceptions import ClientError
+
+from autogpt.file_storage.s3 import S3FileStorage, S3FileStorageConfiguration
+
+if not (os.getenv("S3_ENDPOINT_URL") and os.getenv("AWS_ACCESS_KEY_ID")):
+ pytest.skip("S3 environment variables are not set", allow_module_level=True)
+
+
+@pytest.fixture
+def s3_bucket_name() -> str:
+ return f"test-bucket-{str(uuid.uuid4())[:8]}"
+
+
+@pytest.fixture
+def s3_root() -> Path:
+ return Path("/workspaces/AutoGPT-some-unique-task-id")
+
+
+@pytest.fixture
+def s3_storage_uninitialized(s3_bucket_name: str, s3_root: Path) -> S3FileStorage:
+ os.environ["STORAGE_BUCKET"] = s3_bucket_name
+ storage_config = S3FileStorageConfiguration.from_env()
+ storage_config.root = s3_root
+ storage = S3FileStorage(storage_config)
+ yield storage # type: ignore
+ del os.environ["STORAGE_BUCKET"]
+
+
+def test_initialize(s3_bucket_name: str, s3_storage_uninitialized: S3FileStorage):
+ s3 = s3_storage_uninitialized._s3
+
+ # test that the bucket doesn't exist yet
+ with pytest.raises(ClientError):
+ s3.meta.client.head_bucket(Bucket=s3_bucket_name)
+
+ s3_storage_uninitialized.initialize()
+
+ # test that the bucket has been created
+ s3.meta.client.head_bucket(Bucket=s3_bucket_name)
+
+
+def test_workspace_bucket_name(
+ s3_storage: S3FileStorage,
+ s3_bucket_name: str,
+):
+ assert s3_storage._bucket.name == s3_bucket_name
+
+
+@pytest.fixture
+def s3_storage(s3_storage_uninitialized: S3FileStorage) -> S3FileStorage:
+ (s3_storage := s3_storage_uninitialized).initialize()
+ yield s3_storage # type: ignore
+
+ # Empty & delete the test bucket
+ s3_storage._bucket.objects.all().delete()
+ s3_storage._bucket.delete()
+
+
+NESTED_DIR = "existing/test/dir"
+TEST_FILES: list[tuple[str | Path, str]] = [
+ ("existing_test_file_1", "test content 1"),
+ ("existing_test_file_2.txt", "test content 2"),
+ (Path("existing_test_file_3"), "test content 3"),
+ (Path(f"{NESTED_DIR}/test_file_4"), "test content 4"),
+]
+
+
+@pytest_asyncio.fixture
+async def s3_storage_with_files(s3_storage: S3FileStorage) -> S3FileStorage:
+ for file_name, file_content in TEST_FILES:
+ s3_storage._bucket.Object(str(s3_storage.get_path(file_name))).put(
+ Body=file_content
+ )
+ yield s3_storage # type: ignore
+
+
+@pytest.mark.asyncio
+async def test_read_file(s3_storage_with_files: S3FileStorage):
+ for file_name, file_content in TEST_FILES:
+ content = s3_storage_with_files.read_file(file_name)
+ assert content == file_content
+
+ with pytest.raises(ClientError):
+ s3_storage_with_files.read_file("non_existent_file")
+
+
+def test_list_files(s3_storage_with_files: S3FileStorage):
+ # List at root level
+ assert (
+ files := s3_storage_with_files.list_files()
+ ) == s3_storage_with_files.list_files()
+ assert len(files) > 0
+ assert set(files) == set(Path(file_name) for file_name, _ in TEST_FILES)
+
+ # List at nested path
+ assert (
+ nested_files := s3_storage_with_files.list_files(NESTED_DIR)
+ ) == s3_storage_with_files.list_files(NESTED_DIR)
+ assert len(nested_files) > 0
+ assert set(nested_files) == set(
+ p.relative_to(NESTED_DIR)
+ for file_name, _ in TEST_FILES
+ if (p := Path(file_name)).is_relative_to(NESTED_DIR)
+ )
+
+
+def test_list_folders(s3_storage_with_files: S3FileStorage):
+ # List recursive
+ folders = s3_storage_with_files.list_folders(recursive=True)
+ assert len(folders) > 0
+ assert set(folders) == {
+ Path("existing"),
+ Path("existing/test"),
+ Path("existing/test/dir"),
+ }
+ # List non-recursive
+ folders = s3_storage_with_files.list_folders(recursive=False)
+ assert len(folders) > 0
+ assert set(folders) == {Path("existing")}
+
+
+@pytest.mark.asyncio
+async def test_write_read_file(s3_storage: S3FileStorage):
+ await s3_storage.write_file("test_file", "test_content")
+ assert s3_storage.read_file("test_file") == "test_content"
+
+
+@pytest.mark.asyncio
+async def test_overwrite_file(s3_storage_with_files: S3FileStorage):
+ for file_name, _ in TEST_FILES:
+ await s3_storage_with_files.write_file(file_name, "new content")
+ assert s3_storage_with_files.read_file(file_name) == "new content"
+
+
+def test_delete_file(s3_storage_with_files: S3FileStorage):
+ for file_to_delete, _ in TEST_FILES:
+ s3_storage_with_files.delete_file(file_to_delete)
+ with pytest.raises(ClientError):
+ s3_storage_with_files.read_file(file_to_delete)
+
+
+def test_exists(s3_storage_with_files: S3FileStorage):
+ for file_name, _ in TEST_FILES:
+ assert s3_storage_with_files.exists(file_name)
+
+ assert not s3_storage_with_files.exists("non_existent_file")
+
+
+def test_rename_file(s3_storage_with_files: S3FileStorage):
+ for file_name, _ in TEST_FILES:
+ new_name = str(file_name) + "_renamed"
+ s3_storage_with_files.rename(file_name, new_name)
+ assert s3_storage_with_files.exists(new_name)
+ assert not s3_storage_with_files.exists(file_name)
+
+
+def test_rename_dir(s3_storage_with_files: S3FileStorage):
+ s3_storage_with_files.rename(NESTED_DIR, "existing/test/dir_renamed")
+ assert s3_storage_with_files.exists("existing/test/dir_renamed")
+ assert not s3_storage_with_files.exists(NESTED_DIR)
+
+
+def test_clone(s3_storage_with_files: S3FileStorage, s3_root: Path):
+ cloned = s3_storage_with_files.clone_with_subroot("existing/test")
+ assert cloned.root == s3_root / Path("existing/test")
+ assert cloned._bucket.name == s3_storage_with_files._bucket.name
+ assert cloned.exists("dir")
+ assert cloned.exists("dir/test_file_4")
+
+
+@pytest.mark.asyncio
+async def test_copy_file(storage: S3FileStorage):
+ await storage.write_file("test_file.txt", "test content")
+ storage.copy("test_file.txt", "test_file_copy.txt")
+ storage.make_dir("dir")
+ storage.copy("test_file.txt", "dir/test_file_copy.txt")
+ assert storage.read_file("test_file_copy.txt") == "test content"
+ assert storage.read_file("dir/test_file_copy.txt") == "test content"
+
+
+@pytest.mark.asyncio
+async def test_copy_dir(storage: S3FileStorage):
+ storage.make_dir("dir")
+ storage.make_dir("dir/sub_dir")
+ await storage.write_file("dir/test_file.txt", "test content")
+ await storage.write_file("dir/sub_dir/test_file.txt", "test content")
+ storage.copy("dir", "dir_copy")
+ assert storage.read_file("dir_copy/test_file.txt") == "test content"
+ assert storage.read_file("dir_copy/sub_dir/test_file.txt") == "test content"
diff --git a/autogpts/autogpt/tests/unit/test_s3_file_workspace.py b/autogpts/autogpt/tests/unit/test_s3_file_workspace.py
deleted file mode 100644
index 980d1e3b8..000000000
--- a/autogpts/autogpt/tests/unit/test_s3_file_workspace.py
+++ /dev/null
@@ -1,123 +0,0 @@
-import os
-import uuid
-from pathlib import Path
-
-import pytest
-import pytest_asyncio
-from botocore.exceptions import ClientError
-
-from autogpt.file_workspace.s3 import S3FileWorkspace, S3FileWorkspaceConfiguration
-
-if not os.getenv("S3_ENDPOINT_URL") and not os.getenv("AWS_ACCESS_KEY_ID"):
- pytest.skip("S3 environment variables are not set", allow_module_level=True)
-
-
-@pytest.fixture
-def s3_bucket_name() -> str:
- return f"test-bucket-{str(uuid.uuid4())[:8]}"
-
-
-@pytest.fixture
-def s3_workspace_uninitialized(s3_bucket_name: str) -> S3FileWorkspace:
- os.environ["WORKSPACE_STORAGE_BUCKET"] = s3_bucket_name
- ws_config = S3FileWorkspaceConfiguration.from_env()
- ws_config.root = Path("/workspaces/AutoGPT-some-unique-task-id")
- workspace = S3FileWorkspace(ws_config)
- yield workspace # type: ignore
- del os.environ["WORKSPACE_STORAGE_BUCKET"]
-
-
-def test_initialize(s3_bucket_name: str, s3_workspace_uninitialized: S3FileWorkspace):
- s3 = s3_workspace_uninitialized._s3
-
- # test that the bucket doesn't exist yet
- with pytest.raises(ClientError):
- s3.meta.client.head_bucket(Bucket=s3_bucket_name)
-
- s3_workspace_uninitialized.initialize()
-
- # test that the bucket has been created
- s3.meta.client.head_bucket(Bucket=s3_bucket_name)
-
-
-def test_workspace_bucket_name(
- s3_workspace: S3FileWorkspace,
- s3_bucket_name: str,
-):
- assert s3_workspace._bucket.name == s3_bucket_name
-
-
-@pytest.fixture
-def s3_workspace(s3_workspace_uninitialized: S3FileWorkspace) -> S3FileWorkspace:
- (s3_workspace := s3_workspace_uninitialized).initialize()
- yield s3_workspace # type: ignore
-
- # Empty & delete the test bucket
- s3_workspace._bucket.objects.all().delete()
- s3_workspace._bucket.delete()
-
-
-NESTED_DIR = "existing/test/dir"
-TEST_FILES: list[tuple[str | Path, str]] = [
- ("existing_test_file_1", "test content 1"),
- ("existing_test_file_2.txt", "test content 2"),
- (Path("existing_test_file_3"), "test content 3"),
- (Path(f"{NESTED_DIR}/test/file/4"), "test content 4"),
-]
-
-
-@pytest_asyncio.fixture
-async def s3_workspace_with_files(s3_workspace: S3FileWorkspace) -> S3FileWorkspace:
- for file_name, file_content in TEST_FILES:
- s3_workspace._bucket.Object(str(s3_workspace.get_path(file_name))).put(
- Body=file_content
- )
- yield s3_workspace # type: ignore
-
-
-@pytest.mark.asyncio
-async def test_read_file(s3_workspace_with_files: S3FileWorkspace):
- for file_name, file_content in TEST_FILES:
- content = s3_workspace_with_files.read_file(file_name)
- assert content == file_content
-
- with pytest.raises(ClientError):
- s3_workspace_with_files.read_file("non_existent_file")
-
-
-def test_list_files(s3_workspace_with_files: S3FileWorkspace):
- # List at root level
- assert (files := s3_workspace_with_files.list()) == s3_workspace_with_files.list()
- assert len(files) > 0
- assert set(files) == set(Path(file_name) for file_name, _ in TEST_FILES)
-
- # List at nested path
- assert (
- nested_files := s3_workspace_with_files.list(NESTED_DIR)
- ) == s3_workspace_with_files.list(NESTED_DIR)
- assert len(nested_files) > 0
- assert set(nested_files) == set(
- p.relative_to(NESTED_DIR)
- for file_name, _ in TEST_FILES
- if (p := Path(file_name)).is_relative_to(NESTED_DIR)
- )
-
-
-@pytest.mark.asyncio
-async def test_write_read_file(s3_workspace: S3FileWorkspace):
- await s3_workspace.write_file("test_file", "test_content")
- assert s3_workspace.read_file("test_file") == "test_content"
-
-
-@pytest.mark.asyncio
-async def test_overwrite_file(s3_workspace_with_files: S3FileWorkspace):
- for file_name, _ in TEST_FILES:
- await s3_workspace_with_files.write_file(file_name, "new content")
- assert s3_workspace_with_files.read_file(file_name) == "new content"
-
-
-def test_delete_file(s3_workspace_with_files: S3FileWorkspace):
- for file_to_delete, _ in TEST_FILES:
- s3_workspace_with_files.delete_file(file_to_delete)
- with pytest.raises(ClientError):
- s3_workspace_with_files.read_file(file_to_delete)
diff --git a/autogpts/autogpt/tests/unit/test_text_file_parsers.py b/autogpts/autogpt/tests/unit/test_text_file_parsers.py
index d17de9c8c..c13241580 100644
--- a/autogpts/autogpt/tests/unit/test_text_file_parsers.py
+++ b/autogpts/autogpt/tests/unit/test_text_file_parsers.py
@@ -1,5 +1,6 @@
import json
import logging
+import os.path
import tempfile
from pathlib import Path
from xml.etree import ElementTree
@@ -159,7 +160,7 @@ binary_files_extensions = [".pdf", ".docx"]
def test_parsers(file_extension, c_file_creator):
created_file_path = Path(c_file_creator())
with open(created_file_path, "rb") as file:
- loaded_text = decode_textual_file(file, logger)
+ loaded_text = decode_textual_file(file, os.path.splitext(file.name)[1], logger)
assert plain_text_str in loaded_text
diff --git a/autogpts/autogpt/tests/unit/test_utils.py b/autogpts/autogpt/tests/unit/test_utils.py
index afe2497dc..9224f7212 100644
--- a/autogpts/autogpt/tests/unit/test_utils.py
+++ b/autogpts/autogpt/tests/unit/test_utils.py
@@ -1,16 +1,20 @@
+import json
import os
+from pathlib import Path
from unittest.mock import patch
import pytest
import requests
from git import InvalidGitRepositoryError
+import autogpt.app.utils
from autogpt.app.utils import (
get_bulletin_from_web,
get_current_git_branch,
get_latest_bulletin,
+ set_env_config_value,
)
-from autogpt.json_utils.utilities import extract_dict_from_response
+from autogpt.core.utils.json_utils import extract_dict_from_json
from autogpt.utils import validate_yaml_file
from tests.utils import skip_in_ci
@@ -194,30 +198,135 @@ def test_get_current_git_branch_failure(mock_repo):
def test_extract_json_from_response(valid_json_response: dict):
- emulated_response_from_openai = str(valid_json_response)
- assert (
- extract_dict_from_response(emulated_response_from_openai) == valid_json_response
- )
+ emulated_response_from_openai = json.dumps(valid_json_response)
+ assert extract_dict_from_json(emulated_response_from_openai) == valid_json_response
def test_extract_json_from_response_wrapped_in_code_block(valid_json_response: dict):
- emulated_response_from_openai = "```" + str(valid_json_response) + "```"
- assert (
- extract_dict_from_response(emulated_response_from_openai) == valid_json_response
- )
+ emulated_response_from_openai = "```" + json.dumps(valid_json_response) + "```"
+ assert extract_dict_from_json(emulated_response_from_openai) == valid_json_response
def test_extract_json_from_response_wrapped_in_code_block_with_language(
valid_json_response: dict,
):
- emulated_response_from_openai = "```json" + str(valid_json_response) + "```"
- assert (
- extract_dict_from_response(emulated_response_from_openai) == valid_json_response
- )
+ emulated_response_from_openai = "```json" + json.dumps(valid_json_response) + "```"
+ assert extract_dict_from_json(emulated_response_from_openai) == valid_json_response
def test_extract_json_from_response_json_contained_in_string(valid_json_response: dict):
- emulated_response_from_openai = "sentence1" + str(valid_json_response) + "sentence2"
- assert (
- extract_dict_from_response(emulated_response_from_openai) == valid_json_response
+ emulated_response_from_openai = (
+ "sentence1" + json.dumps(valid_json_response) + "sentence2"
)
+ assert extract_dict_from_json(emulated_response_from_openai) == valid_json_response
+
+
+@pytest.fixture
+def mock_env_file_path(tmp_path):
+ return tmp_path / ".env"
+
+
+env_file_initial_content = """
+# This is a comment
+EXISTING_KEY=EXISTING_VALUE
+
+## This is also a comment
+# DISABLED_KEY=DISABLED_VALUE
+
+# Another comment
+UNUSED_KEY=UNUSED_VALUE
+"""
+
+
+@pytest.fixture
+def mock_env_file(mock_env_file_path: Path, monkeypatch: pytest.MonkeyPatch):
+ mock_env_file_path.write_text(env_file_initial_content)
+ monkeypatch.setattr(autogpt.app.utils, "ENV_FILE_PATH", mock_env_file_path)
+ return mock_env_file_path
+
+
+@pytest.fixture
+def mock_environ(monkeypatch: pytest.MonkeyPatch):
+ env = {}
+ monkeypatch.setattr(os, "environ", env)
+ return env
+
+
+def test_set_env_config_value_updates_existing_key(
+ mock_env_file: Path, mock_environ: dict
+):
+ # Before updating, ensure the original content is as expected
+ with mock_env_file.open("r") as file:
+ assert file.readlines() == env_file_initial_content.splitlines(True)
+
+ set_env_config_value("EXISTING_KEY", "NEW_VALUE")
+ with mock_env_file.open("r") as file:
+ content = file.readlines()
+
+ # Ensure only the relevant line is altered
+ expected_content_lines = [
+ "\n",
+ "# This is a comment\n",
+ "EXISTING_KEY=NEW_VALUE\n", # existing key + new value
+ "\n",
+ "## This is also a comment\n",
+ "# DISABLED_KEY=DISABLED_VALUE\n",
+ "\n",
+ "# Another comment\n",
+ "UNUSED_KEY=UNUSED_VALUE\n",
+ ]
+ assert content == expected_content_lines
+ assert mock_environ["EXISTING_KEY"] == "NEW_VALUE"
+
+
+def test_set_env_config_value_uncomments_and_updates_disabled_key(
+ mock_env_file: Path, mock_environ: dict
+):
+ # Before adding, ensure the original content is as expected
+ with mock_env_file.open("r") as file:
+ assert file.readlines() == env_file_initial_content.splitlines(True)
+
+ set_env_config_value("DISABLED_KEY", "ENABLED_NEW_VALUE")
+ with mock_env_file.open("r") as file:
+ content = file.readlines()
+
+ # Ensure only the relevant line is altered
+ expected_content_lines = [
+ "\n",
+ "# This is a comment\n",
+ "EXISTING_KEY=EXISTING_VALUE\n",
+ "\n",
+ "## This is also a comment\n",
+ "DISABLED_KEY=ENABLED_NEW_VALUE\n", # disabled -> enabled + new value
+ "\n",
+ "# Another comment\n",
+ "UNUSED_KEY=UNUSED_VALUE\n",
+ ]
+ assert content == expected_content_lines
+ assert mock_environ["DISABLED_KEY"] == "ENABLED_NEW_VALUE"
+
+
+def test_set_env_config_value_adds_new_key(mock_env_file: Path, mock_environ: dict):
+ # Before adding, ensure the original content is as expected
+ with mock_env_file.open("r") as file:
+ assert file.readlines() == env_file_initial_content.splitlines(True)
+
+ set_env_config_value("NEW_KEY", "NEW_VALUE")
+ with mock_env_file.open("r") as file:
+ content = file.readlines()
+
+ # Ensure the new key-value pair is added without altering the rest
+ expected_content_lines = [
+ "\n",
+ "# This is a comment\n",
+ "EXISTING_KEY=EXISTING_VALUE\n",
+ "\n",
+ "## This is also a comment\n",
+ "# DISABLED_KEY=DISABLED_VALUE\n",
+ "\n",
+ "# Another comment\n",
+ "UNUSED_KEY=UNUSED_VALUE\n",
+ "NEW_KEY=NEW_VALUE\n", # New key-value pair added at the end
+ ]
+ assert content == expected_content_lines
+ assert mock_environ["NEW_KEY"] == "NEW_VALUE"
diff --git a/autogpts/autogpt/tests/utils.py b/autogpts/autogpt/tests/utils.py
index fac2816a3..d039bb898 100644
--- a/autogpts/autogpt/tests/utils.py
+++ b/autogpts/autogpt/tests/utils.py
@@ -8,7 +8,3 @@ def skip_in_ci(test_function):
os.environ.get("CI") == "true",
reason="This test doesn't work on GitHub Actions.",
)(test_function)
-
-
-def get_workspace_file_path(workspace, file_name):
- return str(workspace.get_path(file_name))
diff --git a/autogpts/autogpt/tests/vcr/__init__.py b/autogpts/autogpt/tests/vcr/__init__.py
index 976f4d46d..8d477cfe2 100644
--- a/autogpts/autogpt/tests/vcr/__init__.py
+++ b/autogpts/autogpt/tests/vcr/__init__.py
@@ -2,12 +2,14 @@ import logging
import os
from hashlib import sha256
-import openai.api_requestor
import pytest
+from openai import OpenAI
+from openai._models import FinalRequestOptions
+from openai._types import Omit
+from openai._utils import is_given
from pytest_mock import MockerFixture
from .vcr_filter import (
- PROXY,
before_record_request,
before_record_response,
freeze_request_body,
@@ -17,15 +19,6 @@ DEFAULT_RECORD_MODE = "new_episodes"
BASE_VCR_CONFIG = {
"before_record_request": before_record_request,
"before_record_response": before_record_response,
- "filter_headers": [
- "Authorization",
- "AGENT-MODE",
- "AGENT-TYPE",
- "Cookie",
- "OpenAI-Organization",
- "X-OpenAI-Client-User-Agent",
- "User-Agent",
- ],
"match_on": ["method", "headers"],
}
@@ -52,30 +45,22 @@ def vcr_cassette_dir(request):
return os.path.join("tests/vcr_cassettes", test_name)
-def patch_api_base(requestor: openai.api_requestor.APIRequestor):
- new_api_base = f"{PROXY}/v1"
- requestor.api_base = new_api_base
- return requestor
-
-
@pytest.fixture
-def patched_api_requestor(mocker: MockerFixture):
- init_requestor = openai.api_requestor.APIRequestor.__init__
- prepare_request = openai.api_requestor.APIRequestor._prepare_request_raw
+def cached_openai_client(mocker: MockerFixture) -> OpenAI:
+ client = OpenAI()
+ _prepare_options = client._prepare_options
- def patched_init_requestor(requestor, *args, **kwargs):
- init_requestor(requestor, *args, **kwargs)
- patch_api_base(requestor)
+ def _patched_prepare_options(self, options: FinalRequestOptions):
+ _prepare_options(options)
- def patched_prepare_request(self, *args, **kwargs):
- url, headers, data = prepare_request(self, *args, **kwargs)
-
- if PROXY:
- headers["AGENT-MODE"] = os.environ.get("AGENT_MODE")
- headers["AGENT-TYPE"] = os.environ.get("AGENT_TYPE")
+ headers: dict[str, str | Omit] = (
+ {**options.headers} if is_given(options.headers) else {}
+ )
+ options.headers = headers
+ data: dict = options.json_data
- logging.getLogger("patched_api_requestor").debug(
- f"Outgoing API request: {headers}\n{data.decode() if data else None}"
+ logging.getLogger("cached_openai_client").debug(
+ f"Outgoing API request: {headers}\n{data if data else None}"
)
# Add hash header for cheap & fast matching on cassette playback
@@ -83,16 +68,10 @@ def patched_api_requestor(mocker: MockerFixture):
freeze_request_body(data), usedforsecurity=False
).hexdigest()
- return url, headers, data
-
- if PROXY:
- mocker.patch.object(
- openai.api_requestor.APIRequestor,
- "__init__",
- new=patched_init_requestor,
- )
mocker.patch.object(
- openai.api_requestor.APIRequestor,
- "_prepare_request_raw",
- new=patched_prepare_request,
+ client,
+ "_prepare_options",
+ new=_patched_prepare_options,
)
+
+ return client
diff --git a/autogpts/autogpt/tests/vcr/vcr_filter.py b/autogpts/autogpt/tests/vcr/vcr_filter.py
index 8bbb693b8..81c269fc5 100644
--- a/autogpts/autogpt/tests/vcr/vcr_filter.py
+++ b/autogpts/autogpt/tests/vcr/vcr_filter.py
@@ -1,16 +1,27 @@
import contextlib
import json
-import os
import re
from io import BytesIO
-from typing import Any, Dict, List
-from urllib.parse import urlparse, urlunparse
+from typing import Any
from vcr.request import Request
-PROXY = os.environ.get("PROXY")
+HOSTNAMES_TO_CACHE: list[str] = [
+ "api.openai.com",
+ "localhost:50337",
+ "duckduckgo.com",
+]
-REPLACEMENTS: List[Dict[str, str]] = [
+IGNORE_REQUEST_HEADERS: set[str | re.Pattern] = {
+ "Authorization",
+ "Cookie",
+ "OpenAI-Organization",
+ "X-OpenAI-Client-User-Agent",
+ "User-Agent",
+ re.compile(r"X-Stainless-[\w\-]+", re.IGNORECASE),
+}
+
+LLM_MESSAGE_REPLACEMENTS: list[dict[str, str]] = [
{
"regex": r"\w{3} \w{3} {1,2}\d{1,2} \d{2}:\d{2}:\d{2} \d{4}",
"replacement": "Tue Jan 1 00:00:00 2000",
@@ -21,36 +32,53 @@ REPLACEMENTS: List[Dict[str, str]] = [
},
]
-ALLOWED_HOSTNAMES: List[str] = [
- "api.openai.com",
- "localhost:50337",
- "duckduckgo.com",
-]
+OPENAI_URL = "api.openai.com"
-if PROXY:
- ALLOWED_HOSTNAMES.append(PROXY)
- ORIGINAL_URL = PROXY
-else:
- ORIGINAL_URL = "no_ci"
-NEW_URL = "api.openai.com"
+def before_record_request(request: Request) -> Request | None:
+ if not should_cache_request(request):
+ return None
+ request = filter_request_headers(request)
+ request = freeze_request(request)
+ return request
-def replace_message_content(content: str, replacements: List[Dict[str, str]]) -> str:
- for replacement in replacements:
- pattern = re.compile(replacement["regex"])
- content = pattern.sub(replacement["replacement"], content)
- return content
+def should_cache_request(request: Request) -> bool:
+ return any(hostname in request.url for hostname in HOSTNAMES_TO_CACHE)
-def freeze_request_body(json_body: str | bytes) -> bytes:
- """Remove any dynamic items from the request body"""
+def filter_request_headers(request: Request) -> Request:
+ for header_name in list(request.headers):
+ if any(
+ (
+ (type(ignore) is str and ignore.lower() == header_name.lower())
+ or (isinstance(ignore, re.Pattern) and ignore.match(header_name))
+ )
+ for ignore in IGNORE_REQUEST_HEADERS
+ ):
+ del request.headers[header_name]
+ return request
+
- try:
- body = json.loads(json_body)
- except ValueError:
- return json_body if type(json_body) is bytes else json_body.encode()
+def freeze_request(request: Request) -> Request:
+ if not request or not request.body:
+ return request
+
+ with contextlib.suppress(ValueError):
+ request.body = freeze_request_body(
+ json.loads(
+ request.body.getvalue()
+ if isinstance(request.body, BytesIO)
+ else request.body
+ )
+ )
+
+ return request
+
+
+def freeze_request_body(body: dict) -> bytes:
+ """Remove any dynamic items from the request body"""
if "messages" not in body:
return json.dumps(body, sort_keys=True).encode()
@@ -62,60 +90,21 @@ def freeze_request_body(json_body: str | bytes) -> bytes:
if "content" in message and "role" in message:
if message["role"] == "system":
message["content"] = replace_message_content(
- message["content"], REPLACEMENTS
+ message["content"], LLM_MESSAGE_REPLACEMENTS
)
return json.dumps(body, sort_keys=True).encode()
-def freeze_request(request: Request) -> Request:
- if not request or not request.body:
- return request
-
- with contextlib.suppress(ValueError):
- request.body = freeze_request_body(
- request.body.getvalue()
- if isinstance(request.body, BytesIO)
- else request.body
- )
+def replace_message_content(content: str, replacements: list[dict[str, str]]) -> str:
+ for replacement in replacements:
+ pattern = re.compile(replacement["regex"])
+ content = pattern.sub(replacement["replacement"], content)
- return request
+ return content
-def before_record_response(response: Dict[str, Any]) -> Dict[str, Any]:
+def before_record_response(response: dict[str, Any]) -> dict[str, Any]:
if "Transfer-Encoding" in response["headers"]:
del response["headers"]["Transfer-Encoding"]
return response
-
-
-def before_record_request(request: Request) -> Request | None:
- request = replace_request_hostname(request, ORIGINAL_URL, NEW_URL)
-
- filtered_request = filter_hostnames(request)
- if not filtered_request:
- return None
-
- filtered_request_without_dynamic_data = freeze_request(filtered_request)
- return filtered_request_without_dynamic_data
-
-
-def replace_request_hostname(
- request: Request, original_url: str, new_hostname: str
-) -> Request:
- parsed_url = urlparse(request.uri)
-
- if parsed_url.hostname in original_url:
- new_path = parsed_url.path.replace("/proxy_function", "")
- request.uri = urlunparse(
- parsed_url._replace(netloc=new_hostname, path=new_path, scheme="https")
- )
-
- return request
-
-
-def filter_hostnames(request: Request) -> Request | None:
- # Add your implementation here for filtering hostnames
- if any(hostname in request.url for hostname in ALLOWED_HOSTNAMES):
- return request
- else:
- return None
diff --git a/autogpts/autogpt/tests/vcr_cassettes b/autogpts/autogpt/tests/vcr_cassettes
-Subproject 03bf1eb089c19217a08ec97e814b6a3b65b4aff
+Subproject e0f7f4a599620b139e72b8233eb0defdc8339b4
diff --git a/autogpts/forge/forge/__main__.py b/autogpts/forge/forge/__main__.py
index 011eae057..d0b1536e5 100644
--- a/autogpts/forge/forge/__main__.py
+++ b/autogpts/forge/forge/__main__.py
@@ -41,5 +41,17 @@ if __name__ == "__main__":
forge.sdk.forge_log.setup_logger()
uvicorn.run(
- "forge.app:app", host="localhost", port=port, log_level="error", reload=True
+ "forge.app:app",
+ host="localhost",
+ port=int(port),
+ log_level="error",
+ # Reload on changes to code or .env
+ reload=True,
+ reload_dirs=os.path.dirname(os.path.dirname(__file__)),
+ reload_excludes="*.py", # Cancel default *.py include pattern
+ reload_includes=[
+ f"{os.path.basename(os.path.dirname(__file__))}/**/*.py",
+ ".*",
+ ".env",
+ ],
)
diff --git a/autogpts/forge/forge/actions/__init__.py b/autogpts/forge/forge/actions/__init__.py
index 46e86c8c3..36b4d1a16 100644
--- a/autogpts/forge/forge/actions/__init__.py
+++ b/autogpts/forge/forge/actions/__init__.py
@@ -1 +1 @@
-from .registry import ActionRegister, Action, action, ActionParameter
+from .registry import Action, ActionParameter, ActionRegister, action
diff --git a/autogpts/forge/forge/actions/finish.py b/autogpts/forge/forge/actions/finish.py
index 77ddbfd26..d989de328 100644
--- a/autogpts/forge/forge/actions/finish.py
+++ b/autogpts/forge/forge/actions/finish.py
@@ -1,4 +1,5 @@
-from sdk.forge_log import ForgeLogger
+from forge.sdk.forge_log import ForgeLogger
+
from .registry import action
logger = ForgeLogger(__name__)
diff --git a/autogpts/forge/forge/actions/registry.py b/autogpts/forge/forge/actions/registry.py
index 552d873f3..6f548543f 100644
--- a/autogpts/forge/forge/actions/registry.py
+++ b/autogpts/forge/forge/actions/registry.py
@@ -117,7 +117,7 @@ class ActionRegister:
).replace("/", ".")
try:
module = importlib.import_module(
- f".{action[:-3]}", package="forge.sdk.abilities"
+ f".{action[:-3]}", package="forge.actions"
)
for attr in dir(module):
func = getattr(module, attr)
diff --git a/autogpts/forge/forge/actions/web/web_search.py b/autogpts/forge/forge/actions/web/web_search.py
index 2bcc0a32d..b143fed97 100644
--- a/autogpts/forge/forge/actions/web/web_search.py
+++ b/autogpts/forge/forge/actions/web/web_search.py
@@ -2,7 +2,6 @@ from __future__ import annotations
import json
import time
-from itertools import islice
from duckduckgo_search import DDGS
@@ -42,8 +41,7 @@ async def web_search(agent, task_id: str, query: str) -> str:
if not query:
return json.dumps(search_results)
- results = DDGS().text(query)
- search_results = list(islice(results, num_results))
+ search_results = DDGS().text(query, max_results=num_results)
if search_results:
break
diff --git a/autogpts/forge/forge/actions/web/web_selenium.py b/autogpts/forge/forge/actions/web/web_selenium.py
index b2874d657..9e3c7494b 100644
--- a/autogpts/forge/forge/actions/web/web_selenium.py
+++ b/autogpts/forge/forge/actions/web/web_selenium.py
@@ -5,13 +5,16 @@ from __future__ import annotations
COMMAND_CATEGORY = "web_browse"
COMMAND_CATEGORY_TITLE = "Web Browsing"
+import functools
import logging
import re
from pathlib import Path
from sys import platform
-from typing import TYPE_CHECKING, Optional, Type, List, Tuple
+from typing import TYPE_CHECKING, Any, Callable, List, Optional, Tuple, Type
+from urllib.parse import urljoin, urlparse
from bs4 import BeautifulSoup
+from requests.compat import urljoin
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.chrome.service import Service as ChromeDriverService
@@ -33,19 +36,9 @@ from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.firefox import GeckoDriverManager
from webdriver_manager.microsoft import EdgeChromiumDriverManager as EdgeDriverManager
+from forge.sdk.errors import CommandExecutionError
from ..registry import action
-from forge.sdk.errors import *
-import functools
-import re
-from typing import Any, Callable
-from urllib.parse import urljoin, urlparse
-
-from requests.compat import urljoin
-
-
-from bs4 import BeautifulSoup
-from requests.compat import urljoin
def extract_hyperlinks(soup: BeautifulSoup, base_url: str) -> list[tuple[str, str]]:
diff --git a/autogpts/forge/forge/agent.py b/autogpts/forge/forge/agent.py
index 9f242f0cb..7757c6680 100644
--- a/autogpts/forge/forge/agent.py
+++ b/autogpts/forge/forge/agent.py
@@ -1,3 +1,4 @@
+from forge.actions import ActionRegister
from forge.sdk import (
Agent,
AgentDB,
@@ -8,8 +9,6 @@ from forge.sdk import (
TaskRequestBody,
Workspace,
)
-from forge.actions import ActionRegister
-
LOG = ForgeLogger(__name__)
diff --git a/autogpts/forge/forge/app.py b/autogpts/forge/forge/app.py
index b14856358..e04edd756 100644
--- a/autogpts/forge/forge/app.py
+++ b/autogpts/forge/forge/app.py
@@ -2,6 +2,7 @@ import os
from forge.agent import ForgeAgent
from forge.sdk import LocalWorkspace
+
from .db import ForgeDatabase
database_name = os.getenv("DATABASE_STRING")
diff --git a/autogpts/forge/forge/db.py b/autogpts/forge/forge/db.py
index eab8916ba..cff096379 100644
--- a/autogpts/forge/forge/db.py
+++ b/autogpts/forge/forge/db.py
@@ -1,14 +1,11 @@
-from .sdk import AgentDB, ForgeLogger, NotFoundError, Base
-from sqlalchemy.exc import SQLAlchemyError
-
import datetime
-from sqlalchemy import (
- Column,
- DateTime,
- String,
-)
import uuid
+from sqlalchemy import Column, DateTime, String
+from sqlalchemy.exc import SQLAlchemyError
+
+from .sdk import AgentDB, Base, ForgeLogger, NotFoundError
+
LOG = ForgeLogger(__name__)
diff --git a/autogpts/forge/forge/llm.py b/autogpts/forge/forge/llm.py
index 23639a6df..4fe850052 100644
--- a/autogpts/forge/forge/llm.py
+++ b/autogpts/forge/forge/llm.py
@@ -1,18 +1,18 @@
-import typing
+from pathlib import Path
-import openai
+from litellm import AuthenticationError, InvalidRequestError, ModelResponse, acompletion
+from openai import OpenAI
+from openai.types import CreateEmbeddingResponse
+from openai.types.audio import Transcription
from tenacity import retry, stop_after_attempt, wait_random_exponential
from .sdk.forge_log import ForgeLogger
-from litellm import completion, acompletion, AuthenticationError, InvalidRequestError
LOG = ForgeLogger(__name__)
@retry(wait=wait_random_exponential(min=1, max=40), stop=stop_after_attempt(3))
-async def chat_completion_request(
- model, messages, **kwargs
-) -> typing.Union[typing.Dict[str, typing.Any], Exception]:
+async def chat_completion_request(model, messages, **kwargs) -> ModelResponse:
"""Generate a response to a list of messages using OpenAI's API"""
try:
kwargs["model"] = model
@@ -22,8 +22,10 @@ async def chat_completion_request(
return resp
except AuthenticationError as e:
LOG.exception("Authentication Error")
+ raise
except InvalidRequestError as e:
LOG.exception("Invalid Request Error")
+ raise
except Exception as e:
LOG.error("Unable to generate ChatCompletion response")
LOG.error(f"Exception: {e}")
@@ -33,12 +35,12 @@ async def chat_completion_request(
@retry(wait=wait_random_exponential(min=1, max=40), stop=stop_after_attempt(3))
async def create_embedding_request(
messages, model="text-embedding-ada-002"
-) -> typing.Union[typing.Dict[str, typing.Any], Exception]:
+) -> CreateEmbeddingResponse:
"""Generate an embedding for a list of messages using OpenAI's API"""
try:
- return await openai.Embedding.acreate(
+ return OpenAI().embeddings.create(
input=[f"{m['role']}: {m['content']}" for m in messages],
- engine=model,
+ model=model,
)
except Exception as e:
LOG.error("Unable to generate ChatCompletion response")
@@ -47,12 +49,12 @@ async def create_embedding_request(
@retry(wait=wait_random_exponential(min=1, max=40), stop=stop_after_attempt(3))
-async def transcribe_audio(
- audio_file: str,
-) -> typing.Union[typing.Dict[str, typing.Any], Exception]:
+async def transcribe_audio(audio_file: Path) -> Transcription:
"""Transcribe an audio file using OpenAI's API"""
try:
- return await openai.Audio.transcribe(model="whisper-1", file=audio_file)
+ return OpenAI().audio.transcriptions.create(
+ model="whisper-1", file=audio_file.open(mode="rb")
+ )
except Exception as e:
LOG.error("Unable to generate ChatCompletion response")
LOG.error(f"Exception: {e}")
diff --git a/autogpts/forge/forge/memory/__init__.py b/autogpts/forge/forge/memory/__init__.py
index ad8ced929..b0182da70 100644
--- a/autogpts/forge/forge/memory/__init__.py
+++ b/autogpts/forge/forge/memory/__init__.py
@@ -1,2 +1,2 @@
-from .memstore import MemStore
from .chroma_memstore import ChromaMemStore
+from .memstore import MemStore
diff --git a/autogpts/forge/forge/memory/chroma_memstore.py b/autogpts/forge/forge/memory/chroma_memstore.py
index 8dd4971d2..7764f1ab9 100644
--- a/autogpts/forge/forge/memory/chroma_memstore.py
+++ b/autogpts/forge/forge/memory/chroma_memstore.py
@@ -1,8 +1,9 @@
-from .memstore import MemStore
+import hashlib
import chromadb
from chromadb.config import Settings
-import hashlib
+
+from .memstore import MemStore
class ChromaMemStore:
diff --git a/autogpts/forge/forge/sdk/__init__.py b/autogpts/forge/forge/sdk/__init__.py
index 366464f95..9ee9f428a 100644
--- a/autogpts/forge/forge/sdk/__init__.py
+++ b/autogpts/forge/forge/sdk/__init__.py
@@ -2,11 +2,11 @@
The Forge SDK. This is the core of the Forge. It contains the agent protocol, which is the
core of the Forge.
"""
+from ..llm import chat_completion_request, create_embedding_request, transcribe_audio
from .agent import Agent
from .db import AgentDB, Base
+from .errors import *
from .forge_log import ForgeLogger
-from ..llm import chat_completion_request, create_embedding_request, transcribe_audio
-from .prompting import PromptEngine
from .model import (
Artifact,
ArtifactUpload,
@@ -21,5 +21,5 @@ from .model import (
TaskRequestBody,
TaskStepsListResponse,
)
+from .prompting import PromptEngine
from .workspace import LocalWorkspace, Workspace
-from .errors import *
diff --git a/autogpts/forge/forge/sdk/agent.py b/autogpts/forge/forge/sdk/agent.py
index a3f5370b6..125167938 100644
--- a/autogpts/forge/forge/sdk/agent.py
+++ b/autogpts/forge/forge/sdk/agent.py
@@ -13,8 +13,17 @@ from .db import AgentDB
from .errors import NotFoundError
from .forge_log import ForgeLogger
from .middlewares import AgentMiddleware
+from .model import (
+ Artifact,
+ Step,
+ StepRequestBody,
+ Task,
+ TaskArtifactsListResponse,
+ TaskListResponse,
+ TaskRequestBody,
+ TaskStepsListResponse,
+)
from .routes.agent_protocol import base_router
-from .model import *
from .workspace import Workspace
LOG = ForgeLogger(__name__)
diff --git a/autogpts/forge/forge/sdk/db.py b/autogpts/forge/forge/sdk/db.py
index 1af538c62..ce4d22f6f 100644
--- a/autogpts/forge/forge/sdk/db.py
+++ b/autogpts/forge/forge/sdk/db.py
@@ -7,7 +7,7 @@ IT IS NOT ADVISED TO USE THIS IN PRODUCTION!
import datetime
import math
import uuid
-from typing import Any, Dict, List, Optional, Tuple
+from typing import Any, Dict, List, Literal, Optional, Tuple
from sqlalchemy import (
JSON,
@@ -311,6 +311,29 @@ class AgentDB:
LOG.error(f"Unexpected error while getting step: {e}")
raise
+ async def get_artifact(self, artifact_id: str) -> Artifact:
+ if self.debug_enabled:
+ LOG.debug(f"Getting artifact with and artifact_id: {artifact_id}")
+ try:
+ with self.Session() as session:
+ if (
+ artifact_model := session.query(ArtifactModel)
+ .filter_by(artifact_id=artifact_id)
+ .first()
+ ):
+ return convert_to_artifact(artifact_model)
+ else:
+ LOG.error(f"Artifact not found with and artifact_id: {artifact_id}")
+ raise NotFoundError("Artifact not found")
+ except SQLAlchemyError as e:
+ LOG.error(f"SQLAlchemy error while getting artifact: {e}")
+ raise
+ except NotFoundError as e:
+ raise
+ except Exception as e:
+ LOG.error(f"Unexpected error while getting artifact: {e}")
+ raise
+
async def update_step(
self,
task_id: str,
@@ -353,28 +376,32 @@ class AgentDB:
LOG.error(f"Unexpected error while getting step: {e}")
raise
- async def get_artifact(self, artifact_id: str) -> Artifact:
- if self.debug_enabled:
- LOG.debug(f"Getting artifact with and artifact_id: {artifact_id}")
- try:
- with self.Session() as session:
- if (
- artifact_model := session.query(ArtifactModel)
- .filter_by(artifact_id=artifact_id)
- .first()
- ):
- return convert_to_artifact(artifact_model)
- else:
- LOG.error(f"Artifact not found with and artifact_id: {artifact_id}")
- raise NotFoundError("Artifact not found")
- except SQLAlchemyError as e:
- LOG.error(f"SQLAlchemy error while getting artifact: {e}")
- raise
- except NotFoundError as e:
- raise
- except Exception as e:
- LOG.error(f"Unexpected error while getting artifact: {e}")
- raise
+ async def update_artifact(
+ self,
+ artifact_id: str,
+ *,
+ file_name: str = "",
+ relative_path: str = "",
+ agent_created: Optional[Literal[True]] = None,
+ ) -> Artifact:
+ LOG.debug(f"Updating artifact with artifact_id: {artifact_id}")
+ with self.Session() as session:
+ if (
+ artifact := session.query(ArtifactModel)
+ .filter_by(artifact_id=artifact_id)
+ .first()
+ ):
+ if file_name:
+ artifact.file_name = file_name
+ if relative_path:
+ artifact.relative_path = relative_path
+ if agent_created:
+ artifact.agent_created = agent_created
+ session.commit()
+ return await self.get_artifact(artifact_id)
+ else:
+ LOG.error(f"Artifact not found with artifact_id: {artifact_id}")
+ raise NotFoundError("Artifact not found")
async def list_tasks(
self, page: int = 1, per_page: int = 10
diff --git a/autogpts/forge/forge/sdk/db_test.py b/autogpts/forge/forge/sdk/db_test.py
index 6bcfd577a..14330435e 100644
--- a/autogpts/forge/forge/sdk/db_test.py
+++ b/autogpts/forge/forge/sdk/db_test.py
@@ -14,7 +14,13 @@ from forge.sdk.db import (
convert_to_task,
)
from forge.sdk.errors import NotFoundError as DataNotFoundError
-from autogpts.forge.forge.sdk.model import *
+from forge.sdk.model import (
+ Artifact,
+ Status,
+ Step,
+ StepRequestBody,
+ Task,
+)
@pytest.mark.asyncio
diff --git a/autogpts/forge/forge/sdk/routes/agent_protocol.py b/autogpts/forge/forge/sdk/routes/agent_protocol.py
index 8a46fde0b..4cab4be0c 100644
--- a/autogpts/forge/forge/sdk/routes/agent_protocol.py
+++ b/autogpts/forge/forge/sdk/routes/agent_protocol.py
@@ -31,6 +31,7 @@ from fastapi.responses import FileResponse
from forge.sdk.errors import *
from forge.sdk.forge_log import ForgeLogger
from forge.sdk.model import *
+from forge.sdk.utils import get_detailed_traceback, get_exception_message
base_router = APIRouter()
@@ -92,7 +93,13 @@ async def create_agent_task(request: Request, task_request: TaskRequestBody) ->
except Exception:
LOG.exception(f"Error whilst trying to create a task: {task_request}")
return Response(
- content=json.dumps({"error": "Internal server error"}),
+ content=json.dumps(
+ {
+ "error": "Internal server error",
+ "exception": get_exception_message(),
+ "traceback": get_detailed_traceback(),
+ }
+ ),
status_code=500,
media_type="application/json",
)
@@ -157,7 +164,13 @@ async def list_agent_tasks(
except Exception:
LOG.exception("Error whilst trying to list tasks")
return Response(
- content=json.dumps({"error": "Internal server error"}),
+ content=json.dumps(
+ {
+ "error": "Internal server error",
+ "exception": get_exception_message(),
+ "traceback": get_detailed_traceback(),
+ }
+ ),
status_code=500,
media_type="application/json",
)
@@ -218,6 +231,7 @@ async def get_agent_task(request: Request, task_id: str) -> Task:
agent = request["agent"]
try:
task = await agent.get_task(task_id)
+
return Response(
content=task.json(),
status_code=200,
@@ -233,14 +247,22 @@ async def get_agent_task(request: Request, task_id: str) -> Task:
except Exception:
LOG.exception(f"Error whilst trying to get task: {task_id}")
return Response(
- content=json.dumps({"error": "Internal server error"}),
+ content=json.dumps(
+ {
+ "error": "Internal server error",
+ "exception": get_exception_message(),
+ "traceback": get_detailed_traceback(),
+ }
+ ),
status_code=500,
media_type="application/json",
)
@base_router.get(
- "/agent/tasks/{task_id}/steps", tags=["agent"], response_model=TaskStepsListResponse
+ "/agent/tasks/{task_id}/steps",
+ tags=["agent"],
+ response_model=TaskStepsListResponse,
)
async def list_agent_task_steps(
request: Request,
@@ -300,7 +322,13 @@ async def list_agent_task_steps(
except Exception:
LOG.exception("Error whilst trying to list steps")
return Response(
- content=json.dumps({"error": "Internal server error"}),
+ content=json.dumps(
+ {
+ "error": "Internal server error",
+ "exception": get_exception_message(),
+ "traceback": get_detailed_traceback(),
+ }
+ ),
status_code=500,
media_type="application/json",
)
@@ -356,6 +384,7 @@ async def execute_agent_task_step(
step = StepRequestBody(input="y")
step = await agent.execute_step(task_id, step)
+
return Response(
content=step.json(),
status_code=200,
@@ -368,10 +397,16 @@ async def execute_agent_task_step(
status_code=404,
media_type="application/json",
)
- except Exception as e:
+ except Exception:
LOG.exception(f"Error whilst trying to execute a task step: {task_id}")
return Response(
- content=json.dumps({"error": "Internal server error"}),
+ content=json.dumps(
+ {
+ "error": "Internal server error",
+ "exception": get_exception_message(),
+ "traceback": get_detailed_traceback(),
+ }
+ ),
status_code=500,
media_type="application/json",
)
@@ -406,6 +441,7 @@ async def get_agent_task_step(request: Request, task_id: str, step_id: str) -> S
agent = request["agent"]
try:
step = await agent.get_step(task_id, step_id)
+
return Response(content=step.json(), status_code=200)
except NotFoundError:
LOG.exception(f"Error whilst trying to get step: {step_id}")
@@ -417,7 +453,13 @@ async def get_agent_task_step(request: Request, task_id: str, step_id: str) -> S
except Exception:
LOG.exception(f"Error whilst trying to get step: {step_id}")
return Response(
- content=json.dumps({"error": "Internal server error"}),
+ content=json.dumps(
+ {
+ "error": "Internal server error",
+ "exception": get_exception_message(),
+ "traceback": get_detailed_traceback(),
+ }
+ ),
status_code=500,
media_type="application/json",
)
@@ -481,7 +523,13 @@ async def list_agent_task_artifacts(
except Exception:
LOG.exception("Error whilst trying to list artifacts")
return Response(
- content=json.dumps({"error": "Internal server error"}),
+ content=json.dumps(
+ {
+ "error": "Internal server error",
+ "exception": get_exception_message(),
+ "traceback": get_detailed_traceback(),
+ }
+ ),
status_code=500,
media_type="application/json",
)
@@ -538,14 +586,22 @@ async def upload_agent_task_artifacts(
except Exception:
LOG.exception(f"Error whilst trying to upload artifact: {task_id}")
return Response(
- content=json.dumps({"error": "Internal server error"}),
+ content=json.dumps(
+ {
+ "error": "Internal server error",
+ "exception": get_exception_message(),
+ "traceback": get_detailed_traceback(),
+ }
+ ),
status_code=500,
media_type="application/json",
)
@base_router.get(
- "/agent/tasks/{task_id}/artifacts/{artifact_id}", tags=["agent"], response_model=str
+ "/agent/tasks/{task_id}/artifacts/{artifact_id}",
+ tags=["agent"],
+ response_model=str,
)
async def download_agent_task_artifact(
request: Request, task_id: str, artifact_id: str
@@ -576,7 +632,8 @@ async def download_agent_task_artifact(
return Response(
content=json.dumps(
{
- "error": f"Artifact not found - task_id: {task_id}, artifact_id: {artifact_id}"
+ "error": f"Artifact not found "
+ "- task_id: {task_id}, artifact_id: {artifact_id}"
}
),
status_code=404,
@@ -587,7 +644,10 @@ async def download_agent_task_artifact(
return Response(
content=json.dumps(
{
- "error": f"Internal server error - task_id: {task_id}, artifact_id: {artifact_id}"
+ "error": f"Internal server error "
+ "- task_id: {task_id}, artifact_id: {artifact_id}",
+ "exception": get_exception_message(),
+ "traceback": get_detailed_traceback(),
}
),
status_code=500,
diff --git a/autogpts/forge/forge/sdk/utils.py b/autogpts/forge/forge/sdk/utils.py
new file mode 100644
index 000000000..204d713fc
--- /dev/null
+++ b/autogpts/forge/forge/sdk/utils.py
@@ -0,0 +1,39 @@
+import inspect
+import sys
+import traceback
+
+
+def get_exception_message():
+ """Get current exception type and message."""
+ exc_type, exc_value, _ = sys.exc_info()
+ exception_message = f"{exc_type.__name__}: {exc_value}"
+ return exception_message
+
+
+def get_detailed_traceback():
+ """Get current exception traceback with local variables."""
+ _, _, exc_tb = sys.exc_info()
+ detailed_traceback = "Traceback (most recent call last):\n"
+ formatted_tb = traceback.format_tb(exc_tb)
+ detailed_traceback += "".join(formatted_tb)
+
+ # Optionally add local variables to the traceback information
+ detailed_traceback += "\nLocal variables by frame, innermost last:\n"
+ while exc_tb:
+ frame = exc_tb.tb_frame
+ lineno = exc_tb.tb_lineno
+ function_name = frame.f_code.co_name
+
+ # Format frame information
+ detailed_traceback += (
+ f" Frame {function_name} in {frame.f_code.co_filename} at line {lineno}\n"
+ )
+
+ # Get local variables for the frame
+ local_vars = inspect.getargvalues(frame).locals
+ for var_name, value in local_vars.items():
+ detailed_traceback += f" {var_name} = {value}\n"
+
+ exc_tb = exc_tb.tb_next
+
+ return detailed_traceback
diff --git a/autogpts/forge/forge/sdk/workspace.py b/autogpts/forge/forge/sdk/workspace.py
index aca1fd0d2..ff7c52427 100644
--- a/autogpts/forge/forge/sdk/workspace.py
+++ b/autogpts/forge/forge/sdk/workspace.py
@@ -2,6 +2,7 @@ import abc
import os
import typing
from pathlib import Path
+
from google.cloud import storage
diff --git a/autogpts/forge/poetry.lock b/autogpts/forge/poetry.lock
index 2c2980edd..e7beb7995 100644
--- a/autogpts/forge/poetry.lock
+++ b/autogpts/forge/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
[[package]]
name = "agbenchmark"
@@ -10,15 +10,16 @@ files = []
develop = false
[package.dependencies]
+agent-protocol-client = "^1.1.0"
click = "^8.1.3"
+click-default-group = "^1.2.4"
colorama = "^0.4.6"
-fastapi = "^0.99.0"
+fastapi = "^0.109.1"
gitpython = "^3.1.32"
-helicone = "^1.0.9"
httpx = "^0.24.0"
matplotlib = "^3.7.2"
networkx = "^3.1"
-openai = "^0.27.8"
+openai = "^1.7.2"
pandas = "^2.0.3"
pexpect = "^4.8.0"
psutil = "^5.9.5"
@@ -26,104 +27,119 @@ pydantic = "^1.10.9"
pytest = "^7.3.2"
pytest-asyncio = "^0.21.1"
python-dotenv = "^1.0.0"
-python-multipart = "^0.0.6"
+python-multipart = "^0.0.7"
pyvis = "^0.3.2"
requests = "^2.31.0"
selenium = "^4.11.2"
+tabulate = "^0.9.0"
toml = "^0.10.2"
types-requests = "^2.31.0.1"
uvicorn = "^0.23.2"
[package.source]
-type = "git"
-url = "https://github.com/Significant-Gravitas/AutoGPT.git"
-reference = "HEAD"
-resolved_reference = "b33f4cca6bb20ff9f42d45ec5634b0aeefe15931"
-subdirectory = "benchmark"
+type = "directory"
+url = "../../benchmark"
+
+[[package]]
+name = "agent-protocol-client"
+version = "1.1.0"
+description = "Agent Communication Protocol Client"
+optional = true
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "agent_protocol_client-1.1.0-py3-none-any.whl", hash = "sha256:0e8c6c97244189666ed18e320410abddce8c9dfb75437da1e590bbef3b6268be"},
+ {file = "agent_protocol_client-1.1.0.tar.gz", hash = "sha256:aa7e1042de1249477fdc29c2df08a44f2233dade9c02c1279e37c98e9d3a0d72"},
+]
+
+[package.dependencies]
+aiohttp = ">=3.8.4,<4.0.0"
+pydantic = ">=1.10.5,<2.0.0"
+python-dateutil = ">=2.8.2,<3.0.0"
+urllib3 = ">=1.25.3,<2.0.0"
[[package]]
name = "aiohttp"
-version = "3.9.1"
+version = "3.9.3"
description = "Async http client/server framework (asyncio)"
optional = false
python-versions = ">=3.8"
files = [
- {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1f80197f8b0b846a8d5cf7b7ec6084493950d0882cc5537fb7b96a69e3c8590"},
- {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c72444d17777865734aa1a4d167794c34b63e5883abb90356a0364a28904e6c0"},
- {file = "aiohttp-3.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b05d5cbe9dafcdc733262c3a99ccf63d2f7ce02543620d2bd8db4d4f7a22f83"},
- {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c4fa235d534b3547184831c624c0b7c1e262cd1de847d95085ec94c16fddcd5"},
- {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:289ba9ae8e88d0ba16062ecf02dd730b34186ea3b1e7489046fc338bdc3361c4"},
- {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bff7e2811814fa2271be95ab6e84c9436d027a0e59665de60edf44e529a42c1f"},
- {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81b77f868814346662c96ab36b875d7814ebf82340d3284a31681085c051320f"},
- {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b9c7426923bb7bd66d409da46c41e3fb40f5caf679da624439b9eba92043fa6"},
- {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8d44e7bf06b0c0a70a20f9100af9fcfd7f6d9d3913e37754c12d424179b4e48f"},
- {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22698f01ff5653fe66d16ffb7658f582a0ac084d7da1323e39fd9eab326a1f26"},
- {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ca7ca5abfbfe8d39e653870fbe8d7710be7a857f8a8386fc9de1aae2e02ce7e4"},
- {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:8d7f98fde213f74561be1d6d3fa353656197f75d4edfbb3d94c9eb9b0fc47f5d"},
- {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5216b6082c624b55cfe79af5d538e499cd5f5b976820eac31951fb4325974501"},
- {file = "aiohttp-3.9.1-cp310-cp310-win32.whl", hash = "sha256:0e7ba7ff228c0d9a2cd66194e90f2bca6e0abca810b786901a569c0de082f489"},
- {file = "aiohttp-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:c7e939f1ae428a86e4abbb9a7c4732bf4706048818dfd979e5e2839ce0159f23"},
- {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:df9cf74b9bc03d586fc53ba470828d7b77ce51b0582d1d0b5b2fb673c0baa32d"},
- {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ecca113f19d5e74048c001934045a2b9368d77b0b17691d905af18bd1c21275e"},
- {file = "aiohttp-3.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8cef8710fb849d97c533f259103f09bac167a008d7131d7b2b0e3a33269185c0"},
- {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea94403a21eb94c93386d559bce297381609153e418a3ffc7d6bf772f59cc35"},
- {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91c742ca59045dce7ba76cab6e223e41d2c70d79e82c284a96411f8645e2afff"},
- {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c93b7c2e52061f0925c3382d5cb8980e40f91c989563d3d32ca280069fd6a87"},
- {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee2527134f95e106cc1653e9ac78846f3a2ec1004cf20ef4e02038035a74544d"},
- {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11ff168d752cb41e8492817e10fb4f85828f6a0142b9726a30c27c35a1835f01"},
- {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b8c3a67eb87394386847d188996920f33b01b32155f0a94f36ca0e0c635bf3e3"},
- {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c7b5d5d64e2a14e35a9240b33b89389e0035e6de8dbb7ffa50d10d8b65c57449"},
- {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:69985d50a2b6f709412d944ffb2e97d0be154ea90600b7a921f95a87d6f108a2"},
- {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:c9110c06eaaac7e1f5562caf481f18ccf8f6fdf4c3323feab28a93d34cc646bd"},
- {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737e69d193dac7296365a6dcb73bbbf53bb760ab25a3727716bbd42022e8d7a"},
- {file = "aiohttp-3.9.1-cp311-cp311-win32.whl", hash = "sha256:4ee8caa925aebc1e64e98432d78ea8de67b2272252b0a931d2ac3bd876ad5544"},
- {file = "aiohttp-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:a34086c5cc285be878622e0a6ab897a986a6e8bf5b67ecb377015f06ed316587"},
- {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f800164276eec54e0af5c99feb9494c295118fc10a11b997bbb1348ba1a52065"},
- {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:500f1c59906cd142d452074f3811614be04819a38ae2b3239a48b82649c08821"},
- {file = "aiohttp-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0b0a6a36ed7e164c6df1e18ee47afbd1990ce47cb428739d6c99aaabfaf1b3af"},
- {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69da0f3ed3496808e8cbc5123a866c41c12c15baaaead96d256477edf168eb57"},
- {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:176df045597e674fa950bf5ae536be85699e04cea68fa3a616cf75e413737eb5"},
- {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b796b44111f0cab6bbf66214186e44734b5baab949cb5fb56154142a92989aeb"},
- {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f27fdaadce22f2ef950fc10dcdf8048407c3b42b73779e48a4e76b3c35bca26c"},
- {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcb6532b9814ea7c5a6a3299747c49de30e84472fa72821b07f5a9818bce0f66"},
- {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:54631fb69a6e44b2ba522f7c22a6fb2667a02fd97d636048478db2fd8c4e98fe"},
- {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4b4c452d0190c5a820d3f5c0f3cd8a28ace48c54053e24da9d6041bf81113183"},
- {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:cae4c0c2ca800c793cae07ef3d40794625471040a87e1ba392039639ad61ab5b"},
- {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:565760d6812b8d78d416c3c7cfdf5362fbe0d0d25b82fed75d0d29e18d7fc30f"},
- {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54311eb54f3a0c45efb9ed0d0a8f43d1bc6060d773f6973efd90037a51cd0a3f"},
- {file = "aiohttp-3.9.1-cp312-cp312-win32.whl", hash = "sha256:85c3e3c9cb1d480e0b9a64c658cd66b3cfb8e721636ab8b0e746e2d79a7a9eed"},
- {file = "aiohttp-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:11cb254e397a82efb1805d12561e80124928e04e9c4483587ce7390b3866d213"},
- {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8a22a34bc594d9d24621091d1b91511001a7eea91d6652ea495ce06e27381f70"},
- {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:598db66eaf2e04aa0c8900a63b0101fdc5e6b8a7ddd805c56d86efb54eb66672"},
- {file = "aiohttp-3.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c9376e2b09895c8ca8b95362283365eb5c03bdc8428ade80a864160605715f1"},
- {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41473de252e1797c2d2293804e389a6d6986ef37cbb4a25208de537ae32141dd"},
- {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c5857612c9813796960c00767645cb5da815af16dafb32d70c72a8390bbf690"},
- {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffcd828e37dc219a72c9012ec44ad2e7e3066bec6ff3aaa19e7d435dbf4032ca"},
- {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:219a16763dc0294842188ac8a12262b5671817042b35d45e44fd0a697d8c8361"},
- {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f694dc8a6a3112059258a725a4ebe9acac5fe62f11c77ac4dcf896edfa78ca28"},
- {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bcc0ea8d5b74a41b621ad4a13d96c36079c81628ccc0b30cfb1603e3dfa3a014"},
- {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:90ec72d231169b4b8d6085be13023ece8fa9b1bb495e4398d847e25218e0f431"},
- {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:cf2a0ac0615842b849f40c4d7f304986a242f1e68286dbf3bd7a835e4f83acfd"},
- {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:0e49b08eafa4f5707ecfb321ab9592717a319e37938e301d462f79b4e860c32a"},
- {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2c59e0076ea31c08553e868cec02d22191c086f00b44610f8ab7363a11a5d9d8"},
- {file = "aiohttp-3.9.1-cp38-cp38-win32.whl", hash = "sha256:4831df72b053b1eed31eb00a2e1aff6896fb4485301d4ccb208cac264b648db4"},
- {file = "aiohttp-3.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:3135713c5562731ee18f58d3ad1bf41e1d8883eb68b363f2ffde5b2ea4b84cc7"},
- {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cfeadf42840c1e870dc2042a232a8748e75a36b52d78968cda6736de55582766"},
- {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70907533db712f7aa791effb38efa96f044ce3d4e850e2d7691abd759f4f0ae0"},
- {file = "aiohttp-3.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cdefe289681507187e375a5064c7599f52c40343a8701761c802c1853a504558"},
- {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7481f581251bb5558ba9f635db70908819caa221fc79ee52a7f58392778c636"},
- {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49f0c1b3c2842556e5de35f122fc0f0b721334ceb6e78c3719693364d4af8499"},
- {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d406b01a9f5a7e232d1b0d161b40c05275ffbcbd772dc18c1d5a570961a1ca4"},
- {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d8e4450e7fe24d86e86b23cc209e0023177b6d59502e33807b732d2deb6975f"},
- {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c0266cd6f005e99f3f51e583012de2778e65af6b73860038b968a0a8888487a"},
- {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab221850108a4a063c5b8a70f00dd7a1975e5a1713f87f4ab26a46e5feac5a0e"},
- {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c88a15f272a0ad3d7773cf3a37cc7b7d077cbfc8e331675cf1346e849d97a4e5"},
- {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:237533179d9747080bcaad4d02083ce295c0d2eab3e9e8ce103411a4312991a0"},
- {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:02ab6006ec3c3463b528374c4cdce86434e7b89ad355e7bf29e2f16b46c7dd6f"},
- {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04fa38875e53eb7e354ece1607b1d2fdee2d175ea4e4d745f6ec9f751fe20c7c"},
- {file = "aiohttp-3.9.1-cp39-cp39-win32.whl", hash = "sha256:82eefaf1a996060602f3cc1112d93ba8b201dbf5d8fd9611227de2003dddb3b7"},
- {file = "aiohttp-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:9b05d33ff8e6b269e30a7957bd3244ffbce2a7a35a81b81c382629b80af1a8bf"},
- {file = "aiohttp-3.9.1.tar.gz", hash = "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"},
+ {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"},
+ {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"},
+ {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"},
+ {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"},
+ {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"},
+ {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"},
+ {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"},
+ {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"},
+ {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"},
+ {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"},
+ {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"},
]
[package.dependencies]
@@ -153,19 +169,20 @@ frozenlist = ">=1.1.0"
[[package]]
name = "anyio"
-version = "4.1.0"
+version = "4.2.0"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
optional = false
python-versions = ">=3.8"
files = [
- {file = "anyio-4.1.0-py3-none-any.whl", hash = "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f"},
- {file = "anyio-4.1.0.tar.gz", hash = "sha256:5a0bec7085176715be77df87fc66d6c9d70626bd752fcc85f57cdbee5b3760da"},
+ {file = "anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee"},
+ {file = "anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f"},
]
[package.dependencies]
exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""}
idna = ">=2.8"
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"]
@@ -173,16 +190,22 @@ test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypo
trio = ["trio (>=0.23)"]
[[package]]
-name = "appdirs"
-version = "1.4.4"
-description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+name = "asgiref"
+version = "3.7.2"
+description = "ASGI specs, helper code, and adapters"
optional = false
-python-versions = "*"
+python-versions = ">=3.7"
files = [
- {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
- {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
+ {file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"},
+ {file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"},
]
+[package.dependencies]
+typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""}
+
+[package.extras]
+tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
+
[[package]]
name = "asttokens"
version = "2.4.1"
@@ -214,21 +237,22 @@ files = [
[[package]]
name = "attrs"
-version = "23.1.0"
+version = "23.2.0"
description = "Classes Without Boilerplate"
optional = false
python-versions = ">=3.7"
files = [
- {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
- {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
+ {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"},
+ {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"},
]
[package.extras]
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
-dev = ["attrs[docs,tests]", "pre-commit"]
+dev = ["attrs[tests]", "pre-commit"]
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
tests = ["attrs[tests-no-zope]", "zope-interface"]
-tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"]
+tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"]
[[package]]
name = "autoflake"
@@ -258,28 +282,38 @@ files = [
[[package]]
name = "bcrypt"
-version = "4.1.1"
+version = "4.1.2"
description = "Modern password hashing for your software and your servers"
optional = false
python-versions = ">=3.7"
files = [
- {file = "bcrypt-4.1.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:196008d91201bbb1aa4e666fee5e610face25d532e433a560cabb33bfdff958b"},
- {file = "bcrypt-4.1.1-cp37-abi3-macosx_13_0_universal2.whl", hash = "sha256:2e197534c884336f9020c1f3a8efbaab0aa96fc798068cb2da9c671818b7fbb0"},
- {file = "bcrypt-4.1.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d573885b637815a7f3a3cd5f87724d7d0822da64b0ab0aa7f7c78bae534e86dc"},
- {file = "bcrypt-4.1.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab33473f973e8058d1b2df8d6e095d237c49fbf7a02b527541a86a5d1dc4444"},
- {file = "bcrypt-4.1.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:fb931cd004a7ad36a89789caf18a54c20287ec1cd62161265344b9c4554fdb2e"},
- {file = "bcrypt-4.1.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:12f40f78dcba4aa7d1354d35acf45fae9488862a4fb695c7eeda5ace6aae273f"},
- {file = "bcrypt-4.1.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2ade10e8613a3b8446214846d3ddbd56cfe9205a7d64742f0b75458c868f7492"},
- {file = "bcrypt-4.1.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f33b385c3e80b5a26b3a5e148e6165f873c1c202423570fdf45fe34e00e5f3e5"},
- {file = "bcrypt-4.1.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:755b9d27abcab678e0b8fb4d0abdebeea1f68dd1183b3f518bad8d31fa77d8be"},
- {file = "bcrypt-4.1.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a7a7b8a87e51e5e8ca85b9fdaf3a5dc7aaf123365a09be7a27883d54b9a0c403"},
- {file = "bcrypt-4.1.1-cp37-abi3-win32.whl", hash = "sha256:3d6c4e0d6963c52f8142cdea428e875042e7ce8c84812d8e5507bd1e42534e07"},
- {file = "bcrypt-4.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:14d41933510717f98aac63378b7956bbe548986e435df173c841d7f2bd0b2de7"},
- {file = "bcrypt-4.1.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:24c2ebd287b5b11016f31d506ca1052d068c3f9dc817160628504690376ff050"},
- {file = "bcrypt-4.1.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:476aa8e8aca554260159d4c7a97d6be529c8e177dbc1d443cb6b471e24e82c74"},
- {file = "bcrypt-4.1.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:12611c4b0a8b1c461646228344784a1089bc0c49975680a2f54f516e71e9b79e"},
- {file = "bcrypt-4.1.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c6450538a0fc32fb7ce4c6d511448c54c4ff7640b2ed81badf9898dcb9e5b737"},
- {file = "bcrypt-4.1.1.tar.gz", hash = "sha256:df37f5418d4f1cdcff845f60e747a015389fa4e63703c918330865e06ad80007"},
+ {file = "bcrypt-4.1.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:ac621c093edb28200728a9cca214d7e838529e557027ef0581685909acd28b5e"},
+ {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea505c97a5c465ab8c3ba75c0805a102ce526695cd6818c6de3b1a38f6f60da1"},
+ {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57fa9442758da926ed33a91644649d3e340a71e2d0a5a8de064fb621fd5a3326"},
+ {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:eb3bd3321517916696233b5e0c67fd7d6281f0ef48e66812db35fc963a422a1c"},
+ {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6cad43d8c63f34b26aef462b6f5e44fdcf9860b723d2453b5d391258c4c8e966"},
+ {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:44290ccc827d3a24604f2c8bcd00d0da349e336e6503656cb8192133e27335e2"},
+ {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:732b3920a08eacf12f93e6b04ea276c489f1c8fb49344f564cca2adb663b3e4c"},
+ {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1c28973decf4e0e69cee78c68e30a523be441972c826703bb93099868a8ff5b5"},
+ {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b8df79979c5bae07f1db22dcc49cc5bccf08a0380ca5c6f391cbb5790355c0b0"},
+ {file = "bcrypt-4.1.2-cp37-abi3-win32.whl", hash = "sha256:fbe188b878313d01b7718390f31528be4010fed1faa798c5a1d0469c9c48c369"},
+ {file = "bcrypt-4.1.2-cp37-abi3-win_amd64.whl", hash = "sha256:9800ae5bd5077b13725e2e3934aa3c9c37e49d3ea3d06318010aa40f54c63551"},
+ {file = "bcrypt-4.1.2-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:71b8be82bc46cedd61a9f4ccb6c1a493211d031415a34adde3669ee1b0afbb63"},
+ {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e3c6642077b0c8092580c819c1684161262b2e30c4f45deb000c38947bf483"},
+ {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:387e7e1af9a4dd636b9505a465032f2f5cb8e61ba1120e79a0e1cd0b512f3dfc"},
+ {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f70d9c61f9c4ca7d57f3bfe88a5ccf62546ffbadf3681bb1e268d9d2e41c91a7"},
+ {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2a298db2a8ab20056120b45e86c00a0a5eb50ec4075b6142db35f593b97cb3fb"},
+ {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ba55e40de38a24e2d78d34c2d36d6e864f93e0d79d0b6ce915e4335aa81d01b1"},
+ {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3566a88234e8de2ccae31968127b0ecccbb4cddb629da744165db72b58d88ca4"},
+ {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b90e216dc36864ae7132cb151ffe95155a37a14e0de3a8f64b49655dd959ff9c"},
+ {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:69057b9fc5093ea1ab00dd24ede891f3e5e65bee040395fb1e66ee196f9c9b4a"},
+ {file = "bcrypt-4.1.2-cp39-abi3-win32.whl", hash = "sha256:02d9ef8915f72dd6daaef40e0baeef8a017ce624369f09754baf32bb32dba25f"},
+ {file = "bcrypt-4.1.2-cp39-abi3-win_amd64.whl", hash = "sha256:be3ab1071662f6065899fe08428e45c16aa36e28bc42921c4901a191fda6ee42"},
+ {file = "bcrypt-4.1.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d75fc8cd0ba23f97bae88a6ec04e9e5351ff3c6ad06f38fe32ba50cbd0d11946"},
+ {file = "bcrypt-4.1.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:a97e07e83e3262599434816f631cc4c7ca2aa8e9c072c1b1a7fec2ae809a1d2d"},
+ {file = "bcrypt-4.1.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e51c42750b7585cee7892c2614be0d14107fad9581d1738d954a262556dd1aab"},
+ {file = "bcrypt-4.1.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba4e4cc26610581a6329b3937e02d319f5ad4b85b074846bf4fef8a8cf51e7bb"},
+ {file = "bcrypt-4.1.2.tar.gz", hash = "sha256:33313a1200a3ae90b75587ceac502b048b840fc69e7f7a0905b5f87fac7a1258"},
]
[package.extras]
@@ -306,33 +340,33 @@ lxml = ["lxml"]
[[package]]
name = "black"
-version = "23.12.0"
+version = "23.12.1"
description = "The uncompromising code formatter."
optional = false
python-versions = ">=3.8"
files = [
- {file = "black-23.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:67f19562d367468ab59bd6c36a72b2c84bc2f16b59788690e02bbcb140a77175"},
- {file = "black-23.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bbd75d9f28a7283b7426160ca21c5bd640ca7cd8ef6630b4754b6df9e2da8462"},
- {file = "black-23.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:593596f699ca2dcbbbdfa59fcda7d8ad6604370c10228223cd6cf6ce1ce7ed7e"},
- {file = "black-23.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:12d5f10cce8dc27202e9a252acd1c9a426c83f95496c959406c96b785a92bb7d"},
- {file = "black-23.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e73c5e3d37e5a3513d16b33305713237a234396ae56769b839d7c40759b8a41c"},
- {file = "black-23.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ba09cae1657c4f8a8c9ff6cfd4a6baaf915bb4ef7d03acffe6a2f6585fa1bd01"},
- {file = "black-23.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace64c1a349c162d6da3cef91e3b0e78c4fc596ffde9413efa0525456148873d"},
- {file = "black-23.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:72db37a2266b16d256b3ea88b9affcdd5c41a74db551ec3dd4609a59c17d25bf"},
- {file = "black-23.12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fdf6f23c83078a6c8da2442f4d4eeb19c28ac2a6416da7671b72f0295c4a697b"},
- {file = "black-23.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39dda060b9b395a6b7bf9c5db28ac87b3c3f48d4fdff470fa8a94ab8271da47e"},
- {file = "black-23.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7231670266ca5191a76cb838185d9be59cfa4f5dd401b7c1c70b993c58f6b1b5"},
- {file = "black-23.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:193946e634e80bfb3aec41830f5d7431f8dd5b20d11d89be14b84a97c6b8bc75"},
- {file = "black-23.12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bcf91b01ddd91a2fed9a8006d7baa94ccefe7e518556470cf40213bd3d44bbbc"},
- {file = "black-23.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:996650a89fe5892714ea4ea87bc45e41a59a1e01675c42c433a35b490e5aa3f0"},
- {file = "black-23.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdbff34c487239a63d86db0c9385b27cdd68b1bfa4e706aa74bb94a435403672"},
- {file = "black-23.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:97af22278043a6a1272daca10a6f4d36c04dfa77e61cbaaf4482e08f3640e9f0"},
- {file = "black-23.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ead25c273adfad1095a8ad32afdb8304933efba56e3c1d31b0fee4143a1e424a"},
- {file = "black-23.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c71048345bdbced456cddf1622832276d98a710196b842407840ae8055ade6ee"},
- {file = "black-23.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a832b6e00eef2c13b3239d514ea3b7d5cc3eaa03d0474eedcbbda59441ba5d"},
- {file = "black-23.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:6a82a711d13e61840fb11a6dfecc7287f2424f1ca34765e70c909a35ffa7fb95"},
- {file = "black-23.12.0-py3-none-any.whl", hash = "sha256:a7c07db8200b5315dc07e331dda4d889a56f6bf4db6a9c2a526fa3166a81614f"},
- {file = "black-23.12.0.tar.gz", hash = "sha256:330a327b422aca0634ecd115985c1c7fd7bdb5b5a2ef8aa9888a82e2ebe9437a"},
+ {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"},
+ {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"},
+ {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"},
+ {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"},
+ {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"},
+ {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"},
+ {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"},
+ {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"},
+ {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"},
+ {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"},
+ {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"},
+ {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"},
+ {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"},
+ {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"},
+ {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"},
+ {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"},
+ {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"},
+ {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"},
+ {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"},
+ {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"},
+ {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"},
+ {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"},
]
[package.dependencies]
@@ -364,6 +398,29 @@ files = [
beautifulsoup4 = "*"
[[package]]
+name = "build"
+version = "1.0.3"
+description = "A simple, correct Python build frontend"
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "build-1.0.3-py3-none-any.whl", hash = "sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f"},
+ {file = "build-1.0.3.tar.gz", hash = "sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "os_name == \"nt\""}
+packaging = ">=19.0"
+pyproject_hooks = "*"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"]
+test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"]
+typing = ["importlib-metadata (>=5.1)", "mypy (>=1.5.0,<1.6.0)", "tomli", "typing-extensions (>=3.7.4.3)"]
+virtualenv = ["virtualenv (>=20.0.35)"]
+
+[[package]]
name = "cachetools"
version = "5.3.2"
description = "Extensible memoizing collections and decorators"
@@ -598,29 +655,38 @@ numpy = "*"
[[package]]
name = "chromadb"
-version = "0.4.14"
+version = "0.4.22"
description = "Chroma."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "chromadb-0.4.14-py3-none-any.whl", hash = "sha256:c1b59bdfb4b35a40bad0b8927c5ed757adf191ff9db2b9a384dc46a76e1ff10f"},
- {file = "chromadb-0.4.14.tar.gz", hash = "sha256:0fcef603bcf9c854305020c3f8d368c09b1545d48bd2bceefd51861090f87dad"},
+ {file = "chromadb-0.4.22-py3-none-any.whl", hash = "sha256:ad210b27b4cda2f09d15adc9c83c81bfa66b69f39648a27b637306e40de0680d"},
+ {file = "chromadb-0.4.22.tar.gz", hash = "sha256:c793149e1c2bbbb52d77602c6c0594c5752f04cd9be12619250ddad2082af27a"},
]
[package.dependencies]
bcrypt = ">=4.0.1"
+build = ">=1.0.3"
chroma-hnswlib = "0.7.3"
fastapi = ">=0.95.2"
grpcio = ">=1.58.0"
importlib-resources = "*"
-numpy = {version = ">=1.22.5", markers = "python_version >= \"3.8\""}
+kubernetes = ">=28.1.0"
+mmh3 = ">=4.0.1"
+numpy = ">=1.22.5"
onnxruntime = ">=1.14.1"
+opentelemetry-api = ">=1.2.0"
+opentelemetry-exporter-otlp-proto-grpc = ">=1.2.0"
+opentelemetry-instrumentation-fastapi = ">=0.41b0"
+opentelemetry-sdk = ">=1.2.0"
overrides = ">=7.3.1"
posthog = ">=2.4.0"
pulsar-client = ">=3.1.0"
pydantic = ">=1.9"
pypika = ">=0.48.9"
+PyYAML = ">=6.0.0"
requests = ">=2.28"
+tenacity = ">=8.2.3"
tokenizers = ">=0.13.2"
tqdm = ">=4.65.0"
typer = ">=0.9.0"
@@ -642,6 +708,23 @@ files = [
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
+name = "click-default-group"
+version = "1.2.4"
+description = "click_default_group"
+optional = true
+python-versions = ">=2.7"
+files = [
+ {file = "click_default_group-1.2.4-py2.py3-none-any.whl", hash = "sha256:9b60486923720e7fc61731bdb32b617039aba820e22e1c88766b1125592eaa5f"},
+ {file = "click_default_group-1.2.4.tar.gz", hash = "sha256:eb3f3c99ec0d456ca6cd2a7f08f7d4e91771bef51b01bdd9580cc6450fe1251e"},
+]
+
+[package.dependencies]
+click = "*"
+
+[package.extras]
+test = ["pytest"]
+
+[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
@@ -751,26 +834,28 @@ test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"]
[[package]]
name = "curl-cffi"
-version = "0.5.10"
+version = "0.6.2"
description = "libcurl ffi bindings for Python, with impersonation support"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "curl_cffi-0.5.10-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:892603dab5e56fb72bfff7ae969136138971f63f63defe98232e1ec55cb0f1c6"},
- {file = "curl_cffi-0.5.10-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:9937b8e13b1a6963c63e155b6621ec74649965105efedb919bc226fe731861cc"},
- {file = "curl_cffi-0.5.10-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b537595b9610a4dd0927c09823925b4e32b1ce0fd04385bfc5bb72ab830720e6"},
- {file = "curl_cffi-0.5.10-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b2bc8822d23415f6533c8b750475e9bbc76764025fe1dcb5866dc033607fd7b"},
- {file = "curl_cffi-0.5.10-cp37-abi3-win_amd64.whl", hash = "sha256:f9a1874b860c4e8db49bdfd9b9d4dc39999a1397d271ec78624c35c838e9e92a"},
- {file = "curl_cffi-0.5.10.tar.gz", hash = "sha256:55bac4b73e2d80ceeaabea33270fc8ca6ace594128a46710242f2e688b4f8bfc"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:23b8a2872b160718c04b06b1f8aa4fb1a2f4f94bce7040493515e081a27cad19"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ad3c1cf5360810825ec4bc3da425f26ee4098878a615dab9d309a99afd883ba9"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d01de6ed737ad1924aaa0198195b9020c38e77ce90ea3d72b9eacf4938c7adf"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37e513cc149d024a2d625e202f2cc9d4423d2937343ea2e06f797d99779e62dc"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-win32.whl", hash = "sha256:12e829af97cbf7c1d5afef177e786f6f404ddf163b08897a1ed087cadbeb4837"},
+ {file = "curl_cffi-0.6.2-cp38-abi3-win_amd64.whl", hash = "sha256:3791b7a9ae4cb1298165300f2dc2d60a86779f055570ae83163fc2d8a74bf714"},
+ {file = "curl_cffi-0.6.2.tar.gz", hash = "sha256:9ee519e960b5fc6e0bbf13d0ecba9ce5f6306cb929354504bf03cc30f59a8f63"},
]
[package.dependencies]
+certifi = "*"
cffi = ">=1.12.0"
[package.extras]
build = ["cibuildwheel", "wheel"]
-dev = ["autoflake (==1.4)", "black (==22.8.0)", "coverage (==6.4.1)", "cryptography (==38.0.3)", "flake8 (==6.0.0)", "flake8-bugbear (==22.7.1)", "flake8-pie (==0.15.0)", "httpx (==0.23.1)", "isort (==5.10.1)", "mypy (==0.971)", "pytest (==7.1.2)", "pytest-asyncio (==0.19.0)", "pytest-trio (==0.7.0)", "trio (==0.21.0)", "trio-typing (==0.7.0)", "trustme (==0.9.0)", "types-certifi (==2021.10.8.2)", "uvicorn (==0.18.3)"]
-test = ["cryptography (==38.0.3)", "httpx (==0.23.1)", "pytest (==7.1.2)", "pytest-asyncio (==0.19.0)", "pytest-trio (==0.7.0)", "trio (==0.21.0)", "trio-typing (==0.7.0)", "trustme (==0.9.0)", "types-certifi (==2021.10.8.2)", "uvicorn (==0.18.3)"]
+dev = ["autoflake (==1.4)", "coverage (==6.4.1)", "cryptography (==38.0.3)", "flake8 (==6.0.0)", "flake8-bugbear (==22.7.1)", "flake8-pie (==0.15.0)", "httpx (==0.23.1)", "mypy (==0.971)", "nest-asyncio (==1.6.0)", "pytest (==7.1.2)", "pytest-asyncio (==0.19.0)", "pytest-trio (==0.7.0)", "ruff (==0.1.14)", "trio (==0.21.0)", "trio-typing (==0.7.0)", "trustme (==0.9.0)", "types-certifi (==2021.10.8.2)", "uvicorn (==0.18.3)", "websockets (==11.0.3)"]
+test = ["cryptography (==38.0.3)", "fastapi (==0.100.0)", "httpx (==0.23.1)", "nest-asyncio (==1.6.0)", "proxy.py (==2.4.3)", "pytest (==7.1.2)", "pytest-asyncio (==0.19.0)", "pytest-trio (==0.7.0)", "python-multipart (==0.0.6)", "trio (==0.21.0)", "trio-typing (==0.7.0)", "trustme (==0.9.0)", "types-certifi (==2021.10.8.2)", "uvicorn (==0.18.3)", "websockets (==11.0.3)"]
[[package]]
name = "cycler"
@@ -799,6 +884,23 @@ files = [
]
[[package]]
+name = "deprecated"
+version = "1.2.14"
+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.*"
+files = [
+ {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"},
+ {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"},
+]
+
+[package.dependencies]
+wrapt = ">=1.10,<2"
+
+[package.extras]
+dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"]
+
+[[package]]
name = "distlib"
version = "0.3.8"
description = "Distribution utilities"
@@ -810,23 +912,34 @@ files = [
]
[[package]]
+name = "distro"
+version = "1.9.0"
+description = "Distro - an OS platform information API"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"},
+ {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"},
+]
+
+[[package]]
name = "duckduckgo-search"
-version = "4.0.0"
+version = "5.1.0"
description = "Search for words, documents, images, news, maps and text translation using the DuckDuckGo.com search engine."
optional = false
python-versions = ">=3.8"
files = [
- {file = "duckduckgo_search-4.0.0-py3-none-any.whl", hash = "sha256:7f6f264ed0369f5c24cca655e698641e99fece0067838a919a9905c5344771cf"},
- {file = "duckduckgo_search-4.0.0.tar.gz", hash = "sha256:38c6f6125c579305ad441b7fe816c7febbef2d3f4387afd5a182c5a83c12ecab"},
+ {file = "duckduckgo_search-5.1.0-py3-none-any.whl", hash = "sha256:691a3e1c948ab9c4409af7891557bdfff66b9f0c521336b008bbc91675ba5353"},
+ {file = "duckduckgo_search-5.1.0.tar.gz", hash = "sha256:27522d05f1e3dc5c2fbe95bd12cc32ff96a790cf8ee993b2949158dee0dbfb1f"},
]
[package.dependencies]
click = ">=8.1.7"
-curl-cffi = ">=0.5.10"
-lxml = ">=4.9.3"
+curl-cffi = ">=0.6.2"
+lxml = ">=5.1.0"
[package.extras]
-dev = ["pytest (>=7.4.2)", "pytest-asyncio (>=0.21.1)", "ruff (>=0.1.6)"]
+dev = ["mypy (>=1.8.0)", "pytest (>=8.0.1)", "ruff (>=0.3.0)"]
[[package]]
name = "exceptiongroup"
@@ -858,22 +971,22 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth
[[package]]
name = "fastapi"
-version = "0.99.1"
+version = "0.109.2"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "fastapi-0.99.1-py3-none-any.whl", hash = "sha256:976df7bab51ac7beda9f68c4513b8c4490b5c1135c72aafd0a5ee4023ec5282e"},
- {file = "fastapi-0.99.1.tar.gz", hash = "sha256:ac78f717cd80d657bd183f94d33b9bda84aa376a46a9dab513586b8eef1dc6fc"},
+ {file = "fastapi-0.109.2-py3-none-any.whl", hash = "sha256:2c9bab24667293b501cad8dd388c05240c850b58ec5876ee3283c47d6e1e3a4d"},
+ {file = "fastapi-0.109.2.tar.gz", hash = "sha256:f3817eac96fe4f65a2ebb4baa000f394e55f5fccdaf7f75250804bc58f354f73"},
]
[package.dependencies]
-pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0"
-starlette = ">=0.27.0,<0.28.0"
-typing-extensions = ">=4.5.0"
+pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
+starlette = ">=0.36.3,<0.37.0"
+typing-extensions = ">=4.8.0"
[package.extras]
-all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
+all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
[[package]]
name = "filelock"
@@ -920,59 +1033,59 @@ files = [
[[package]]
name = "fonttools"
-version = "4.46.0"
+version = "4.47.2"
description = "Tools to manipulate font files"
optional = true
python-versions = ">=3.8"
files = [
- {file = "fonttools-4.46.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d4e69e2c7f93b695d2e6f18f709d501d945f65c1d237dafaabdd23cd935a5276"},
- {file = "fonttools-4.46.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:25852f0c63df0af022f698464a4a80f7d1d5bd974bcd22f995f6b4ad198e32dd"},
- {file = "fonttools-4.46.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:adab73618d0a328b203a0e242b3eba60a2b5662d9cb2bd16ed9c52af8a7d86af"},
- {file = "fonttools-4.46.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf923a4a556ab4cc4c52f69a4a2db624cf5a2cf360394368b40c5152fe3321e"},
- {file = "fonttools-4.46.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:87c214197712cc14fd2a4621efce2a9c501a77041232b789568149a8a3161517"},
- {file = "fonttools-4.46.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:156ae342a1ed1fe38e180de471e98fbf5b2b6ae280fa3323138569c4ca215844"},
- {file = "fonttools-4.46.0-cp310-cp310-win32.whl", hash = "sha256:c506e3d3a9e898caee4dc094f34b49c5566870d5a2d1ca2125f0a9f35ecc2205"},
- {file = "fonttools-4.46.0-cp310-cp310-win_amd64.whl", hash = "sha256:f8bc3973ed58893c4107993e0a7ae34901cb572b5e798249cbef35d30801ffd4"},
- {file = "fonttools-4.46.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:982f69855ac258260f51048d9e0c53c5f19881138cc7ca06deb38dc4b97404b6"},
- {file = "fonttools-4.46.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c23c59d321d62588620f2255cf951270bf637d88070f38ed8b5e5558775b86c"},
- {file = "fonttools-4.46.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0e94244ec24a940ecfbe5b31c975c8a575d5ed2d80f9a280ce3b21fa5dc9c34"},
- {file = "fonttools-4.46.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a9f9cdd7ef63d1b8ac90db335762451452426b3207abd79f60da510cea62da5"},
- {file = "fonttools-4.46.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ca9eceebe70035b057ce549e2054cad73e95cac3fe91a9d827253d1c14618204"},
- {file = "fonttools-4.46.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8be6adfa4e15977075278dd0a0bae74dec59be7b969b5ceed93fb86af52aa5be"},
- {file = "fonttools-4.46.0-cp311-cp311-win32.whl", hash = "sha256:7b5636f5706d49f13b6d610fe54ee662336cdf56b5a6f6683c0b803e23d826d2"},
- {file = "fonttools-4.46.0-cp311-cp311-win_amd64.whl", hash = "sha256:49ea0983e55fd7586a809787cd4644a7ae471e53ab8ddc016f9093b400e32646"},
- {file = "fonttools-4.46.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7b460720ce81773da1a3e7cc964c48e1e11942b280619582a897fa0117b56a62"},
- {file = "fonttools-4.46.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8bee9f4fc8c99824a424ae45c789ee8c67cb84f8e747afa7f83b7d3cef439c3b"},
- {file = "fonttools-4.46.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3d7b96aba96e05e8c911ce2dfc5acc6a178b8f44f6aa69371ab91aa587563da"},
- {file = "fonttools-4.46.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e6aeb5c340416d11a3209d75c48d13e72deea9e1517837dd1522c1fd1f17c11"},
- {file = "fonttools-4.46.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c779f8701deedf41908f287aeb775b8a6f59875ad1002b98ac6034ae4ddc1b7b"},
- {file = "fonttools-4.46.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce199227ce7921eaafdd4f96536f16b232d6b580ce74ce337de544bf06cb2752"},
- {file = "fonttools-4.46.0-cp312-cp312-win32.whl", hash = "sha256:1c9937c4dd1061afd22643389445fabda858af5e805860ec3082a4bc07c7a720"},
- {file = "fonttools-4.46.0-cp312-cp312-win_amd64.whl", hash = "sha256:a9fa52ef8fd14d7eb3d813e1451e7ace3e1eebfa9b7237d3f81fee8f3de6a114"},
- {file = "fonttools-4.46.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c94564b1f3b5dd87e73577610d85115b1936edcc596deaf84a31bbe70e17456b"},
- {file = "fonttools-4.46.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4a50a1dfad7f7ba5ca3f99cc73bf5cdac67ceade8e4b355a877521f20ad1b63"},
- {file = "fonttools-4.46.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89c2c520f9492844ecd6316d20c6c7a157b5c0cb73a1411b3db28ee304f30122"},
- {file = "fonttools-4.46.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5b7905fd68eacb7cc56a13139da5c312c45baae6950dd00b02563c54508a041"},
- {file = "fonttools-4.46.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8485cc468288e213f31afdaf1fdda3c79010f542559fbba936a54f4644df2570"},
- {file = "fonttools-4.46.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:87c3299da7da55394fb324349db0ede38114a46aafd0e7dfcabfecd28cdd94c3"},
- {file = "fonttools-4.46.0-cp38-cp38-win32.whl", hash = "sha256:f5f1423a504ccc329efb5aa79738de83d38c072be5308788dde6bd419969d7f5"},
- {file = "fonttools-4.46.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d4a4ebcc76e30898ff3296ea786491c70e183f738319ae2629e0d44f17ece42"},
- {file = "fonttools-4.46.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9a0e422ab79e5cb2b47913be6a4b5fd20c4c7ac34a24f3691a4e099e965e0b8"},
- {file = "fonttools-4.46.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:13ac0cba2fc63fa4b232f2a7971f35f35c6eaf10bd1271fa96d4ce6253a8acfd"},
- {file = "fonttools-4.46.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:795150d5edc595e1a2cfb3d65e8f4f3d027704fc2579f8990d381bef6b188eb6"},
- {file = "fonttools-4.46.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d00fc63131dcac6b25f50a5a129758438317e54e3ce5587163f7058de4b0e933"},
- {file = "fonttools-4.46.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3033b55f401a622de2630b3982234d97219d89b058607b87927eccb0f922313c"},
- {file = "fonttools-4.46.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e26e7fb908ae4f622813e7cb32cd2db6c24e3122bb3b98f25e832a2fe0e7e228"},
- {file = "fonttools-4.46.0-cp39-cp39-win32.whl", hash = "sha256:2d0eba685938c603f2f648dfc0aadbf8c6a4fe1c7ca608c2970a6ef39e00f254"},
- {file = "fonttools-4.46.0-cp39-cp39-win_amd64.whl", hash = "sha256:5200b01f463d97cc2b7ff8a1e3584151f4413e98cb8419da5f17d1dbb84cc214"},
- {file = "fonttools-4.46.0-py3-none-any.whl", hash = "sha256:5b627ed142398ea9202bd752c04311592558964d1a765fb2f78dc441a05633f4"},
- {file = "fonttools-4.46.0.tar.gz", hash = "sha256:2ae45716c27a41807d58a9f3f59983bdc8c0a46cb259e4450ab7e196253a9853"},
+ {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3b629108351d25512d4ea1a8393a2dba325b7b7d7308116b605ea3f8e1be88df"},
+ {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c19044256c44fe299d9a73456aabee4b4d06c6b930287be93b533b4737d70aa1"},
+ {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8be28c036b9f186e8c7eaf8a11b42373e7e4949f9e9f370202b9da4c4c3f56c"},
+ {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f83a4daef6d2a202acb9bf572958f91cfde5b10c8ee7fb1d09a4c81e5d851fd8"},
+ {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5a5318ba5365d992666ac4fe35365f93004109d18858a3e18ae46f67907670"},
+ {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8f57ecd742545362a0f7186774b2d1c53423ed9ece67689c93a1055b236f638c"},
+ {file = "fonttools-4.47.2-cp310-cp310-win32.whl", hash = "sha256:a1c154bb85dc9a4cf145250c88d112d88eb414bad81d4cb524d06258dea1bdc0"},
+ {file = "fonttools-4.47.2-cp310-cp310-win_amd64.whl", hash = "sha256:3e2b95dce2ead58fb12524d0ca7d63a63459dd489e7e5838c3cd53557f8933e1"},
+ {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:29495d6d109cdbabe73cfb6f419ce67080c3ef9ea1e08d5750240fd4b0c4763b"},
+ {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0a1d313a415eaaba2b35d6cd33536560deeebd2ed758b9bfb89ab5d97dc5deac"},
+ {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f898cdd67f52f18049250a6474185ef6544c91f27a7bee70d87d77a8daf89c"},
+ {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3480eeb52770ff75140fe7d9a2ec33fb67b07efea0ab5129c7e0c6a639c40c70"},
+ {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0255dbc128fee75fb9be364806b940ed450dd6838672a150d501ee86523ac61e"},
+ {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f791446ff297fd5f1e2247c188de53c1bfb9dd7f0549eba55b73a3c2087a2703"},
+ {file = "fonttools-4.47.2-cp311-cp311-win32.whl", hash = "sha256:740947906590a878a4bde7dd748e85fefa4d470a268b964748403b3ab2aeed6c"},
+ {file = "fonttools-4.47.2-cp311-cp311-win_amd64.whl", hash = "sha256:63fbed184979f09a65aa9c88b395ca539c94287ba3a364517698462e13e457c9"},
+ {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4ec558c543609e71b2275c4894e93493f65d2f41c15fe1d089080c1d0bb4d635"},
+ {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e040f905d542362e07e72e03612a6270c33d38281fd573160e1003e43718d68d"},
+ {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dd58cc03016b281bd2c74c84cdaa6bd3ce54c5a7f47478b7657b930ac3ed8eb"},
+ {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32ab2e9702dff0dd4510c7bb958f265a8d3dd5c0e2547e7b5f7a3df4979abb07"},
+ {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a808f3c1d1df1f5bf39be869b6e0c263570cdafb5bdb2df66087733f566ea71"},
+ {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac71e2e201df041a2891067dc36256755b1229ae167edbdc419b16da78732c2f"},
+ {file = "fonttools-4.47.2-cp312-cp312-win32.whl", hash = "sha256:69731e8bea0578b3c28fdb43dbf95b9386e2d49a399e9a4ad736b8e479b08085"},
+ {file = "fonttools-4.47.2-cp312-cp312-win_amd64.whl", hash = "sha256:b3e1304e5f19ca861d86a72218ecce68f391646d85c851742d265787f55457a4"},
+ {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:254d9a6f7be00212bf0c3159e0a420eb19c63793b2c05e049eb337f3023c5ecc"},
+ {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eabae77a07c41ae0b35184894202305c3ad211a93b2eb53837c2a1143c8bc952"},
+ {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86a5ab2873ed2575d0fcdf1828143cfc6b977ac448e3dc616bb1e3d20efbafa"},
+ {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13819db8445a0cec8c3ff5f243af6418ab19175072a9a92f6cc8ca7d1452754b"},
+ {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4e743935139aa485fe3253fc33fe467eab6ea42583fa681223ea3f1a93dd01e6"},
+ {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d49ce3ea7b7173faebc5664872243b40cf88814ca3eb135c4a3cdff66af71946"},
+ {file = "fonttools-4.47.2-cp38-cp38-win32.whl", hash = "sha256:94208ea750e3f96e267f394d5588579bb64cc628e321dbb1d4243ffbc291b18b"},
+ {file = "fonttools-4.47.2-cp38-cp38-win_amd64.whl", hash = "sha256:0f750037e02beb8b3569fbff701a572e62a685d2a0e840d75816592280e5feae"},
+ {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3d71606c9321f6701642bd4746f99b6089e53d7e9817fc6b964e90d9c5f0ecc6"},
+ {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86e0427864c6c91cf77f16d1fb9bf1bbf7453e824589e8fb8461b6ee1144f506"},
+ {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a00bd0e68e88987dcc047ea31c26d40a3c61185153b03457956a87e39d43c37"},
+ {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5d77479fb885ef38a16a253a2f4096bc3d14e63a56d6246bfdb56365a12b20c"},
+ {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5465df494f20a7d01712b072ae3ee9ad2887004701b95cb2cc6dcb9c2c97a899"},
+ {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4c811d3c73b6abac275babb8aa439206288f56fdb2c6f8835e3d7b70de8937a7"},
+ {file = "fonttools-4.47.2-cp39-cp39-win32.whl", hash = "sha256:5b60e3afa9635e3dfd3ace2757039593e3bd3cf128be0ddb7a1ff4ac45fa5a50"},
+ {file = "fonttools-4.47.2-cp39-cp39-win_amd64.whl", hash = "sha256:7ee48bd9d6b7e8f66866c9090807e3a4a56cf43ffad48962725a190e0dd774c8"},
+ {file = "fonttools-4.47.2-py3-none-any.whl", hash = "sha256:7eb7ad665258fba68fd22228a09f347469d95a97fb88198e133595947a20a184"},
+ {file = "fonttools-4.47.2.tar.gz", hash = "sha256:7df26dd3650e98ca45f1e29883c96a0b9f5bb6af8d632a6a108bc744fa0bd9b3"},
]
[package.extras]
-all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"]
+all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"]
graphite = ["lz4 (>=1.7.4.2)"]
-interpolatable = ["munkres", "scipy"]
+interpolatable = ["munkres", "pycairo", "scipy"]
lxml = ["lxml (>=4.0,<5)"]
pathops = ["skia-pathops (>=0.5.0)"]
plot = ["matplotlib"]
@@ -985,72 +1098,88 @@ woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"]
[[package]]
name = "frozenlist"
-version = "1.4.0"
+version = "1.4.1"
description = "A list-like structure which implements collections.abc.MutableSequence"
optional = false
python-versions = ">=3.8"
files = [
- {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"},
- {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"},
- {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"},
- {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"},
- {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"},
- {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"},
- {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"},
- {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"},
- {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"},
- {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"},
- {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"},
- {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"},
- {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"},
- {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"},
- {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"},
- {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"},
- {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"},
- {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"},
- {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"},
- {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"},
- {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"},
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"},
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"},
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"},
+ {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"},
+ {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"},
+ {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"},
+ {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"},
+ {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"},
+ {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"},
+ {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"},
+ {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"},
+ {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"},
+ {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"},
+ {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"},
+ {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"},
]
[[package]]
@@ -1104,20 +1233,20 @@ smmap = ">=3.0.1,<6"
[[package]]
name = "gitpython"
-version = "3.1.40"
+version = "3.1.41"
description = "GitPython is a Python library used to interact with Git repositories"
optional = true
python-versions = ">=3.7"
files = [
- {file = "GitPython-3.1.40-py3-none-any.whl", hash = "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a"},
- {file = "GitPython-3.1.40.tar.gz", hash = "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4"},
+ {file = "GitPython-3.1.41-py3-none-any.whl", hash = "sha256:c36b6634d069b3f719610175020a9aed919421c87552185b085e04fbbdb10b7c"},
+ {file = "GitPython-3.1.41.tar.gz", hash = "sha256:ed66e624884f76df22c8e16066d567aaa5a37d5b5fa19db2c6df6f7156db9048"},
]
[package.dependencies]
gitdb = ">=4.0.1,<5"
[package.extras]
-test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-instafail", "pytest-subtests", "pytest-sugar"]
+test = ["black", "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", "sumtypes"]
[[package]]
name = "google-api-core"
@@ -1143,13 +1272,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"]
[[package]]
name = "google-auth"
-version = "2.25.2"
+version = "2.26.2"
description = "Google Authentication Library"
optional = false
python-versions = ">=3.7"
files = [
- {file = "google-auth-2.25.2.tar.gz", hash = "sha256:42f707937feb4f5e5a39e6c4f343a17300a459aaf03141457ba505812841cc40"},
- {file = "google_auth-2.25.2-py2.py3-none-any.whl", hash = "sha256:473a8dfd0135f75bb79d878436e568f2695dce456764bf3a02b6f8c540b1d256"},
+ {file = "google-auth-2.26.2.tar.gz", hash = "sha256:97327dbbf58cccb58fc5a1712bba403ae76668e64814eb30f7316f7e27126b81"},
+ {file = "google_auth-2.26.2-py2.py3-none-any.whl", hash = "sha256:3f445c8ce9b61ed6459aad86d8ccdba4a9afed841b2d1451a11ef4db08957424"},
]
[package.dependencies]
@@ -1321,73 +1450,73 @@ grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"]
[[package]]
name = "greenlet"
-version = "3.0.2"
+version = "3.0.3"
description = "Lightweight in-process concurrent programming"
optional = false
python-versions = ">=3.7"
files = [
- {file = "greenlet-3.0.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9acd8fd67c248b8537953cb3af8787c18a87c33d4dcf6830e410ee1f95a63fd4"},
- {file = "greenlet-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:339c0272a62fac7e602e4e6ec32a64ff9abadc638b72f17f6713556ed011d493"},
- {file = "greenlet-3.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38878744926cec29b5cc3654ef47f3003f14bfbba7230e3c8492393fe29cc28b"},
- {file = "greenlet-3.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b3f0497db77cfd034f829678b28267eeeeaf2fc21b3f5041600f7617139e6773"},
- {file = "greenlet-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed1a8a08de7f68506a38f9a2ddb26bbd1480689e66d788fcd4b5f77e2d9ecfcc"},
- {file = "greenlet-3.0.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89a6f6ddcbef4000cda7e205c4c20d319488ff03db961d72d4e73519d2465309"},
- {file = "greenlet-3.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c1f647fe5b94b51488b314c82fdda10a8756d650cee8d3cd29f657c6031bdf73"},
- {file = "greenlet-3.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9560c580c896030ff9c311c603aaf2282234643c90d1dec738a1d93e3e53cd51"},
- {file = "greenlet-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2e9c5423046eec21f6651268cb674dfba97280701e04ef23d312776377313206"},
- {file = "greenlet-3.0.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1fd25dfc5879a82103b3d9e43fa952e3026c221996ff4d32a9c72052544835d"},
- {file = "greenlet-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cecfdc950dd25f25d6582952e58521bca749cf3eeb7a9bad69237024308c8196"},
- {file = "greenlet-3.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edf7a1daba1f7c54326291a8cde58da86ab115b78c91d502be8744f0aa8e3ffa"},
- {file = "greenlet-3.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4cf532bf3c58a862196b06947b1b5cc55503884f9b63bf18582a75228d9950e"},
- {file = "greenlet-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e79fb5a9fb2d0bd3b6573784f5e5adabc0b0566ad3180a028af99523ce8f6138"},
- {file = "greenlet-3.0.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:006c1028ac0cfcc4e772980cfe73f5476041c8c91d15d64f52482fc571149d46"},
- {file = "greenlet-3.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fefd5eb2c0b1adffdf2802ff7df45bfe65988b15f6b972706a0e55d451bffaea"},
- {file = "greenlet-3.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0c0fdb8142742ee68e97c106eb81e7d3e883cc739d9c5f2b28bc38a7bafeb6d1"},
- {file = "greenlet-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:8f8d14a0a4e8c670fbce633d8b9a1ee175673a695475acd838e372966845f764"},
- {file = "greenlet-3.0.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:654b84c9527182036747938b81938f1d03fb8321377510bc1854a9370418ab66"},
- {file = "greenlet-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bc4fde0842ff2b9cf33382ad0b4db91c2582db836793d58d174c569637144"},
- {file = "greenlet-3.0.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c27b142a9080bdd5869a2fa7ebf407b3c0b24bd812db925de90e9afe3c417fd6"},
- {file = "greenlet-3.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0df7eed98ea23b20e9db64d46eb05671ba33147df9405330695bcd81a73bb0c9"},
- {file = "greenlet-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb5d60805057d8948065338be6320d35e26b0a72f45db392eb32b70dd6dc9227"},
- {file = "greenlet-3.0.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e0e28f5233d64c693382f66d47c362b72089ebf8ac77df7e12ac705c9fa1163d"},
- {file = "greenlet-3.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e4bfa752b3688d74ab1186e2159779ff4867644d2b1ebf16db14281f0445377"},
- {file = "greenlet-3.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c42bb589e6e9f9d8bdd79f02f044dff020d30c1afa6e84c0b56d1ce8a324553c"},
- {file = "greenlet-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:b2cedf279ca38ef3f4ed0d013a6a84a7fc3d9495a716b84a5fc5ff448965f251"},
- {file = "greenlet-3.0.2-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:6d65bec56a7bc352bcf11b275b838df618651109074d455a772d3afe25390b7d"},
- {file = "greenlet-3.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0acadbc3f72cb0ee85070e8d36bd2a4673d2abd10731ee73c10222cf2dd4713c"},
- {file = "greenlet-3.0.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14b5d999aefe9ffd2049ad19079f733c3aaa426190ffecadb1d5feacef8fe397"},
- {file = "greenlet-3.0.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f27aa32466993c92d326df982c4acccd9530fe354e938d9e9deada563e71ce76"},
- {file = "greenlet-3.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f34a765c5170c0673eb747213a0275ecc749ab3652bdbec324621ed5b2edaef"},
- {file = "greenlet-3.0.2-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:520fcb53a39ef90f5021c77606952dbbc1da75d77114d69b8d7bded4a8e1a813"},
- {file = "greenlet-3.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d1fceb5351ab1601903e714c3028b37f6ea722be6873f46e349a960156c05650"},
- {file = "greenlet-3.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7363756cc439a503505b67983237d1cc19139b66488263eb19f5719a32597836"},
- {file = "greenlet-3.0.2-cp37-cp37m-win32.whl", hash = "sha256:d5547b462b8099b84746461e882a3eb8a6e3f80be46cb6afb8524eeb191d1a30"},
- {file = "greenlet-3.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:950e21562818f9c771989b5b65f990e76f4ac27af66e1bb34634ae67886ede2a"},
- {file = "greenlet-3.0.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d64643317e76b4b41fdba659e7eca29634e5739b8bc394eda3a9127f697ed4b0"},
- {file = "greenlet-3.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f9ea7c2c9795549653b6f7569f6bc75d2c7d1f6b2854eb8ce0bc6ec3cb2dd88"},
- {file = "greenlet-3.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db4233358d3438369051a2f290f1311a360d25c49f255a6c5d10b5bcb3aa2b49"},
- {file = "greenlet-3.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed9bf77b41798e8417657245b9f3649314218a4a17aefb02bb3992862df32495"},
- {file = "greenlet-3.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d0df07a38e41a10dfb62c6fc75ede196572b580f48ee49b9282c65639f3965"},
- {file = "greenlet-3.0.2-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10d247260db20887ae8857c0cbc750b9170f0b067dd7d38fb68a3f2334393bd3"},
- {file = "greenlet-3.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a37ae53cca36823597fd5f65341b6f7bac2dd69ecd6ca01334bb795460ab150b"},
- {file = "greenlet-3.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:80d068e4b6e2499847d916ef64176811ead6bf210a610859220d537d935ec6fd"},
- {file = "greenlet-3.0.2-cp38-cp38-win32.whl", hash = "sha256:b1405614692ac986490d10d3e1a05e9734f473750d4bee3cf7d1286ef7af7da6"},
- {file = "greenlet-3.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:8756a94ed8f293450b0e91119eca2a36332deba69feb2f9ca410d35e74eae1e4"},
- {file = "greenlet-3.0.2-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:2c93cd03acb1499ee4de675e1a4ed8eaaa7227f7949dc55b37182047b006a7aa"},
- {file = "greenlet-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1dac09e3c0b78265d2e6d3cbac2d7c48bd1aa4b04a8ffeda3adde9f1688df2c3"},
- {file = "greenlet-3.0.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ee59c4627c8c4bb3e15949fbcd499abd6b7f4ad9e0bfcb62c65c5e2cabe0ec4"},
- {file = "greenlet-3.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18fe39d70d482b22f0014e84947c5aaa7211fb8e13dc4cc1c43ed2aa1db06d9a"},
- {file = "greenlet-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84bef3cfb6b6bfe258c98c519811c240dbc5b33a523a14933a252e486797c90"},
- {file = "greenlet-3.0.2-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aecea0442975741e7d69daff9b13c83caff8c13eeb17485afa65f6360a045765"},
- {file = "greenlet-3.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f260e6c2337871a52161824058923df2bbddb38bc11a5cbe71f3474d877c5bd9"},
- {file = "greenlet-3.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fc14dd9554f88c9c1fe04771589ae24db76cd56c8f1104e4381b383d6b71aff8"},
- {file = "greenlet-3.0.2-cp39-cp39-win32.whl", hash = "sha256:bfcecc984d60b20ffe30173b03bfe9ba6cb671b0be1e95c3e2056d4fe7006590"},
- {file = "greenlet-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:c235131bf59d2546bb3ebaa8d436126267392f2e51b85ff45ac60f3a26549af0"},
- {file = "greenlet-3.0.2.tar.gz", hash = "sha256:1c1129bc47266d83444c85a8e990ae22688cf05fb20d7951fd2866007c2ba9bc"},
+ {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"},
+ {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"},
+ {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"},
+ {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"},
+ {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"},
+ {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"},
+ {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"},
+ {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"},
+ {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"},
+ {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"},
+ {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"},
+ {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"},
+ {file = "greenlet-3.0.3-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41"},
+ {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7"},
+ {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6"},
+ {file = "greenlet-3.0.3-cp37-cp37m-win32.whl", hash = "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d"},
+ {file = "greenlet-3.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67"},
+ {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"},
+ {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"},
+ {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"},
+ {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"},
+ {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"},
+ {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"},
+ {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"},
+ {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"},
+ {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"},
+ {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"},
+ {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"},
]
[package.extras]
-docs = ["Sphinx"]
+docs = ["Sphinx", "furo"]
test = ["objgraph", "psutil"]
[[package]]
@@ -1468,26 +1597,10 @@ files = [
]
[[package]]
-name = "helicone"
-version = "1.0.14"
-description = "A Python wrapper for the OpenAI API that logs all requests to Helicone."
-optional = true
-python-versions = ">=3.8.1"
-files = [
- {file = "helicone-1.0.14-py3-none-any.whl", hash = "sha256:1828eb546e2f1aa780391ff640a1c62d55de030d3712c26db8d53f288333349a"},
- {file = "helicone-1.0.14.tar.gz", hash = "sha256:d8061b1ff7ed45257cd24f42e7f6e24d330130a30fe0444253d3cad4bb9d23d5"},
-]
-
-[package.dependencies]
-lockfile = ">=0.12.2,<0.13.0"
-openai = ">=0.27.0,<0.28.0"
-pyhumps = ">=3.8.0,<4.0.0"
-
-[[package]]
name = "httpcore"
version = "0.17.3"
description = "A minimal low-level HTTP client."
-optional = true
+optional = false
python-versions = ">=3.7"
files = [
{file = "httpcore-0.17.3-py3-none-any.whl", hash = "sha256:c2789b767ddddfa2a5782e3199b2b7f6894540b17b16ec26b2c4d8e103510b87"},
@@ -1556,7 +1669,7 @@ test = ["Cython (>=0.29.24,<0.30.0)"]
name = "httpx"
version = "0.24.1"
description = "The next generation HTTP client."
-optional = true
+optional = false
python-versions = ">=3.7"
files = [
{file = "httpx-0.24.1-py3-none-any.whl", hash = "sha256:06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd"},
@@ -1577,13 +1690,13 @@ socks = ["socksio (==1.*)"]
[[package]]
name = "huggingface-hub"
-version = "0.19.4"
+version = "0.20.2"
description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub"
optional = false
python-versions = ">=3.8.0"
files = [
- {file = "huggingface_hub-0.19.4-py3-none-any.whl", hash = "sha256:dba013f779da16f14b606492828f3760600a1e1801432d09fe1c33e50b825bb5"},
- {file = "huggingface_hub-0.19.4.tar.gz", hash = "sha256:176a4fc355a851c17550e7619488f383189727eab209534d7cef2114dae77b22"},
+ {file = "huggingface_hub-0.20.2-py3-none-any.whl", hash = "sha256:53752eda2239d30a470c307a61cf9adcf136bc77b0a734338c7d04941af560d8"},
+ {file = "huggingface_hub-0.20.2.tar.gz", hash = "sha256:215c5fceff631030c7a3d19ba7b588921c908b3f21eef31d160ebc245b200ff6"},
]
[package.dependencies]
@@ -1596,15 +1709,14 @@ tqdm = ">=4.42.1"
typing-extensions = ">=3.7.4.3"
[package.extras]
-all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
+all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
cli = ["InquirerPy (==0.3.4)"]
-dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
-docs = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "hf-doc-builder", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)", "watchdog"]
+dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"]
inference = ["aiohttp", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)"]
quality = ["mypy (==1.5.1)", "ruff (>=0.1.3)"]
tensorflow = ["graphviz", "pydot", "tensorflow"]
-testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"]
+testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"]
torch = ["torch"]
typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"]
@@ -1649,13 +1761,13 @@ files = [
[[package]]
name = "importlib-metadata"
-version = "7.0.0"
+version = "6.11.0"
description = "Read metadata from Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"},
- {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"},
+ {file = "importlib_metadata-6.11.0-py3-none-any.whl", hash = "sha256:f0afba6205ad8f8947c7d338b5342d5db2afbfd82f9cbef7879a9539cc12eb9b"},
+ {file = "importlib_metadata-6.11.0.tar.gz", hash = "sha256:1231cf92d825c9e03cfc4da076a16de6422c863558229ea0b22b675657463443"},
]
[package.dependencies]
@@ -1694,13 +1806,13 @@ files = [
[[package]]
name = "ipython"
-version = "8.18.1"
+version = "8.20.0"
description = "IPython: Productive Interactive Computing"
optional = true
-python-versions = ">=3.9"
+python-versions = ">=3.10"
files = [
- {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"},
- {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"},
+ {file = "ipython-8.20.0-py3-none-any.whl", hash = "sha256:bc9716aad6f29f36c449e30821c9dd0c1c1a7b59ddcc26931685b87b4c569619"},
+ {file = "ipython-8.20.0.tar.gz", hash = "sha256:2f21bd3fc1d51550c89ee3944ae04bbc7bc79e129ea0937da6e6c68bfdbf117a"},
]
[package.dependencies]
@@ -1716,29 +1828,32 @@ stack-data = "*"
traitlets = ">=5"
[package.extras]
-all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
+all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.23)", "pandas", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
black = ["black"]
-doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"]
+doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"]
kernel = ["ipykernel"]
nbconvert = ["nbconvert"]
nbformat = ["nbformat"]
notebook = ["ipywidgets", "notebook"]
parallel = ["ipyparallel"]
qtconsole = ["qtconsole"]
-test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"]
-test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"]
+test = ["pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"]
+test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath", "trio"]
[[package]]
name = "isort"
-version = "5.13.1"
+version = "5.13.2"
description = "A Python utility / library to sort Python imports."
optional = false
python-versions = ">=3.8.0"
files = [
- {file = "isort-5.13.1-py3-none-any.whl", hash = "sha256:56a51732c25f94ca96f6721be206dd96a95f42950502eb26c1015d333bc6edb7"},
- {file = "isort-5.13.1.tar.gz", hash = "sha256:aaed790b463e8703fb1eddb831dfa8e8616bacde2c083bd557ef73c8189b7263"},
+ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"},
+ {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"},
]
+[package.extras]
+colors = ["colorama (>=0.4.6)"]
+
[[package]]
name = "jedi"
version = "0.19.1"
@@ -1760,13 +1875,13 @@ testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
[[package]]
name = "jinja2"
-version = "3.1.2"
+version = "3.1.3"
description = "A very fast and expressive template engine."
optional = false
python-versions = ">=3.7"
files = [
- {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
- {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+ {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"},
+ {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"},
]
[package.dependencies]
@@ -1905,143 +2020,149 @@ files = [
]
[[package]]
+name = "kubernetes"
+version = "29.0.0"
+description = "Kubernetes python client"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "kubernetes-29.0.0-py2.py3-none-any.whl", hash = "sha256:ab8cb0e0576ccdfb71886366efb102c6a20f268d817be065ce7f9909c631e43e"},
+ {file = "kubernetes-29.0.0.tar.gz", hash = "sha256:c4812e227ae74d07d53c88293e564e54b850452715a59a927e7e1bc6b9a60459"},
+]
+
+[package.dependencies]
+certifi = ">=14.05.14"
+google-auth = ">=1.0.1"
+oauthlib = ">=3.2.2"
+python-dateutil = ">=2.5.3"
+pyyaml = ">=5.4.1"
+requests = "*"
+requests-oauthlib = "*"
+six = ">=1.9.0"
+urllib3 = ">=1.24.2"
+websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.dev0 || >=0.43.dev0"
+
+[package.extras]
+adal = ["adal (>=1.0.2)"]
+
+[[package]]
name = "litellm"
-version = "0.1.824"
+version = "1.17.9"
description = "Library to easily interface with LLM API providers"
optional = false
-python-versions = ">=3.8,<4.0"
+python-versions = ">=3.8, !=2.7.*, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*, !=3.7.*"
files = [
- {file = "litellm-0.1.824-py3-none-any.whl", hash = "sha256:3aed4d3d849b8e518aaafc62758a548111e4502bad7fbcd69581bfeb10bc016a"},
- {file = "litellm-0.1.824.tar.gz", hash = "sha256:8c4dd49d1d996a6b953f39271608139e96ac25c43b91dd32188367b7d233f584"},
+ {file = "litellm-1.17.9-py3-none-any.whl", hash = "sha256:1ef004431eab9d4fd1182bfd0ce996e8381671f7461170a8171941b6c42bd1e6"},
+ {file = "litellm-1.17.9.tar.gz", hash = "sha256:19410fca9098fe44cfa1587d3eb9ad52d60c06d1144fe6b7542000b0b3600362"},
]
[package.dependencies]
-appdirs = ">=1.4.4,<2.0.0"
+aiohttp = "*"
click = "*"
importlib-metadata = ">=6.8.0"
jinja2 = ">=3.1.2,<4.0.0"
-openai = ">=0.27.0,<0.29.0"
+openai = ">=1.0.0"
python-dotenv = ">=0.2.0"
+requests = ">=2.31.0,<3.0.0"
tiktoken = ">=0.4.0"
tokenizers = "*"
-[[package]]
-name = "lockfile"
-version = "0.12.2"
-description = "Platform-independent file locking module"
-optional = true
-python-versions = "*"
-files = [
- {file = "lockfile-0.12.2-py2.py3-none-any.whl", hash = "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"},
- {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"},
-]
+[package.extras]
+extra-proxy = ["streamlit (>=1.29.0,<2.0.0)"]
+proxy = ["backoff", "fastapi (>=0.104.1,<0.105.0)", "gunicorn (>=21.2.0,<22.0.0)", "orjson (>=3.9.7,<4.0.0)", "pyyaml (>=6.0,<7.0)", "rq", "uvicorn (>=0.22.0,<0.23.0)"]
[[package]]
name = "lxml"
-version = "4.9.3"
+version = "5.1.0"
description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*"
-files = [
- {file = "lxml-4.9.3-cp27-cp27m-macosx_11_0_x86_64.whl", hash = "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c"},
- {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d"},
- {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef"},
- {file = "lxml-4.9.3-cp27-cp27m-win32.whl", hash = "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7"},
- {file = "lxml-4.9.3-cp27-cp27m-win_amd64.whl", hash = "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1"},
- {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb"},
- {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e"},
- {file = "lxml-4.9.3-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991"},
- {file = "lxml-4.9.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd"},
- {file = "lxml-4.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c"},
- {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8"},
- {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76"},
- {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23"},
- {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f"},
- {file = "lxml-4.9.3-cp310-cp310-win32.whl", hash = "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85"},
- {file = "lxml-4.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d"},
- {file = "lxml-4.9.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5"},
- {file = "lxml-4.9.3-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf"},
- {file = "lxml-4.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a"},
- {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f"},
- {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b"},
- {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120"},
- {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6"},
- {file = "lxml-4.9.3-cp311-cp311-win32.whl", hash = "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305"},
- {file = "lxml-4.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc"},
- {file = "lxml-4.9.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4"},
- {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be"},
- {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13"},
- {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9"},
- {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5"},
- {file = "lxml-4.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8"},
- {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7"},
- {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2"},
- {file = "lxml-4.9.3-cp35-cp35m-win32.whl", hash = "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d"},
- {file = "lxml-4.9.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833"},
- {file = "lxml-4.9.3-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584"},
- {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287"},
- {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458"},
- {file = "lxml-4.9.3-cp36-cp36m-win32.whl", hash = "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477"},
- {file = "lxml-4.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4"},
- {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a"},
- {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02"},
- {file = "lxml-4.9.3-cp37-cp37m-win32.whl", hash = "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f"},
- {file = "lxml-4.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa"},
- {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40"},
- {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7"},
- {file = "lxml-4.9.3-cp38-cp38-win32.whl", hash = "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574"},
- {file = "lxml-4.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96"},
- {file = "lxml-4.9.3-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432"},
- {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69"},
- {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50"},
- {file = "lxml-4.9.3-cp39-cp39-win32.whl", hash = "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2"},
- {file = "lxml-4.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2"},
- {file = "lxml-4.9.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35"},
- {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0"},
- {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3"},
- {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b"},
- {file = "lxml-4.9.3-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b"},
- {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7"},
- {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d"},
- {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b"},
- {file = "lxml-4.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a"},
- {file = "lxml-4.9.3-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0"},
- {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694"},
- {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7"},
- {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4"},
- {file = "lxml-4.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9"},
- {file = "lxml-4.9.3.tar.gz", hash = "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c"},
+python-versions = ">=3.6"
+files = [
+ {file = "lxml-5.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:704f5572ff473a5f897745abebc6df40f22d4133c1e0a1f124e4f2bd3330ff7e"},
+ {file = "lxml-5.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9d3c0f8567ffe7502d969c2c1b809892dc793b5d0665f602aad19895f8d508da"},
+ {file = "lxml-5.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5fcfbebdb0c5d8d18b84118842f31965d59ee3e66996ac842e21f957eb76138c"},
+ {file = "lxml-5.1.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f37c6d7106a9d6f0708d4e164b707037b7380fcd0b04c5bd9cae1fb46a856fb"},
+ {file = "lxml-5.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2befa20a13f1a75c751f47e00929fb3433d67eb9923c2c0b364de449121f447c"},
+ {file = "lxml-5.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22b7ee4c35f374e2c20337a95502057964d7e35b996b1c667b5c65c567d2252a"},
+ {file = "lxml-5.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bf8443781533b8d37b295016a4b53c1494fa9a03573c09ca5104550c138d5c05"},
+ {file = "lxml-5.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:82bddf0e72cb2af3cbba7cec1d2fd11fda0de6be8f4492223d4a268713ef2147"},
+ {file = "lxml-5.1.0-cp310-cp310-win32.whl", hash = "sha256:b66aa6357b265670bb574f050ffceefb98549c721cf28351b748be1ef9577d93"},
+ {file = "lxml-5.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:4946e7f59b7b6a9e27bef34422f645e9a368cb2be11bf1ef3cafc39a1f6ba68d"},
+ {file = "lxml-5.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:14deca1460b4b0f6b01f1ddc9557704e8b365f55c63070463f6c18619ebf964f"},
+ {file = "lxml-5.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ed8c3d2cd329bf779b7ed38db176738f3f8be637bb395ce9629fc76f78afe3d4"},
+ {file = "lxml-5.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:436a943c2900bb98123b06437cdd30580a61340fbdb7b28aaf345a459c19046a"},
+ {file = "lxml-5.1.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:acb6b2f96f60f70e7f34efe0c3ea34ca63f19ca63ce90019c6cbca6b676e81fa"},
+ {file = "lxml-5.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af8920ce4a55ff41167ddbc20077f5698c2e710ad3353d32a07d3264f3a2021e"},
+ {file = "lxml-5.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cfced4a069003d8913408e10ca8ed092c49a7f6cefee9bb74b6b3e860683b45"},
+ {file = "lxml-5.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9e5ac3437746189a9b4121db2a7b86056ac8786b12e88838696899328fc44bb2"},
+ {file = "lxml-5.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f4c9bda132ad108b387c33fabfea47866af87f4ea6ffb79418004f0521e63204"},
+ {file = "lxml-5.1.0-cp311-cp311-win32.whl", hash = "sha256:bc64d1b1dab08f679fb89c368f4c05693f58a9faf744c4d390d7ed1d8223869b"},
+ {file = "lxml-5.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:a5ab722ae5a873d8dcee1f5f45ddd93c34210aed44ff2dc643b5025981908cda"},
+ {file = "lxml-5.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9aa543980ab1fbf1720969af1d99095a548ea42e00361e727c58a40832439114"},
+ {file = "lxml-5.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6f11b77ec0979f7e4dc5ae081325a2946f1fe424148d3945f943ceaede98adb8"},
+ {file = "lxml-5.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a36c506e5f8aeb40680491d39ed94670487ce6614b9d27cabe45d94cd5d63e1e"},
+ {file = "lxml-5.1.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f643ffd2669ffd4b5a3e9b41c909b72b2a1d5e4915da90a77e119b8d48ce867a"},
+ {file = "lxml-5.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16dd953fb719f0ffc5bc067428fc9e88f599e15723a85618c45847c96f11f431"},
+ {file = "lxml-5.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16018f7099245157564d7148165132c70adb272fb5a17c048ba70d9cc542a1a1"},
+ {file = "lxml-5.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:82cd34f1081ae4ea2ede3d52f71b7be313756e99b4b5f829f89b12da552d3aa3"},
+ {file = "lxml-5.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:19a1bc898ae9f06bccb7c3e1dfd73897ecbbd2c96afe9095a6026016e5ca97b8"},
+ {file = "lxml-5.1.0-cp312-cp312-win32.whl", hash = "sha256:13521a321a25c641b9ea127ef478b580b5ec82aa2e9fc076c86169d161798b01"},
+ {file = "lxml-5.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:1ad17c20e3666c035db502c78b86e58ff6b5991906e55bdbef94977700c72623"},
+ {file = "lxml-5.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:24ef5a4631c0b6cceaf2dbca21687e29725b7c4e171f33a8f8ce23c12558ded1"},
+ {file = "lxml-5.1.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d2900b7f5318bc7ad8631d3d40190b95ef2aa8cc59473b73b294e4a55e9f30f"},
+ {file = "lxml-5.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:601f4a75797d7a770daed8b42b97cd1bb1ba18bd51a9382077a6a247a12aa38d"},
+ {file = "lxml-5.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4b68c961b5cc402cbd99cca5eb2547e46ce77260eb705f4d117fd9c3f932b95"},
+ {file = "lxml-5.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:afd825e30f8d1f521713a5669b63657bcfe5980a916c95855060048b88e1adb7"},
+ {file = "lxml-5.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:262bc5f512a66b527d026518507e78c2f9c2bd9eb5c8aeeb9f0eb43fcb69dc67"},
+ {file = "lxml-5.1.0-cp36-cp36m-win32.whl", hash = "sha256:e856c1c7255c739434489ec9c8aa9cdf5179785d10ff20add308b5d673bed5cd"},
+ {file = "lxml-5.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:c7257171bb8d4432fe9d6fdde4d55fdbe663a63636a17f7f9aaba9bcb3153ad7"},
+ {file = "lxml-5.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b9e240ae0ba96477682aa87899d94ddec1cc7926f9df29b1dd57b39e797d5ab5"},
+ {file = "lxml-5.1.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a96f02ba1bcd330807fc060ed91d1f7a20853da6dd449e5da4b09bfcc08fdcf5"},
+ {file = "lxml-5.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3898ae2b58eeafedfe99e542a17859017d72d7f6a63de0f04f99c2cb125936"},
+ {file = "lxml-5.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61c5a7edbd7c695e54fca029ceb351fc45cd8860119a0f83e48be44e1c464862"},
+ {file = "lxml-5.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3aeca824b38ca78d9ee2ab82bd9883083d0492d9d17df065ba3b94e88e4d7ee6"},
+ {file = "lxml-5.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8f52fe6859b9db71ee609b0c0a70fea5f1e71c3462ecf144ca800d3f434f0764"},
+ {file = "lxml-5.1.0-cp37-cp37m-win32.whl", hash = "sha256:d42e3a3fc18acc88b838efded0e6ec3edf3e328a58c68fbd36a7263a874906c8"},
+ {file = "lxml-5.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:eac68f96539b32fce2c9b47eb7c25bb2582bdaf1bbb360d25f564ee9e04c542b"},
+ {file = "lxml-5.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ae15347a88cf8af0949a9872b57a320d2605ae069bcdf047677318bc0bba45b1"},
+ {file = "lxml-5.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c26aab6ea9c54d3bed716b8851c8bfc40cb249b8e9880e250d1eddde9f709bf5"},
+ {file = "lxml-5.1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:342e95bddec3a698ac24378d61996b3ee5ba9acfeb253986002ac53c9a5f6f84"},
+ {file = "lxml-5.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:725e171e0b99a66ec8605ac77fa12239dbe061482ac854d25720e2294652eeaa"},
+ {file = "lxml-5.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d184e0d5c918cff04cdde9dbdf9600e960161d773666958c9d7b565ccc60c45"},
+ {file = "lxml-5.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:98f3f020a2b736566c707c8e034945c02aa94e124c24f77ca097c446f81b01f1"},
+ {file = "lxml-5.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d48fc57e7c1e3df57be5ae8614bab6d4e7b60f65c5457915c26892c41afc59e"},
+ {file = "lxml-5.1.0-cp38-cp38-win32.whl", hash = "sha256:7ec465e6549ed97e9f1e5ed51c657c9ede767bc1c11552f7f4d022c4df4a977a"},
+ {file = "lxml-5.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:b21b4031b53d25b0858d4e124f2f9131ffc1530431c6d1321805c90da78388d1"},
+ {file = "lxml-5.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:52427a7eadc98f9e62cb1368a5079ae826f94f05755d2d567d93ee1bc3ceb354"},
+ {file = "lxml-5.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6a2a2c724d97c1eb8cf966b16ca2915566a4904b9aad2ed9a09c748ffe14f969"},
+ {file = "lxml-5.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:843b9c835580d52828d8f69ea4302537337a21e6b4f1ec711a52241ba4a824f3"},
+ {file = "lxml-5.1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9b99f564659cfa704a2dd82d0684207b1aadf7d02d33e54845f9fc78e06b7581"},
+ {file = "lxml-5.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f8b0c78e7aac24979ef09b7f50da871c2de2def043d468c4b41f512d831e912"},
+ {file = "lxml-5.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9bcf86dfc8ff3e992fed847c077bd875d9e0ba2fa25d859c3a0f0f76f07f0c8d"},
+ {file = "lxml-5.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:49a9b4af45e8b925e1cd6f3b15bbba2c81e7dba6dce170c677c9cda547411e14"},
+ {file = "lxml-5.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:280f3edf15c2a967d923bcfb1f8f15337ad36f93525828b40a0f9d6c2ad24890"},
+ {file = "lxml-5.1.0-cp39-cp39-win32.whl", hash = "sha256:ed7326563024b6e91fef6b6c7a1a2ff0a71b97793ac33dbbcf38f6005e51ff6e"},
+ {file = "lxml-5.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:8d7b4beebb178e9183138f552238f7e6613162a42164233e2bda00cb3afac58f"},
+ {file = "lxml-5.1.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9bd0ae7cc2b85320abd5e0abad5ccee5564ed5f0cc90245d2f9a8ef330a8deae"},
+ {file = "lxml-5.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8c1d679df4361408b628f42b26a5d62bd3e9ba7f0c0e7969f925021554755aa"},
+ {file = "lxml-5.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2ad3a8ce9e8a767131061a22cd28fdffa3cd2dc193f399ff7b81777f3520e372"},
+ {file = "lxml-5.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:304128394c9c22b6569eba2a6d98392b56fbdfbad58f83ea702530be80d0f9df"},
+ {file = "lxml-5.1.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d74fcaf87132ffc0447b3c685a9f862ffb5b43e70ea6beec2fb8057d5d2a1fea"},
+ {file = "lxml-5.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:8cf5877f7ed384dabfdcc37922c3191bf27e55b498fecece9fd5c2c7aaa34c33"},
+ {file = "lxml-5.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:877efb968c3d7eb2dad540b6cabf2f1d3c0fbf4b2d309a3c141f79c7e0061324"},
+ {file = "lxml-5.1.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f14a4fb1c1c402a22e6a341a24c1341b4a3def81b41cd354386dcb795f83897"},
+ {file = "lxml-5.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:25663d6e99659544ee8fe1b89b1a8c0aaa5e34b103fab124b17fa958c4a324a6"},
+ {file = "lxml-5.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8b9f19df998761babaa7f09e6bc169294eefafd6149aaa272081cbddc7ba4ca3"},
+ {file = "lxml-5.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e53d7e6a98b64fe54775d23a7c669763451340c3d44ad5e3a3b48a1efbdc96f"},
+ {file = "lxml-5.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c3cd1fc1dc7c376c54440aeaaa0dcc803d2126732ff5c6b68ccd619f2e64be4f"},
+ {file = "lxml-5.1.0.tar.gz", hash = "sha256:3eea6ed6e6c918e468e693c41ef07f3c3acc310b70ddd9cc72d9ef84bc9564ca"},
]
[package.extras]
cssselect = ["cssselect (>=0.7)"]
html5 = ["html5lib"]
htmlsoup = ["BeautifulSoup4"]
-source = ["Cython (>=0.29.35)"]
+source = ["Cython (>=3.0.7)"]
[[package]]
name = "markupsafe"
@@ -2186,6 +2307,98 @@ files = [
]
[[package]]
+name = "mmh3"
+version = "4.1.0"
+description = "Python extension for MurmurHash (MurmurHash3), a set of fast and robust hash functions."
+optional = false
+python-versions = "*"
+files = [
+ {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:be5ac76a8b0cd8095784e51e4c1c9c318c19edcd1709a06eb14979c8d850c31a"},
+ {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98a49121afdfab67cd80e912b36404139d7deceb6773a83620137aaa0da5714c"},
+ {file = "mmh3-4.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5259ac0535874366e7d1a5423ef746e0d36a9e3c14509ce6511614bdc5a7ef5b"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5950827ca0453a2be357696da509ab39646044e3fa15cad364eb65d78797437"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1dd0f652ae99585b9dd26de458e5f08571522f0402155809fd1dc8852a613a39"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99d25548070942fab1e4a6f04d1626d67e66d0b81ed6571ecfca511f3edf07e6"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53db8d9bad3cb66c8f35cbc894f336273f63489ce4ac416634932e3cbe79eb5b"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75da0f615eb55295a437264cc0b736753f830b09d102aa4c2a7d719bc445ec05"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b926b07fd678ea84b3a2afc1fa22ce50aeb627839c44382f3d0291e945621e1a"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c5b053334f9b0af8559d6da9dc72cef0a65b325ebb3e630c680012323c950bb6"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5bf33dc43cd6de2cb86e0aa73a1cc6530f557854bbbe5d59f41ef6de2e353d7b"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fa7eacd2b830727ba3dd65a365bed8a5c992ecd0c8348cf39a05cc77d22f4970"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:42dfd6742b9e3eec599f85270617debfa0bbb913c545bb980c8a4fa7b2d047da"},
+ {file = "mmh3-4.1.0-cp310-cp310-win32.whl", hash = "sha256:2974ad343f0d39dcc88e93ee6afa96cedc35a9883bc067febd7ff736e207fa47"},
+ {file = "mmh3-4.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:74699a8984ded645c1a24d6078351a056f5a5f1fe5838870412a68ac5e28d865"},
+ {file = "mmh3-4.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:f0dc874cedc23d46fc488a987faa6ad08ffa79e44fb08e3cd4d4cf2877c00a00"},
+ {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3280a463855b0eae64b681cd5b9ddd9464b73f81151e87bb7c91a811d25619e6"},
+ {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:97ac57c6c3301769e757d444fa7c973ceb002cb66534b39cbab5e38de61cd896"},
+ {file = "mmh3-4.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7b6502cdb4dbd880244818ab363c8770a48cdccecf6d729ade0241b736b5ec0"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52ba2da04671a9621580ddabf72f06f0e72c1c9c3b7b608849b58b11080d8f14"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a5fef4c4ecc782e6e43fbeab09cff1bac82c998a1773d3a5ee6a3605cde343e"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5135358a7e00991f73b88cdc8eda5203bf9de22120d10a834c5761dbeb07dd13"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cff9ae76a54f7c6fe0167c9c4028c12c1f6de52d68a31d11b6790bb2ae685560"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f02576a4d106d7830ca90278868bf0983554dd69183b7bbe09f2fcd51cf54f"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:073d57425a23721730d3ff5485e2da489dd3c90b04e86243dd7211f889898106"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:71e32ddec7f573a1a0feb8d2cf2af474c50ec21e7a8263026e8d3b4b629805db"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7cbb20b29d57e76a58b40fd8b13a9130db495a12d678d651b459bf61c0714cea"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a42ad267e131d7847076bb7e31050f6c4378cd38e8f1bf7a0edd32f30224d5c9"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4a013979fc9390abadc445ea2527426a0e7a4495c19b74589204f9b71bcaafeb"},
+ {file = "mmh3-4.1.0-cp311-cp311-win32.whl", hash = "sha256:1d3b1cdad7c71b7b88966301789a478af142bddcb3a2bee563f7a7d40519a00f"},
+ {file = "mmh3-4.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0dc6dc32eb03727467da8e17deffe004fbb65e8b5ee2b502d36250d7a3f4e2ec"},
+ {file = "mmh3-4.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:9ae3a5c1b32dda121c7dc26f9597ef7b01b4c56a98319a7fe86c35b8bc459ae6"},
+ {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0033d60c7939168ef65ddc396611077a7268bde024f2c23bdc283a19123f9e9c"},
+ {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d6af3e2287644b2b08b5924ed3a88c97b87b44ad08e79ca9f93d3470a54a41c5"},
+ {file = "mmh3-4.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d82eb4defa245e02bb0b0dc4f1e7ee284f8d212633389c91f7fba99ba993f0a2"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba245e94b8d54765e14c2d7b6214e832557e7856d5183bc522e17884cab2f45d"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb04e2feeabaad6231e89cd43b3d01a4403579aa792c9ab6fdeef45cc58d4ec0"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e3b1a27def545ce11e36158ba5d5390cdbc300cfe456a942cc89d649cf7e3b2"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce0ab79ff736d7044e5e9b3bfe73958a55f79a4ae672e6213e92492ad5e734d5"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b02268be6e0a8eeb8a924d7db85f28e47344f35c438c1e149878bb1c47b1cd3"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:deb887f5fcdaf57cf646b1e062d56b06ef2f23421c80885fce18b37143cba828"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99dd564e9e2b512eb117bd0cbf0f79a50c45d961c2a02402787d581cec5448d5"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:08373082dfaa38fe97aa78753d1efd21a1969e51079056ff552e687764eafdfe"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:54b9c6a2ea571b714e4fe28d3e4e2db37abfd03c787a58074ea21ee9a8fd1740"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a7b1edf24c69e3513f879722b97ca85e52f9032f24a52284746877f6a7304086"},
+ {file = "mmh3-4.1.0-cp312-cp312-win32.whl", hash = "sha256:411da64b951f635e1e2284b71d81a5a83580cea24994b328f8910d40bed67276"},
+ {file = "mmh3-4.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:bebc3ecb6ba18292e3d40c8712482b4477abd6981c2ebf0e60869bd90f8ac3a9"},
+ {file = "mmh3-4.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:168473dd608ade6a8d2ba069600b35199a9af837d96177d3088ca91f2b3798e3"},
+ {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:372f4b7e1dcde175507640679a2a8790185bb71f3640fc28a4690f73da986a3b"},
+ {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:438584b97f6fe13e944faf590c90fc127682b57ae969f73334040d9fa1c7ffa5"},
+ {file = "mmh3-4.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6e27931b232fc676675fac8641c6ec6b596daa64d82170e8597f5a5b8bdcd3b6"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:571a92bad859d7b0330e47cfd1850b76c39b615a8d8e7aa5853c1f971fd0c4b1"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a69d6afe3190fa08f9e3a58e5145549f71f1f3fff27bd0800313426929c7068"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afb127be0be946b7630220908dbea0cee0d9d3c583fa9114a07156f98566dc28"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:940d86522f36348ef1a494cbf7248ab3f4a1638b84b59e6c9e90408bd11ad729"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3dcccc4935686619a8e3d1f7b6e97e3bd89a4a796247930ee97d35ea1a39341"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01bb9b90d61854dfc2407c5e5192bfb47222d74f29d140cb2dd2a69f2353f7cc"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bcb1b8b951a2c0b0fb8a5426c62a22557e2ffc52539e0a7cc46eb667b5d606a9"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6477a05d5e5ab3168e82e8b106e316210ac954134f46ec529356607900aea82a"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:da5892287e5bea6977364b15712a2573c16d134bc5fdcdd4cf460006cf849278"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:99180d7fd2327a6fffbaff270f760576839dc6ee66d045fa3a450f3490fda7f5"},
+ {file = "mmh3-4.1.0-cp38-cp38-win32.whl", hash = "sha256:9b0d4f3949913a9f9a8fb1bb4cc6ecd52879730aab5ff8c5a3d8f5b593594b73"},
+ {file = "mmh3-4.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:598c352da1d945108aee0c3c3cfdd0e9b3edef74108f53b49d481d3990402169"},
+ {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:475d6d1445dd080f18f0f766277e1237fa2914e5fe3307a3b2a3044f30892103"},
+ {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5ca07c41e6a2880991431ac717c2a049056fff497651a76e26fc22224e8b5732"},
+ {file = "mmh3-4.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ebe052fef4bbe30c0548d12ee46d09f1b69035ca5208a7075e55adfe091be44"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaefd42e85afb70f2b855a011f7b4d8a3c7e19c3f2681fa13118e4d8627378c5"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0ae43caae5a47afe1b63a1ae3f0986dde54b5fb2d6c29786adbfb8edc9edfb"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6218666f74c8c013c221e7f5f8a693ac9cf68e5ac9a03f2373b32d77c48904de"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac59294a536ba447b5037f62d8367d7d93b696f80671c2c45645fa9f1109413c"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086844830fcd1e5c84fec7017ea1ee8491487cfc877847d96f86f68881569d2e"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e42b38fad664f56f77f6fbca22d08450f2464baa68acdbf24841bf900eb98e87"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d08b790a63a9a1cde3b5d7d733ed97d4eb884bfbc92f075a091652d6bfd7709a"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:73ea4cc55e8aea28c86799ecacebca09e5f86500414870a8abaedfcbaf74d288"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f90938ff137130e47bcec8dc1f4ceb02f10178c766e2ef58a9f657ff1f62d124"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:aa1f13e94b8631c8cd53259250556edcf1de71738936b60febba95750d9632bd"},
+ {file = "mmh3-4.1.0-cp39-cp39-win32.whl", hash = "sha256:a3b680b471c181490cf82da2142029edb4298e1bdfcb67c76922dedef789868d"},
+ {file = "mmh3-4.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:fefef92e9c544a8dbc08f77a8d1b6d48006a750c4375bbcd5ff8199d761e263b"},
+ {file = "mmh3-4.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:8e2c1f6a2b41723a4f82bd5a762a777836d29d664fc0095f17910bea0adfd4a6"},
+ {file = "mmh3-4.1.0.tar.gz", hash = "sha256:a1cf25348b9acd229dda464a094d6170f47d2850a1fcb762a3b6172d2ce6ca4a"},
+]
+
+[package.extras]
+test = ["mypy (>=1.0)", "pytest (>=7.0.0)"]
+
+[[package]]
name = "mock"
version = "5.1.0"
description = "Rolling backport of unittest.mock for all Pythons"
@@ -2314,38 +2527,38 @@ files = [
[[package]]
name = "mypy"
-version = "1.7.1"
+version = "1.8.0"
description = "Optional static typing for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "mypy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:12cce78e329838d70a204293e7b29af9faa3ab14899aec397798a4b41be7f340"},
- {file = "mypy-1.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1484b8fa2c10adf4474f016e09d7a159602f3239075c7bf9f1627f5acf40ad49"},
- {file = "mypy-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31902408f4bf54108bbfb2e35369877c01c95adc6192958684473658c322c8a5"},
- {file = "mypy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f2c2521a8e4d6d769e3234350ba7b65ff5d527137cdcde13ff4d99114b0c8e7d"},
- {file = "mypy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:fcd2572dd4519e8a6642b733cd3a8cfc1ef94bafd0c1ceed9c94fe736cb65b6a"},
- {file = "mypy-1.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b901927f16224d0d143b925ce9a4e6b3a758010673eeded9b748f250cf4e8f7"},
- {file = "mypy-1.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2f7f6985d05a4e3ce8255396df363046c28bea790e40617654e91ed580ca7c51"},
- {file = "mypy-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:944bdc21ebd620eafefc090cdf83158393ec2b1391578359776c00de00e8907a"},
- {file = "mypy-1.7.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9c7ac372232c928fff0645d85f273a726970c014749b924ce5710d7d89763a28"},
- {file = "mypy-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:f6efc9bd72258f89a3816e3a98c09d36f079c223aa345c659622f056b760ab42"},
- {file = "mypy-1.7.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6dbdec441c60699288adf051f51a5d512b0d818526d1dcfff5a41f8cd8b4aaf1"},
- {file = "mypy-1.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fc3d14ee80cd22367caaaf6e014494415bf440980a3045bf5045b525680ac33"},
- {file = "mypy-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c6e4464ed5f01dc44dc9821caf67b60a4e5c3b04278286a85c067010653a0eb"},
- {file = "mypy-1.7.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d9b338c19fa2412f76e17525c1b4f2c687a55b156320acb588df79f2e6fa9fea"},
- {file = "mypy-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:204e0d6de5fd2317394a4eff62065614c4892d5a4d1a7ee55b765d7a3d9e3f82"},
- {file = "mypy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:84860e06ba363d9c0eeabd45ac0fde4b903ad7aa4f93cd8b648385a888e23200"},
- {file = "mypy-1.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8c5091ebd294f7628eb25ea554852a52058ac81472c921150e3a61cdd68f75a7"},
- {file = "mypy-1.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40716d1f821b89838589e5b3106ebbc23636ffdef5abc31f7cd0266db936067e"},
- {file = "mypy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cf3f0c5ac72139797953bd50bc6c95ac13075e62dbfcc923571180bebb662e9"},
- {file = "mypy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:78e25b2fd6cbb55ddfb8058417df193f0129cad5f4ee75d1502248e588d9e0d7"},
- {file = "mypy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75c4d2a6effd015786c87774e04331b6da863fc3fc4e8adfc3b40aa55ab516fe"},
- {file = "mypy-1.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2643d145af5292ee956aa0a83c2ce1038a3bdb26e033dadeb2f7066fb0c9abce"},
- {file = "mypy-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aa828610b67462ffe3057d4d8a4112105ed211596b750b53cbfe182f44777a"},
- {file = "mypy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ee5d62d28b854eb61889cde4e1dbc10fbaa5560cb39780c3995f6737f7e82120"},
- {file = "mypy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:72cf32ce7dd3562373f78bd751f73c96cfb441de147cc2448a92c1a308bd0ca6"},
- {file = "mypy-1.7.1-py3-none-any.whl", hash = "sha256:f7c5d642db47376a0cc130f0de6d055056e010debdaf0707cd2b0fc7e7ef30ea"},
- {file = "mypy-1.7.1.tar.gz", hash = "sha256:fcb6d9afb1b6208b4c712af0dafdc650f518836065df0d4fb1d800f5d6773db2"},
+ {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"},
+ {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"},
+ {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"},
+ {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"},
+ {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"},
+ {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"},
+ {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"},
+ {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"},
+ {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"},
+ {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"},
+ {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"},
+ {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"},
+ {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"},
+ {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"},
+ {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"},
+ {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"},
+ {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"},
+ {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"},
+ {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"},
+ {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"},
+ {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"},
+ {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"},
+ {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"},
+ {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"},
+ {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"},
+ {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"},
+ {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"},
]
[package.dependencies]
@@ -2404,49 +2617,65 @@ setuptools = "*"
[[package]]
name = "numpy"
-version = "1.26.2"
+version = "1.26.3"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.9"
files = [
- {file = "numpy-1.26.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3703fc9258a4a122d17043e57b35e5ef1c5a5837c3db8be396c82e04c1cf9b0f"},
- {file = "numpy-1.26.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc392fdcbd21d4be6ae1bb4475a03ce3b025cd49a9be5345d76d7585aea69440"},
- {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36340109af8da8805d8851ef1d74761b3b88e81a9bd80b290bbfed61bd2b4f75"},
- {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcc008217145b3d77abd3e4d5ef586e3bdfba8fe17940769f8aa09b99e856c00"},
- {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3ced40d4e9e18242f70dd02d739e44698df3dcb010d31f495ff00a31ef6014fe"},
- {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b272d4cecc32c9e19911891446b72e986157e6a1809b7b56518b4f3755267523"},
- {file = "numpy-1.26.2-cp310-cp310-win32.whl", hash = "sha256:22f8fc02fdbc829e7a8c578dd8d2e15a9074b630d4da29cda483337e300e3ee9"},
- {file = "numpy-1.26.2-cp310-cp310-win_amd64.whl", hash = "sha256:26c9d33f8e8b846d5a65dd068c14e04018d05533b348d9eaeef6c1bd787f9919"},
- {file = "numpy-1.26.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b96e7b9c624ef3ae2ae0e04fa9b460f6b9f17ad8b4bec6d7756510f1f6c0c841"},
- {file = "numpy-1.26.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aa18428111fb9a591d7a9cc1b48150097ba6a7e8299fb56bdf574df650e7d1f1"},
- {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06fa1ed84aa60ea6ef9f91ba57b5ed963c3729534e6e54055fc151fad0423f0a"},
- {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96ca5482c3dbdd051bcd1fce8034603d6ebfc125a7bd59f55b40d8f5d246832b"},
- {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:854ab91a2906ef29dc3925a064fcd365c7b4da743f84b123002f6139bcb3f8a7"},
- {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f43740ab089277d403aa07567be138fc2a89d4d9892d113b76153e0e412409f8"},
- {file = "numpy-1.26.2-cp311-cp311-win32.whl", hash = "sha256:a2bbc29fcb1771cd7b7425f98b05307776a6baf43035d3b80c4b0f29e9545186"},
- {file = "numpy-1.26.2-cp311-cp311-win_amd64.whl", hash = "sha256:2b3fca8a5b00184828d12b073af4d0fc5fdd94b1632c2477526f6bd7842d700d"},
- {file = "numpy-1.26.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a4cd6ed4a339c21f1d1b0fdf13426cb3b284555c27ac2f156dfdaaa7e16bfab0"},
- {file = "numpy-1.26.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d5244aabd6ed7f312268b9247be47343a654ebea52a60f002dc70c769048e75"},
- {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a3cdb4d9c70e6b8c0814239ead47da00934666f668426fc6e94cce869e13fd7"},
- {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa317b2325f7aa0a9471663e6093c210cb2ae9c0ad824732b307d2c51983d5b6"},
- {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:174a8880739c16c925799c018f3f55b8130c1f7c8e75ab0a6fa9d41cab092fd6"},
- {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f79b231bf5c16b1f39c7f4875e1ded36abee1591e98742b05d8a0fb55d8a3eec"},
- {file = "numpy-1.26.2-cp312-cp312-win32.whl", hash = "sha256:4a06263321dfd3598cacb252f51e521a8cb4b6df471bb12a7ee5cbab20ea9167"},
- {file = "numpy-1.26.2-cp312-cp312-win_amd64.whl", hash = "sha256:b04f5dc6b3efdaab541f7857351aac359e6ae3c126e2edb376929bd3b7f92d7e"},
- {file = "numpy-1.26.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4eb8df4bf8d3d90d091e0146f6c28492b0be84da3e409ebef54349f71ed271ef"},
- {file = "numpy-1.26.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1a13860fdcd95de7cf58bd6f8bc5a5ef81c0b0625eb2c9a783948847abbef2c2"},
- {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64308ebc366a8ed63fd0bf426b6a9468060962f1a4339ab1074c228fa6ade8e3"},
- {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baf8aab04a2c0e859da118f0b38617e5ee65d75b83795055fb66c0d5e9e9b818"},
- {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d73a3abcac238250091b11caef9ad12413dab01669511779bc9b29261dd50210"},
- {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b361d369fc7e5e1714cf827b731ca32bff8d411212fccd29ad98ad622449cc36"},
- {file = "numpy-1.26.2-cp39-cp39-win32.whl", hash = "sha256:bd3f0091e845164a20bd5a326860c840fe2af79fa12e0469a12768a3ec578d80"},
- {file = "numpy-1.26.2-cp39-cp39-win_amd64.whl", hash = "sha256:2beef57fb031dcc0dc8fa4fe297a742027b954949cabb52a2a376c144e5e6060"},
- {file = "numpy-1.26.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1cc3d5029a30fb5f06704ad6b23b35e11309491c999838c31f124fee32107c79"},
- {file = "numpy-1.26.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94cc3c222bb9fb5a12e334d0479b97bb2df446fbe622b470928f5284ffca3f8d"},
- {file = "numpy-1.26.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe6b44fb8fcdf7eda4ef4461b97b3f63c466b27ab151bec2366db8b197387841"},
- {file = "numpy-1.26.2.tar.gz", hash = "sha256:f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea"},
+ {file = "numpy-1.26.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:806dd64230dbbfaca8a27faa64e2f414bf1c6622ab78cc4264f7f5f028fee3bf"},
+ {file = "numpy-1.26.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f98011ba4ab17f46f80f7f8f1c291ee7d855fcef0a5a98db80767a468c85cd"},
+ {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d45b3ec2faed4baca41c76617fcdcfa4f684ff7a151ce6fc78ad3b6e85af0a6"},
+ {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdd2b45bf079d9ad90377048e2747a0c82351989a2165821f0c96831b4a2a54b"},
+ {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:211ddd1e94817ed2d175b60b6374120244a4dd2287f4ece45d49228b4d529178"},
+ {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1240f767f69d7c4c8a29adde2310b871153df9b26b5cb2b54a561ac85146485"},
+ {file = "numpy-1.26.3-cp310-cp310-win32.whl", hash = "sha256:21a9484e75ad018974a2fdaa216524d64ed4212e418e0a551a2d83403b0531d3"},
+ {file = "numpy-1.26.3-cp310-cp310-win_amd64.whl", hash = "sha256:9e1591f6ae98bcfac2a4bbf9221c0b92ab49762228f38287f6eeb5f3f55905ce"},
+ {file = "numpy-1.26.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b831295e5472954104ecb46cd98c08b98b49c69fdb7040483aff799a755a7374"},
+ {file = "numpy-1.26.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9e87562b91f68dd8b1c39149d0323b42e0082db7ddb8e934ab4c292094d575d6"},
+ {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c66d6fec467e8c0f975818c1796d25c53521124b7cfb760114be0abad53a0a2"},
+ {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f25e2811a9c932e43943a2615e65fc487a0b6b49218899e62e426e7f0a57eeda"},
+ {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af36e0aa45e25c9f57bf684b1175e59ea05d9a7d3e8e87b7ae1a1da246f2767e"},
+ {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:51c7f1b344f302067b02e0f5b5d2daa9ed4a721cf49f070280ac202738ea7f00"},
+ {file = "numpy-1.26.3-cp311-cp311-win32.whl", hash = "sha256:7ca4f24341df071877849eb2034948459ce3a07915c2734f1abb4018d9c49d7b"},
+ {file = "numpy-1.26.3-cp311-cp311-win_amd64.whl", hash = "sha256:39763aee6dfdd4878032361b30b2b12593fb445ddb66bbac802e2113eb8a6ac4"},
+ {file = "numpy-1.26.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a7081fd19a6d573e1a05e600c82a1c421011db7935ed0d5c483e9dd96b99cf13"},
+ {file = "numpy-1.26.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12c70ac274b32bc00c7f61b515126c9205323703abb99cd41836e8125ea0043e"},
+ {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f784e13e598e9594750b2ef6729bcd5a47f6cfe4a12cca13def35e06d8163e3"},
+ {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f24750ef94d56ce6e33e4019a8a4d68cfdb1ef661a52cdaee628a56d2437419"},
+ {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:77810ef29e0fb1d289d225cabb9ee6cf4d11978a00bb99f7f8ec2132a84e0166"},
+ {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8ed07a90f5450d99dad60d3799f9c03c6566709bd53b497eb9ccad9a55867f36"},
+ {file = "numpy-1.26.3-cp312-cp312-win32.whl", hash = "sha256:f73497e8c38295aaa4741bdfa4fda1a5aedda5473074369eca10626835445511"},
+ {file = "numpy-1.26.3-cp312-cp312-win_amd64.whl", hash = "sha256:da4b0c6c699a0ad73c810736303f7fbae483bcb012e38d7eb06a5e3b432c981b"},
+ {file = "numpy-1.26.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1666f634cb3c80ccbd77ec97bc17337718f56d6658acf5d3b906ca03e90ce87f"},
+ {file = "numpy-1.26.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18c3319a7d39b2c6a9e3bb75aab2304ab79a811ac0168a671a62e6346c29b03f"},
+ {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b7e807d6888da0db6e7e75838444d62495e2b588b99e90dd80c3459594e857b"},
+ {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4d362e17bcb0011738c2d83e0a65ea8ce627057b2fdda37678f4374a382a137"},
+ {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b8c275f0ae90069496068c714387b4a0eba5d531aace269559ff2b43655edd58"},
+ {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cc0743f0302b94f397a4a65a660d4cd24267439eb16493fb3caad2e4389bccbb"},
+ {file = "numpy-1.26.3-cp39-cp39-win32.whl", hash = "sha256:9bc6d1a7f8cedd519c4b7b1156d98e051b726bf160715b769106661d567b3f03"},
+ {file = "numpy-1.26.3-cp39-cp39-win_amd64.whl", hash = "sha256:867e3644e208c8922a3be26fc6bbf112a035f50f0a86497f98f228c50c607bb2"},
+ {file = "numpy-1.26.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3c67423b3703f8fbd90f5adaa37f85b5794d3366948efe9a5190a5f3a83fc34e"},
+ {file = "numpy-1.26.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46f47ee566d98849323f01b349d58f2557f02167ee301e5e28809a8c0e27a2d0"},
+ {file = "numpy-1.26.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a8474703bffc65ca15853d5fd4d06b18138ae90c17c8d12169968e998e448bb5"},
+ {file = "numpy-1.26.3.tar.gz", hash = "sha256:697df43e2b6310ecc9d95f05d5ef20eacc09c7c4ecc9da3f235d39e71b7da1e4"},
+]
+
+[[package]]
+name = "oauthlib"
+version = "3.2.2"
+description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"},
+ {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"},
]
+[package.extras]
+rsa = ["cryptography (>=3.0.0)"]
+signals = ["blinker (>=1.4.0)"]
+signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"]
+
[[package]]
name = "onnxruntime"
version = "1.16.3"
@@ -2490,25 +2719,192 @@ sympy = "*"
[[package]]
name = "openai"
-version = "0.27.10"
-description = "Python client library for the OpenAI API"
+version = "1.7.2"
+description = "The official Python library for the openai API"
optional = false
python-versions = ">=3.7.1"
files = [
- {file = "openai-0.27.10-py3-none-any.whl", hash = "sha256:beabd1757e3286fa166dde3b70ebb5ad8081af046876b47c14c41e203ed22a14"},
- {file = "openai-0.27.10.tar.gz", hash = "sha256:60e09edf7100080283688748c6803b7b3b52d5a55d21890f3815292a0552d83b"},
+ {file = "openai-1.7.2-py3-none-any.whl", hash = "sha256:8f41b90a762f5fd9d182b45851041386fed94c8ad240a70abefee61a68e0ef53"},
+ {file = "openai-1.7.2.tar.gz", hash = "sha256:c73c78878258b07f1b468b0602c6591f25a1478f49ecb90b9bd44b7cc80bce73"},
]
[package.dependencies]
-aiohttp = "*"
-requests = ">=2.20"
-tqdm = "*"
+anyio = ">=3.5.0,<5"
+distro = ">=1.7.0,<2"
+httpx = ">=0.23.0,<1"
+pydantic = ">=1.9.0,<3"
+sniffio = "*"
+tqdm = ">4"
+typing-extensions = ">=4.7,<5"
[package.extras]
-datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
-dev = ["black (>=21.6b0,<22.0)", "pytest (==6.*)", "pytest-asyncio", "pytest-mock"]
-embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"]
-wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"]
+datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
+
+[[package]]
+name = "opentelemetry-api"
+version = "1.22.0"
+description = "OpenTelemetry Python API"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_api-1.22.0-py3-none-any.whl", hash = "sha256:43621514301a7e9f5d06dd8013a1b450f30c2e9372b8e30aaeb4562abf2ce034"},
+ {file = "opentelemetry_api-1.22.0.tar.gz", hash = "sha256:15ae4ca925ecf9cfdfb7a709250846fbb08072260fca08ade78056c502b86bed"},
+]
+
+[package.dependencies]
+deprecated = ">=1.2.6"
+importlib-metadata = ">=6.0,<7.0"
+
+[[package]]
+name = "opentelemetry-exporter-otlp-proto-common"
+version = "1.22.0"
+description = "OpenTelemetry Protobuf encoding"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_exporter_otlp_proto_common-1.22.0-py3-none-any.whl", hash = "sha256:3f2538bec5312587f8676c332b3747f54c89fe6364803a807e217af4603201fa"},
+ {file = "opentelemetry_exporter_otlp_proto_common-1.22.0.tar.gz", hash = "sha256:71ae2f81bc6d6fe408d06388826edc8933759b2ca3a97d24054507dc7cfce52d"},
+]
+
+[package.dependencies]
+backoff = {version = ">=1.10.0,<3.0.0", markers = "python_version >= \"3.7\""}
+opentelemetry-proto = "1.22.0"
+
+[[package]]
+name = "opentelemetry-exporter-otlp-proto-grpc"
+version = "1.22.0"
+description = "OpenTelemetry Collector Protobuf over gRPC Exporter"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_exporter_otlp_proto_grpc-1.22.0-py3-none-any.whl", hash = "sha256:b5bcadc129272004316a455e9081216d3380c1fc2231a928ea6a70aa90e173fb"},
+ {file = "opentelemetry_exporter_otlp_proto_grpc-1.22.0.tar.gz", hash = "sha256:1e0e5aa4bbabc74942f06f268deffd94851d12a8dc30b02527472ef1729fe5b1"},
+]
+
+[package.dependencies]
+backoff = {version = ">=1.10.0,<3.0.0", markers = "python_version >= \"3.7\""}
+deprecated = ">=1.2.6"
+googleapis-common-protos = ">=1.52,<2.0"
+grpcio = ">=1.0.0,<2.0.0"
+opentelemetry-api = ">=1.15,<2.0"
+opentelemetry-exporter-otlp-proto-common = "1.22.0"
+opentelemetry-proto = "1.22.0"
+opentelemetry-sdk = ">=1.22.0,<1.23.0"
+
+[package.extras]
+test = ["pytest-grpc"]
+
+[[package]]
+name = "opentelemetry-instrumentation"
+version = "0.43b0"
+description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_instrumentation-0.43b0-py3-none-any.whl", hash = "sha256:0ff1334d7e359e27640e9d420024efeb73eacae464309c2e14ede7ba6c93967e"},
+ {file = "opentelemetry_instrumentation-0.43b0.tar.gz", hash = "sha256:c3755da6c4be8033be0216d0501e11f4832690f4e2eca5a3576fbf113498f0f6"},
+]
+
+[package.dependencies]
+opentelemetry-api = ">=1.4,<2.0"
+setuptools = ">=16.0"
+wrapt = ">=1.0.0,<2.0.0"
+
+[[package]]
+name = "opentelemetry-instrumentation-asgi"
+version = "0.43b0"
+description = "ASGI instrumentation for OpenTelemetry"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_instrumentation_asgi-0.43b0-py3-none-any.whl", hash = "sha256:1f593829fa039e9367820736fb063e92acd15c25b53d7bcb5d319971b8e93fd7"},
+ {file = "opentelemetry_instrumentation_asgi-0.43b0.tar.gz", hash = "sha256:3f6f19333dca31ef696672e4e36cb1c2613c71dc7e847c11ff36a37e1130dadc"},
+]
+
+[package.dependencies]
+asgiref = ">=3.0,<4.0"
+opentelemetry-api = ">=1.12,<2.0"
+opentelemetry-instrumentation = "0.43b0"
+opentelemetry-semantic-conventions = "0.43b0"
+opentelemetry-util-http = "0.43b0"
+
+[package.extras]
+instruments = ["asgiref (>=3.0,<4.0)"]
+test = ["opentelemetry-instrumentation-asgi[instruments]", "opentelemetry-test-utils (==0.43b0)"]
+
+[[package]]
+name = "opentelemetry-instrumentation-fastapi"
+version = "0.43b0"
+description = "OpenTelemetry FastAPI Instrumentation"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_instrumentation_fastapi-0.43b0-py3-none-any.whl", hash = "sha256:b79c044df68a52e07b35fa12a424e7cc0dd27ff0a171c5fdcc41dea9de8fc938"},
+ {file = "opentelemetry_instrumentation_fastapi-0.43b0.tar.gz", hash = "sha256:2afaaf470622e1a2732182c68f6d2431ffe5e026a7edacd0f83605632b66347f"},
+]
+
+[package.dependencies]
+opentelemetry-api = ">=1.12,<2.0"
+opentelemetry-instrumentation = "0.43b0"
+opentelemetry-instrumentation-asgi = "0.43b0"
+opentelemetry-semantic-conventions = "0.43b0"
+opentelemetry-util-http = "0.43b0"
+
+[package.extras]
+instruments = ["fastapi (>=0.58,<1.0)"]
+test = ["httpx (>=0.22,<1.0)", "opentelemetry-instrumentation-fastapi[instruments]", "opentelemetry-test-utils (==0.43b0)", "requests (>=2.23,<3.0)"]
+
+[[package]]
+name = "opentelemetry-proto"
+version = "1.22.0"
+description = "OpenTelemetry Python Proto"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_proto-1.22.0-py3-none-any.whl", hash = "sha256:ce7188d22c75b6d0fe53e7fb58501613d0feade5139538e79dedd9420610fa0c"},
+ {file = "opentelemetry_proto-1.22.0.tar.gz", hash = "sha256:9ec29169286029f17ca34ec1f3455802ffb90131642d2f545ece9a63e8f69003"},
+]
+
+[package.dependencies]
+protobuf = ">=3.19,<5.0"
+
+[[package]]
+name = "opentelemetry-sdk"
+version = "1.22.0"
+description = "OpenTelemetry Python SDK"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_sdk-1.22.0-py3-none-any.whl", hash = "sha256:a730555713d7c8931657612a88a141e3a4fe6eb5523d9e2d5a8b1e673d76efa6"},
+ {file = "opentelemetry_sdk-1.22.0.tar.gz", hash = "sha256:45267ac1f38a431fc2eb5d6e0c0d83afc0b78de57ac345488aa58c28c17991d0"},
+]
+
+[package.dependencies]
+opentelemetry-api = "1.22.0"
+opentelemetry-semantic-conventions = "0.43b0"
+typing-extensions = ">=3.7.4"
+
+[[package]]
+name = "opentelemetry-semantic-conventions"
+version = "0.43b0"
+description = "OpenTelemetry Semantic Conventions"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_semantic_conventions-0.43b0-py3-none-any.whl", hash = "sha256:291284d7c1bf15fdaddf309b3bd6d3b7ce12a253cec6d27144439819a15d8445"},
+ {file = "opentelemetry_semantic_conventions-0.43b0.tar.gz", hash = "sha256:b9576fb890df479626fa624e88dde42d3d60b8b6c8ae1152ad157a8b97358635"},
+]
+
+[[package]]
+name = "opentelemetry-util-http"
+version = "0.43b0"
+description = "Web util for OpenTelemetry"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "opentelemetry_util_http-0.43b0-py3-none-any.whl", hash = "sha256:f25a820784b030f6cb86b3d76e5676c769b75ed3f55a210bcdae0a5e175ebadb"},
+ {file = "opentelemetry_util_http-0.43b0.tar.gz", hash = "sha256:3ff6ab361dbe99fc81200d625603c0fb890c055c6e416a3e6d661ddf47a6c7f7"},
+]
[[package]]
name = "outcome"
@@ -2656,70 +3052,88 @@ ptyprocess = ">=0.5"
[[package]]
name = "pillow"
-version = "10.1.0"
+version = "10.2.0"
description = "Python Imaging Library (Fork)"
optional = true
python-versions = ">=3.8"
files = [
- {file = "Pillow-10.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106"},
- {file = "Pillow-10.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273"},
- {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666"},
- {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2"},
- {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593"},
- {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db"},
- {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f"},
- {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818"},
- {file = "Pillow-10.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57"},
- {file = "Pillow-10.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7"},
- {file = "Pillow-10.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7"},
- {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610"},
- {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839"},
- {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172"},
- {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061"},
- {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262"},
- {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992"},
- {file = "Pillow-10.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a"},
- {file = "Pillow-10.1.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b"},
- {file = "Pillow-10.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d"},
- {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27"},
- {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312"},
- {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de"},
- {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651"},
- {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b"},
- {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f"},
- {file = "Pillow-10.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996"},
- {file = "Pillow-10.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793"},
- {file = "Pillow-10.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e"},
- {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2"},
- {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a"},
- {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01"},
- {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d"},
- {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80"},
- {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212"},
- {file = "Pillow-10.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14"},
- {file = "Pillow-10.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099"},
- {file = "Pillow-10.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616"},
- {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb"},
- {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219"},
- {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34"},
- {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd"},
- {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28"},
- {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2"},
- {file = "Pillow-10.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256"},
- {file = "Pillow-10.1.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7"},
- {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba"},
- {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4"},
- {file = "Pillow-10.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9"},
- {file = "Pillow-10.1.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e"},
- {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412"},
- {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b"},
- {file = "Pillow-10.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f"},
- {file = "Pillow-10.1.0.tar.gz", hash = "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38"},
+ {file = "pillow-10.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e"},
+ {file = "pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2"},
+ {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c"},
+ {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0"},
+ {file = "pillow-10.2.0-cp310-cp310-win32.whl", hash = "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023"},
+ {file = "pillow-10.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72"},
+ {file = "pillow-10.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad"},
+ {file = "pillow-10.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5"},
+ {file = "pillow-10.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311"},
+ {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1"},
+ {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757"},
+ {file = "pillow-10.2.0-cp311-cp311-win32.whl", hash = "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068"},
+ {file = "pillow-10.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56"},
+ {file = "pillow-10.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1"},
+ {file = "pillow-10.2.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef"},
+ {file = "pillow-10.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04"},
+ {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f"},
+ {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb"},
+ {file = "pillow-10.2.0-cp312-cp312-win32.whl", hash = "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f"},
+ {file = "pillow-10.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9"},
+ {file = "pillow-10.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48"},
+ {file = "pillow-10.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9"},
+ {file = "pillow-10.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d"},
+ {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6"},
+ {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe"},
+ {file = "pillow-10.2.0-cp38-cp38-win32.whl", hash = "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e"},
+ {file = "pillow-10.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39"},
+ {file = "pillow-10.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67"},
+ {file = "pillow-10.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13"},
+ {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7"},
+ {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591"},
+ {file = "pillow-10.2.0-cp39-cp39-win32.whl", hash = "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516"},
+ {file = "pillow-10.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8"},
+ {file = "pillow-10.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6"},
+ {file = "pillow-10.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"},
+ {file = "pillow-10.2.0.tar.gz", hash = "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e"},
]
[package.extras]
docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"]
+fpx = ["olefile"]
+mic = ["olefile"]
tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
+typing = ["typing-extensions"]
+xmp = ["defusedxml"]
[[package]]
name = "platformdirs"
@@ -2753,13 +3167,13 @@ testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "posthog"
-version = "3.1.0"
+version = "3.3.1"
description = "Integrate PostHog into any python application."
optional = false
python-versions = "*"
files = [
- {file = "posthog-3.1.0-py2.py3-none-any.whl", hash = "sha256:acd033530bdfc275dce5587f205f62378991ecb9b7cd5479e79c7f4ac575d319"},
- {file = "posthog-3.1.0.tar.gz", hash = "sha256:db17a2c511e18757aec12b6632ddcc1fa318743dad88a4666010467a3d9468da"},
+ {file = "posthog-3.3.1-py2.py3-none-any.whl", hash = "sha256:5f53b232acb680a0389e372db5f786061a18386b8b5324bddcc64eff9fdb319b"},
+ {file = "posthog-3.3.1.tar.gz", hash = "sha256:252cb6ab5cbe7ff002753f34fb647721b3af75034b4a5a631317ebf3db58fe59"},
]
[package.dependencies]
@@ -2808,47 +3222,47 @@ wcwidth = "*"
[[package]]
name = "protobuf"
-version = "4.25.1"
+version = "4.25.2"
description = ""
optional = false
python-versions = ">=3.8"
files = [
- {file = "protobuf-4.25.1-cp310-abi3-win32.whl", hash = "sha256:193f50a6ab78a970c9b4f148e7c750cfde64f59815e86f686c22e26b4fe01ce7"},
- {file = "protobuf-4.25.1-cp310-abi3-win_amd64.whl", hash = "sha256:3497c1af9f2526962f09329fd61a36566305e6c72da2590ae0d7d1322818843b"},
- {file = "protobuf-4.25.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:0bf384e75b92c42830c0a679b0cd4d6e2b36ae0cf3dbb1e1dfdda48a244f4bcd"},
- {file = "protobuf-4.25.1-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:0f881b589ff449bf0b931a711926e9ddaad3b35089cc039ce1af50b21a4ae8cb"},
- {file = "protobuf-4.25.1-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:ca37bf6a6d0046272c152eea90d2e4ef34593aaa32e8873fc14c16440f22d4b7"},
- {file = "protobuf-4.25.1-cp38-cp38-win32.whl", hash = "sha256:abc0525ae2689a8000837729eef7883b9391cd6aa7950249dcf5a4ede230d5dd"},
- {file = "protobuf-4.25.1-cp38-cp38-win_amd64.whl", hash = "sha256:1484f9e692091450e7edf418c939e15bfc8fc68856e36ce399aed6889dae8bb0"},
- {file = "protobuf-4.25.1-cp39-cp39-win32.whl", hash = "sha256:8bdbeaddaac52d15c6dce38c71b03038ef7772b977847eb6d374fc86636fa510"},
- {file = "protobuf-4.25.1-cp39-cp39-win_amd64.whl", hash = "sha256:becc576b7e6b553d22cbdf418686ee4daa443d7217999125c045ad56322dda10"},
- {file = "protobuf-4.25.1-py3-none-any.whl", hash = "sha256:a19731d5e83ae4737bb2a089605e636077ac001d18781b3cf489b9546c7c80d6"},
- {file = "protobuf-4.25.1.tar.gz", hash = "sha256:57d65074b4f5baa4ab5da1605c02be90ac20c8b40fb137d6a8df9f416b0d0ce2"},
+ {file = "protobuf-4.25.2-cp310-abi3-win32.whl", hash = "sha256:b50c949608682b12efb0b2717f53256f03636af5f60ac0c1d900df6213910fd6"},
+ {file = "protobuf-4.25.2-cp310-abi3-win_amd64.whl", hash = "sha256:8f62574857ee1de9f770baf04dde4165e30b15ad97ba03ceac65f760ff018ac9"},
+ {file = "protobuf-4.25.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:2db9f8fa64fbdcdc93767d3cf81e0f2aef176284071507e3ede160811502fd3d"},
+ {file = "protobuf-4.25.2-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:10894a2885b7175d3984f2be8d9850712c57d5e7587a2410720af8be56cdaf62"},
+ {file = "protobuf-4.25.2-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:fc381d1dd0516343f1440019cedf08a7405f791cd49eef4ae1ea06520bc1c020"},
+ {file = "protobuf-4.25.2-cp38-cp38-win32.whl", hash = "sha256:33a1aeef4b1927431d1be780e87b641e322b88d654203a9e9d93f218ee359e61"},
+ {file = "protobuf-4.25.2-cp38-cp38-win_amd64.whl", hash = "sha256:47f3de503fe7c1245f6f03bea7e8d3ec11c6c4a2ea9ef910e3221c8a15516d62"},
+ {file = "protobuf-4.25.2-cp39-cp39-win32.whl", hash = "sha256:5e5c933b4c30a988b52e0b7c02641760a5ba046edc5e43d3b94a74c9fc57c1b3"},
+ {file = "protobuf-4.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:d66a769b8d687df9024f2985d5137a337f957a0916cf5464d1513eee96a63ff0"},
+ {file = "protobuf-4.25.2-py3-none-any.whl", hash = "sha256:a8b7a98d4ce823303145bf3c1a8bdb0f2f4642a414b196f04ad9853ed0c8f830"},
+ {file = "protobuf-4.25.2.tar.gz", hash = "sha256:fe599e175cb347efc8ee524bcd4b902d11f7262c0e569ececcb89995c15f0a5e"},
]
[[package]]
name = "psutil"
-version = "5.9.6"
+version = "5.9.7"
description = "Cross-platform lib for process and system monitoring in Python."
optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
- {file = "psutil-5.9.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d"},
- {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c"},
- {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28"},
- {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017"},
- {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c"},
- {file = "psutil-5.9.6-cp27-none-win32.whl", hash = "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9"},
- {file = "psutil-5.9.6-cp27-none-win_amd64.whl", hash = "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac"},
- {file = "psutil-5.9.6-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a"},
- {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c"},
- {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4"},
- {file = "psutil-5.9.6-cp36-cp36m-win32.whl", hash = "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602"},
- {file = "psutil-5.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa"},
- {file = "psutil-5.9.6-cp37-abi3-win32.whl", hash = "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c"},
- {file = "psutil-5.9.6-cp37-abi3-win_amd64.whl", hash = "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a"},
- {file = "psutil-5.9.6-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57"},
- {file = "psutil-5.9.6.tar.gz", hash = "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a"},
+ {file = "psutil-5.9.7-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0bd41bf2d1463dfa535942b2a8f0e958acf6607ac0be52265ab31f7923bcd5e6"},
+ {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:5794944462509e49d4d458f4dbfb92c47539e7d8d15c796f141f474010084056"},
+ {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:fe361f743cb3389b8efda21980d93eb55c1f1e3898269bc9a2a1d0bb7b1f6508"},
+ {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:e469990e28f1ad738f65a42dcfc17adaed9d0f325d55047593cb9033a0ab63df"},
+ {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:3c4747a3e2ead1589e647e64aad601981f01b68f9398ddf94d01e3dc0d1e57c7"},
+ {file = "psutil-5.9.7-cp27-none-win32.whl", hash = "sha256:1d4bc4a0148fdd7fd8f38e0498639ae128e64538faa507df25a20f8f7fb2341c"},
+ {file = "psutil-5.9.7-cp27-none-win_amd64.whl", hash = "sha256:4c03362e280d06bbbfcd52f29acd79c733e0af33d707c54255d21029b8b32ba6"},
+ {file = "psutil-5.9.7-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ea36cc62e69a13ec52b2f625c27527f6e4479bca2b340b7a452af55b34fcbe2e"},
+ {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1132704b876e58d277168cd729d64750633d5ff0183acf5b3c986b8466cd0284"},
+ {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe8b7f07948f1304497ce4f4684881250cd859b16d06a1dc4d7941eeb6233bfe"},
+ {file = "psutil-5.9.7-cp36-cp36m-win32.whl", hash = "sha256:b27f8fdb190c8c03914f908a4555159327d7481dac2f01008d483137ef3311a9"},
+ {file = "psutil-5.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:44969859757f4d8f2a9bd5b76eba8c3099a2c8cf3992ff62144061e39ba8568e"},
+ {file = "psutil-5.9.7-cp37-abi3-win32.whl", hash = "sha256:c727ca5a9b2dd5193b8644b9f0c883d54f1248310023b5ad3e92036c5e2ada68"},
+ {file = "psutil-5.9.7-cp37-abi3-win_amd64.whl", hash = "sha256:f37f87e4d73b79e6c5e749440c3113b81d1ee7d26f21c19c47371ddea834f414"},
+ {file = "psutil-5.9.7-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:032f4f2c909818c86cea4fe2cc407f1c0f0cde8e6c6d702b28b8ce0c0d143340"},
+ {file = "psutil-5.9.7.tar.gz", hash = "sha256:3f02134e82cfb5d089fddf20bb2e03fd5cd52395321d1c8458a9e58500ff417c"},
]
[package.extras]
@@ -2867,50 +3281,50 @@ files = [
[[package]]
name = "pulsar-client"
-version = "3.3.0"
+version = "3.4.0"
description = "Apache Pulsar Python client library"
optional = false
python-versions = "*"
files = [
- {file = "pulsar_client-3.3.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:c31afd3e67a044ff93177df89e08febf214cc965e95ede097d9fe8755af00e01"},
- {file = "pulsar_client-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f66982284571674b215324cc26b5c2f7c56c7043113c47a7084cb70d67a8afb"},
- {file = "pulsar_client-3.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fe50a06f81c48a75a9b95c27a6446260039adca71d9face273740de96b2efca"},
- {file = "pulsar_client-3.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d4c46a4b96a6e9919cfe220156d69a2ede8053d9ea1add4ada108abcf2ba9775"},
- {file = "pulsar_client-3.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1e4b5d44b992c9b036286b483f3588c10b89c6047fb59d80c7474445997f4e10"},
- {file = "pulsar_client-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:497a59ac6b650835a3b2c502f53477e5c98e5226998ca3f17c0b0a3eb4d67d08"},
- {file = "pulsar_client-3.3.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:386e78ff52058d881780bae1f6e84ac9434ae0b01a8581755ca8cc0dc844a332"},
- {file = "pulsar_client-3.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e4ecb780df58bcfd3918590bd3ff31ed79bccfbef3a1a60370642eb1e14a9d2"},
- {file = "pulsar_client-3.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ce1e215c252f22a6f26ca5e9076826041a04d88dc213b92c86b524be2774a64"},
- {file = "pulsar_client-3.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:88b0fd5be73a4103986b9dbe3a66468cf8829371e34af87ff8f216e3980f4cbe"},
- {file = "pulsar_client-3.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33656450536d83eed1563ff09692c2c415fb199d88e9ed97d701ca446a119e1b"},
- {file = "pulsar_client-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:ce33de700b06583df8777e139d68cb4b4b3d0a2eac168d74278d8935f357fb10"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-macosx_10_15_universal2.whl", hash = "sha256:7b5dd25cf778d6c980d36c53081e843ea272afe7af4f0ad6394ae9513f94641b"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33c4e6865fda62a2e460f823dce4d49ac2973a4459b8ff99eda5fdd6aaaebf46"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1810ddc623c8de2675d17405ce47057a9a2b92298e708ce4d9564847f5ad904"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8259c3b856eb6deaa1f93dce893ab18d99d36d102da5612c8e97a4fb41b70ab1"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5e7a48b2e505cde758fd51a601b5da0671fa98c9baee38362aaaa3ab2b930c28"},
- {file = "pulsar_client-3.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ede264385d47257b2f2b08ecde9181ec5338bea5639cc543d1856f01736778d2"},
- {file = "pulsar_client-3.3.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:0f64c62746ccd5b65a0c505f5f40b9af1f147eb1fa2d8f9c90cd5c8b92dd8597"},
- {file = "pulsar_client-3.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b84a20c9012e3c4ef1b7085acd7467197118c090b378dec27d773fb79d91556"},
- {file = "pulsar_client-3.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4e15fa696e275ccb66d0791fdc19c4dea0420d81349c8055e485b134125e14f"},
- {file = "pulsar_client-3.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:72cbb1bdcba2dd1265296b5ba65331622ee89c16db75edaad46dd7b90c6dd447"},
- {file = "pulsar_client-3.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d54dd12955bf587dd46d9184444af5e853d9da2a14bbfb739ed2c7c3b78ce280"},
- {file = "pulsar_client-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:43f98afdf0334b2b957a4d96f97a1fe8a7f7fd1e2631d40c3f00b4162f396485"},
- {file = "pulsar_client-3.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:efe7c1e6a96daccc522c3567b6847ffa54c13e0f510d9a427b4aeff9fbebe54b"},
- {file = "pulsar_client-3.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f28e94420090fceeb38e23fc744f3edf8710e48314ef5927d2b674a1d1e43ee0"},
- {file = "pulsar_client-3.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42c8f3eaa98e2351805ecb6efb6d5fedf47a314a3ce6af0e05ea1449ea7244ed"},
- {file = "pulsar_client-3.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5e69750f8ae57e55fddf97b459ce0d8b38b2bb85f464a71e871ee6a86d893be7"},
- {file = "pulsar_client-3.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7e147e5ba460c1818bc05254279a885b4e552bcafb8961d40e31f98d5ff46628"},
- {file = "pulsar_client-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:694530af1d6c75fb81456fb509778c1868adee31e997ddece6e21678200182ea"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:ebf99db5244ff69479283b25621b070492acc4bb643d162d86b90387cb6fdb2a"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6cb5d8e1482a8aea758633be23717e0c4bb7dc53784e37915c0048c0382f134"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b30a7592e42c76034e9a8d64d42dd5bab361425f869de562e9ccad698e19cd88"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5963090a78a5644ba25f41da3a6d49ea3f00c972b095baff365916dc246426a"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:419cdcf577f755e3f31bf264300d9ba158325edb2ee9cee555d81ba1909c094e"},
+ {file = "pulsar_client-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:4c93c35ee97307dae153e748b33dcd3d4f06da34bca373321aa2df73f1535705"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:11952fb022ee72debf53b169f4482f9dc5c890be0149ae98779864b3a21f1bd3"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8743c320aa96798d20cafa98ea97a68c4295fc4872c23acd5e012fd36cb06ba"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33571de99cd898349f17978ba62e2b839ea0275fb7067f31bf5f6ebfeae0987d"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a60c03c3e70f018538e7cd3fa84d95e283b610272b744166dbc48960a809fa07"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c47041267b5843ffec54352d842156c279945f3e976d7025ffa89875ff76390"},
+ {file = "pulsar_client-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:49fe4ab04004b476c87ab3ad22fe87346fca564a3e3ca9c0ac58fee45a895d81"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:1e077a4839be3ead3de3f05b4c244269dca2df07f47cea0b90544c7e9dc1642f"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f202b84e1f683d64672dd1971114600ae2e5c3735587286ff9bfb431385f08e8"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c606c04f357341042fa6c75477de7d2204f7ae50aa29c2f74b24e54c85f47f96"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c67b25ede3a578f5a7dc30230e52609ef38191f74b47e5cbdbc98c42df556927"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b7f8211cc9460cdf4d06e4e1cb878689d2aa4a7e4027bd2a2f1419a79ade16a6"},
+ {file = "pulsar_client-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:c5399e9780d6951c69808c0b6175311a966af82fb08addf6e741ae37b1bee7ef"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:a2d6c850b60106dc915d3476a490fba547c6748a5f742b68abd30d1a35355b82"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a52ea8294a9f30eb6f0a2db5dc16e3aad7ff2284f818c48ad3a6b601723be02b"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eeeede40108be12222e009285c971e5b8f6433d9f0f8ef934d6a131585921c4"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9409066c600f2b6f220552c5dfe08aeeabcf07fe0e76367aa5816b2e87a5cf72"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:58e2f886e6dab43e66c3ce990fe96209e55ab46350506829a637b77b74125fb9"},
+ {file = "pulsar_client-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:b57dfa5063b0d9dc7664896c55605eac90753e35e80db5a959d3be2be0ab0d48"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:7704c664aa2c801af4c2d3a58e9d8ffaeef12ce8a0f71712e9187f9a96da856f"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0364db563e27442053bdbb8655e7ffb420f491690bc2c78da5a58bd35c658ad"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3e34de19e0744d8aa3538cb2172076bccd0761b3e94ebadb7bd59765ae3d1ed"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:dc8be41dec8cb052fb1837550f495e9b73a8b3cf85e07157904ec84832758a65"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b49d669bed15b7edb9c936704310d57808f1d01c511b94d866f54fe8ffe1752d"},
+ {file = "pulsar_client-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:88c93e5fbfc349f3967e931f7a908d15fd4fd725ebdd842423ac9cd961fe293f"},
]
[package.dependencies]
certifi = "*"
[package.extras]
-all = ["apache-bookkeeper-client (>=4.16.1)", "fastavro (==1.7.3)", "grpcio (>=1.8.2)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"]
-avro = ["fastavro (==1.7.3)"]
-functions = ["apache-bookkeeper-client (>=4.16.1)", "grpcio (>=1.8.2)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"]
+all = ["apache-bookkeeper-client (>=4.16.1)", "fastavro (>=1.9.2)", "grpcio (>=1.60.0)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"]
+avro = ["fastavro (>=1.9.2)"]
+functions = ["apache-bookkeeper-client (>=4.16.1)", "grpcio (>=1.60.0)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"]
[[package]]
name = "pure-eval"
@@ -3027,12 +3441,12 @@ email = ["email-validator (>=1.0.3)"]
[[package]]
name = "pydevd-pycharm"
-version = "233.11799.298"
+version = "233.13763.5"
description = "PyCharm Debugger (used in PyCharm and PyDev)"
optional = false
python-versions = "*"
files = [
- {file = "pydevd-pycharm-233.11799.298.tar.gz", hash = "sha256:e6524d71c6d63bb7966440afc839ac8fa5ad567b1be9a2d2abd28e8230d156d5"},
+ {file = "pydevd-pycharm-233.13763.5.tar.gz", hash = "sha256:2585e3c8a0048f65a7276bb40805e851a76355ca6528523de8561f9369102fff"},
]
[[package]]
@@ -3062,17 +3476,6 @@ plugins = ["importlib-metadata"]
windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
-name = "pyhumps"
-version = "3.8.0"
-description = "🐫 Convert strings (and dictionary keys) between snake case, camel case and pascal case in Python. Inspired by Humps for Node"
-optional = true
-python-versions = "*"
-files = [
- {file = "pyhumps-3.8.0-py3-none-any.whl", hash = "sha256:060e1954d9069f428232a1adda165db0b9d8dfdce1d265d36df7fbff540acfd6"},
- {file = "pyhumps-3.8.0.tar.gz", hash = "sha256:498026258f7ee1a8e447c2e28526c0bea9407f9a59c03260aee4bd6c04d681a3"},
-]
-
-[[package]]
name = "pyparsing"
version = "3.1.1"
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
@@ -3097,6 +3500,20 @@ files = [
]
[[package]]
+name = "pyproject-hooks"
+version = "1.0.0"
+description = "Wrappers to call pyproject.toml-based build backend hooks."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pyproject_hooks-1.0.0-py3-none-any.whl", hash = "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8"},
+ {file = "pyproject_hooks-1.0.0.tar.gz", hash = "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5"},
+]
+
+[package.dependencies]
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+
+[[package]]
name = "pyreadline3"
version = "3.4.1"
description = "A python implementation of GNU readline."
@@ -3121,13 +3538,13 @@ files = [
[[package]]
name = "pytest"
-version = "7.4.3"
+version = "7.4.4"
description = "pytest: simple powerful testing with Python"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"},
- {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"},
+ {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"},
+ {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"},
]
[package.dependencies]
@@ -3189,17 +3606,17 @@ cli = ["click (>=5.0)"]
[[package]]
name = "python-multipart"
-version = "0.0.6"
+version = "0.0.7"
description = "A streaming multipart parser for Python"
optional = false
python-versions = ">=3.7"
files = [
- {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"},
- {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"},
+ {file = "python_multipart-0.0.7-py3-none-any.whl", hash = "sha256:b1fef9a53b74c795e2347daac8c54b252d9e0df9c619712691c1cc8021bd3c49"},
+ {file = "python_multipart-0.0.7.tar.gz", hash = "sha256:288a6c39b06596c1b988bb6794c6fbc80e6c369e35e5062637df256bee0c9af9"},
]
[package.extras]
-dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"]
+dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==2.2.0)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"]
[[package]]
name = "pytz"
@@ -3253,6 +3670,7 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
@@ -3289,99 +3707,104 @@ files = [
[[package]]
name = "regex"
-version = "2023.10.3"
+version = "2023.12.25"
description = "Alternative regular expression module, to replace re."
optional = false
python-versions = ">=3.7"
files = [
- {file = "regex-2023.10.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4c34d4f73ea738223a094d8e0ffd6d2c1a1b4c175da34d6b0de3d8d69bee6bcc"},
- {file = "regex-2023.10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8f4e49fc3ce020f65411432183e6775f24e02dff617281094ba6ab079ef0915"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cd1bccf99d3ef1ab6ba835308ad85be040e6a11b0977ef7ea8c8005f01a3c29"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81dce2ddc9f6e8f543d94b05d56e70d03a0774d32f6cca53e978dc01e4fc75b8"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c6b4d23c04831e3ab61717a707a5d763b300213db49ca680edf8bf13ab5d91b"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c15ad0aee158a15e17e0495e1e18741573d04eb6da06d8b84af726cfc1ed02ee"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6239d4e2e0b52c8bd38c51b760cd870069f0bdf99700a62cd509d7a031749a55"},
- {file = "regex-2023.10.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4a8bf76e3182797c6b1afa5b822d1d5802ff30284abe4599e1247be4fd6b03be"},
- {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9c727bbcf0065cbb20f39d2b4f932f8fa1631c3e01fcedc979bd4f51fe051c5"},
- {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3ccf2716add72f80714b9a63899b67fa711b654be3fcdd34fa391d2d274ce767"},
- {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:107ac60d1bfdc3edb53be75e2a52aff7481b92817cfdddd9b4519ccf0e54a6ff"},
- {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:00ba3c9818e33f1fa974693fb55d24cdc8ebafcb2e4207680669d8f8d7cca79a"},
- {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f0a47efb1dbef13af9c9a54a94a0b814902e547b7f21acb29434504d18f36e3a"},
- {file = "regex-2023.10.3-cp310-cp310-win32.whl", hash = "sha256:36362386b813fa6c9146da6149a001b7bd063dabc4d49522a1f7aa65b725c7ec"},
- {file = "regex-2023.10.3-cp310-cp310-win_amd64.whl", hash = "sha256:c65a3b5330b54103e7d21cac3f6bf3900d46f6d50138d73343d9e5b2900b2353"},
- {file = "regex-2023.10.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90a79bce019c442604662d17bf69df99090e24cdc6ad95b18b6725c2988a490e"},
- {file = "regex-2023.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c7964c2183c3e6cce3f497e3a9f49d182e969f2dc3aeeadfa18945ff7bdd7051"},
- {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ef80829117a8061f974b2fda8ec799717242353bff55f8a29411794d635d964"},
- {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5addc9d0209a9afca5fc070f93b726bf7003bd63a427f65ef797a931782e7edc"},
- {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c148bec483cc4b421562b4bcedb8e28a3b84fcc8f0aa4418e10898f3c2c0eb9b"},
- {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d1f21af4c1539051049796a0f50aa342f9a27cde57318f2fc41ed50b0dbc4ac"},
- {file = "regex-2023.10.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b9ac09853b2a3e0d0082104036579809679e7715671cfbf89d83c1cb2a30f58"},
- {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ebedc192abbc7fd13c5ee800e83a6df252bec691eb2c4bedc9f8b2e2903f5e2a"},
- {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d8a993c0a0ffd5f2d3bda23d0cd75e7086736f8f8268de8a82fbc4bd0ac6791e"},
- {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:be6b7b8d42d3090b6c80793524fa66c57ad7ee3fe9722b258aec6d0672543fd0"},
- {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4023e2efc35a30e66e938de5aef42b520c20e7eda7bb5fb12c35e5d09a4c43f6"},
- {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0d47840dc05e0ba04fe2e26f15126de7c755496d5a8aae4a08bda4dd8d646c54"},
- {file = "regex-2023.10.3-cp311-cp311-win32.whl", hash = "sha256:9145f092b5d1977ec8c0ab46e7b3381b2fd069957b9862a43bd383e5c01d18c2"},
- {file = "regex-2023.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:b6104f9a46bd8743e4f738afef69b153c4b8b592d35ae46db07fc28ae3d5fb7c"},
- {file = "regex-2023.10.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bff507ae210371d4b1fe316d03433ac099f184d570a1a611e541923f78f05037"},
- {file = "regex-2023.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be5e22bbb67924dea15039c3282fa4cc6cdfbe0cbbd1c0515f9223186fc2ec5f"},
- {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a992f702c9be9c72fa46f01ca6e18d131906a7180950958f766c2aa294d4b41"},
- {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7434a61b158be563c1362d9071358f8ab91b8d928728cd2882af060481244c9e"},
- {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2169b2dcabf4e608416f7f9468737583ce5f0a6e8677c4efbf795ce81109d7c"},
- {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9e908ef5889cda4de038892b9accc36d33d72fb3e12c747e2799a0e806ec841"},
- {file = "regex-2023.10.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12bd4bc2c632742c7ce20db48e0d99afdc05e03f0b4c1af90542e05b809a03d9"},
- {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bc72c231f5449d86d6c7d9cc7cd819b6eb30134bb770b8cfdc0765e48ef9c420"},
- {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bce8814b076f0ce5766dc87d5a056b0e9437b8e0cd351b9a6c4e1134a7dfbda9"},
- {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:ba7cd6dc4d585ea544c1412019921570ebd8a597fabf475acc4528210d7c4a6f"},
- {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b0c7d2f698e83f15228ba41c135501cfe7d5740181d5903e250e47f617eb4292"},
- {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5a8f91c64f390ecee09ff793319f30a0f32492e99f5dc1c72bc361f23ccd0a9a"},
- {file = "regex-2023.10.3-cp312-cp312-win32.whl", hash = "sha256:ad08a69728ff3c79866d729b095872afe1e0557251da4abb2c5faff15a91d19a"},
- {file = "regex-2023.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:39cdf8d141d6d44e8d5a12a8569d5a227f645c87df4f92179bd06e2e2705e76b"},
- {file = "regex-2023.10.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4a3ee019a9befe84fa3e917a2dd378807e423d013377a884c1970a3c2792d293"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76066d7ff61ba6bf3cb5efe2428fc82aac91802844c022d849a1f0f53820502d"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe50b61bab1b1ec260fa7cd91106fa9fece57e6beba05630afe27c71259c59b"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fd88f373cb71e6b59b7fa597e47e518282455c2734fd4306a05ca219a1991b0"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ab05a182c7937fb374f7e946f04fb23a0c0699c0450e9fb02ef567412d2fa3"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dac37cf08fcf2094159922edc7a2784cfcc5c70f8354469f79ed085f0328ebdf"},
- {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e54ddd0bb8fb626aa1f9ba7b36629564544954fff9669b15da3610c22b9a0991"},
- {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3367007ad1951fde612bf65b0dffc8fd681a4ab98ac86957d16491400d661302"},
- {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:16f8740eb6dbacc7113e3097b0a36065a02e37b47c936b551805d40340fb9971"},
- {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:f4f2ca6df64cbdd27f27b34f35adb640b5d2d77264228554e68deda54456eb11"},
- {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:39807cbcbe406efca2a233884e169d056c35aa7e9f343d4e78665246a332f597"},
- {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7eece6fbd3eae4a92d7c748ae825cbc1ee41a89bb1c3db05b5578ed3cfcfd7cb"},
- {file = "regex-2023.10.3-cp37-cp37m-win32.whl", hash = "sha256:ce615c92d90df8373d9e13acddd154152645c0dc060871abf6bd43809673d20a"},
- {file = "regex-2023.10.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f649fa32fe734c4abdfd4edbb8381c74abf5f34bc0b3271ce687b23729299ed"},
- {file = "regex-2023.10.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b98b7681a9437262947f41c7fac567c7e1f6eddd94b0483596d320092004533"},
- {file = "regex-2023.10.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:91dc1d531f80c862441d7b66c4505cd6ea9d312f01fb2f4654f40c6fdf5cc37a"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82fcc1f1cc3ff1ab8a57ba619b149b907072e750815c5ba63e7aa2e1163384a4"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7979b834ec7a33aafae34a90aad9f914c41fd6eaa8474e66953f3f6f7cbd4368"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef71561f82a89af6cfcbee47f0fabfdb6e63788a9258e913955d89fdd96902ab"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd829712de97753367153ed84f2de752b86cd1f7a88b55a3a775eb52eafe8a94"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00e871d83a45eee2f8688d7e6849609c2ca2a04a6d48fba3dff4deef35d14f07"},
- {file = "regex-2023.10.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:706e7b739fdd17cb89e1fbf712d9dc21311fc2333f6d435eac2d4ee81985098c"},
- {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cc3f1c053b73f20c7ad88b0d1d23be7e7b3901229ce89f5000a8399746a6e039"},
- {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6f85739e80d13644b981a88f529d79c5bdf646b460ba190bffcaf6d57b2a9863"},
- {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:741ba2f511cc9626b7561a440f87d658aabb3d6b744a86a3c025f866b4d19e7f"},
- {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e77c90ab5997e85901da85131fd36acd0ed2221368199b65f0d11bca44549711"},
- {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:979c24cbefaf2420c4e377ecd1f165ea08cc3d1fbb44bdc51bccbbf7c66a2cb4"},
- {file = "regex-2023.10.3-cp38-cp38-win32.whl", hash = "sha256:58837f9d221744d4c92d2cf7201c6acd19623b50c643b56992cbd2b745485d3d"},
- {file = "regex-2023.10.3-cp38-cp38-win_amd64.whl", hash = "sha256:c55853684fe08d4897c37dfc5faeff70607a5f1806c8be148f1695be4a63414b"},
- {file = "regex-2023.10.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2c54e23836650bdf2c18222c87f6f840d4943944146ca479858404fedeb9f9af"},
- {file = "regex-2023.10.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:69c0771ca5653c7d4b65203cbfc5e66db9375f1078689459fe196fe08b7b4930"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ac965a998e1388e6ff2e9781f499ad1eaa41e962a40d11c7823c9952c77123e"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c0e8fae5b27caa34177bdfa5a960c46ff2f78ee2d45c6db15ae3f64ecadde14"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c56c3d47da04f921b73ff9415fbaa939f684d47293f071aa9cbb13c94afc17d"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ef1e014eed78ab650bef9a6a9cbe50b052c0aebe553fb2881e0453717573f52"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d29338556a59423d9ff7b6eb0cb89ead2b0875e08fe522f3e068b955c3e7b59b"},
- {file = "regex-2023.10.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9c6d0ced3c06d0f183b73d3c5920727268d2201aa0fe6d55c60d68c792ff3588"},
- {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:994645a46c6a740ee8ce8df7911d4aee458d9b1bc5639bc968226763d07f00fa"},
- {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:66e2fe786ef28da2b28e222c89502b2af984858091675044d93cb50e6f46d7af"},
- {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:11175910f62b2b8c055f2b089e0fedd694fe2be3941b3e2633653bc51064c528"},
- {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:06e9abc0e4c9ab4779c74ad99c3fc10d3967d03114449acc2c2762ad4472b8ca"},
- {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fb02e4257376ae25c6dd95a5aec377f9b18c09be6ebdefa7ad209b9137b73d48"},
- {file = "regex-2023.10.3-cp39-cp39-win32.whl", hash = "sha256:3b2c3502603fab52d7619b882c25a6850b766ebd1b18de3df23b2f939360e1bd"},
- {file = "regex-2023.10.3-cp39-cp39-win_amd64.whl", hash = "sha256:adbccd17dcaff65704c856bd29951c58a1bd4b2b0f8ad6b826dbd543fe740988"},
- {file = "regex-2023.10.3.tar.gz", hash = "sha256:3fef4f844d2290ee0ba57addcec17eec9e3df73f10a2748485dfd6a3a188cc0f"},
+ {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"},
+ {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"},
+ {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"},
+ {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"},
+ {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"},
+ {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"},
+ {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"},
+ {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"},
+ {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"},
+ {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"},
+ {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"},
+ {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"},
+ {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"},
+ {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"},
+ {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"},
+ {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"},
+ {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"},
+ {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"},
+ {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"},
+ {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"},
+ {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"},
+ {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"},
+ {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"},
+ {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"},
+ {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"},
+ {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"},
+ {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"},
+ {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"},
+ {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"},
+ {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"},
+ {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"},
+ {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"},
+ {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"},
+ {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"},
+ {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"},
+ {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"},
+ {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"},
+ {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"},
+ {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"},
+ {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"},
+ {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"},
+ {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"},
+ {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"},
+ {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"},
+ {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"},
+ {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"},
+ {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"},
+ {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"},
+ {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"},
+ {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"},
+ {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"},
+ {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"},
+ {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"},
+ {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"},
+ {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"},
+ {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"},
+ {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"},
+ {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"},
+ {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"},
+ {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"},
+ {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"},
+ {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"},
+ {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"},
+ {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"},
+ {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"},
+ {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"},
+ {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"},
+ {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"},
+ {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"},
+ {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"},
+ {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"},
+ {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"},
+ {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"},
]
[[package]]
@@ -3406,6 +3829,24 @@ socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
+name = "requests-oauthlib"
+version = "1.3.1"
+description = "OAuthlib authentication support for Requests."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"},
+ {file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"},
+]
+
+[package.dependencies]
+oauthlib = ">=3.0.0"
+requests = ">=2.0.0"
+
+[package.extras]
+rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
+
+[[package]]
name = "rsa"
version = "4.9"
description = "Pure-Python RSA implementation"
@@ -3438,13 +3879,13 @@ urllib3 = {version = ">=1.26,<3", extras = ["socks"]}
[[package]]
name = "setuptools"
-version = "69.0.2"
+version = "69.0.3"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"},
- {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"},
+ {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"},
+ {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"},
]
[package.extras]
@@ -3509,70 +3950,70 @@ files = [
[[package]]
name = "sqlalchemy"
-version = "2.0.23"
+version = "2.0.25"
description = "Database Abstraction Library"
optional = false
python-versions = ">=3.7"
files = [
- {file = "SQLAlchemy-2.0.23-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:638c2c0b6b4661a4fd264f6fb804eccd392745c5887f9317feb64bb7cb03b3ea"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3b5036aa326dc2df50cba3c958e29b291a80f604b1afa4c8ce73e78e1c9f01d"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:787af80107fb691934a01889ca8f82a44adedbf5ef3d6ad7d0f0b9ac557e0c34"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c14eba45983d2f48f7546bb32b47937ee2cafae353646295f0e99f35b14286ab"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0666031df46b9badba9bed00092a1ffa3aa063a5e68fa244acd9f08070e936d3"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:89a01238fcb9a8af118eaad3ffcc5dedaacbd429dc6fdc43fe430d3a941ff965"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-win32.whl", hash = "sha256:cabafc7837b6cec61c0e1e5c6d14ef250b675fa9c3060ed8a7e38653bd732ff8"},
- {file = "SQLAlchemy-2.0.23-cp310-cp310-win_amd64.whl", hash = "sha256:87a3d6b53c39cd173990de2f5f4b83431d534a74f0e2f88bd16eabb5667e65c6"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d5578e6863eeb998980c212a39106ea139bdc0b3f73291b96e27c929c90cd8e1"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62d9e964870ea5ade4bc870ac4004c456efe75fb50404c03c5fd61f8bc669a72"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c80c38bd2ea35b97cbf7c21aeb129dcbebbf344ee01a7141016ab7b851464f8e"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75eefe09e98043cff2fb8af9796e20747ae870c903dc61d41b0c2e55128f958d"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd45a5b6c68357578263d74daab6ff9439517f87da63442d244f9f23df56138d"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a86cb7063e2c9fb8e774f77fbf8475516d270a3e989da55fa05d08089d77f8c4"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-win32.whl", hash = "sha256:b41f5d65b54cdf4934ecede2f41b9c60c9f785620416e8e6c48349ab18643855"},
- {file = "SQLAlchemy-2.0.23-cp311-cp311-win_amd64.whl", hash = "sha256:9ca922f305d67605668e93991aaf2c12239c78207bca3b891cd51a4515c72e22"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d0f7fb0c7527c41fa6fcae2be537ac137f636a41b4c5a4c58914541e2f436b45"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7c424983ab447dab126c39d3ce3be5bee95700783204a72549c3dceffe0fc8f4"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f508ba8f89e0a5ecdfd3761f82dda2a3d7b678a626967608f4273e0dba8f07ac"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6463aa765cf02b9247e38b35853923edbf2f6fd1963df88706bc1d02410a5577"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e599a51acf3cc4d31d1a0cf248d8f8d863b6386d2b6782c5074427ebb7803bda"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fd54601ef9cc455a0c61e5245f690c8a3ad67ddb03d3b91c361d076def0b4c60"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-win32.whl", hash = "sha256:42d0b0290a8fb0165ea2c2781ae66e95cca6e27a2fbe1016ff8db3112ac1e846"},
- {file = "SQLAlchemy-2.0.23-cp312-cp312-win_amd64.whl", hash = "sha256:227135ef1e48165f37590b8bfc44ed7ff4c074bf04dc8d6f8e7f1c14a94aa6ca"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:14aebfe28b99f24f8a4c1346c48bc3d63705b1f919a24c27471136d2f219f02d"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e983fa42164577d073778d06d2cc5d020322425a509a08119bdcee70ad856bf"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e0dc9031baa46ad0dd5a269cb7a92a73284d1309228be1d5935dac8fb3cae24"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5f94aeb99f43729960638e7468d4688f6efccb837a858b34574e01143cf11f89"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:63bfc3acc970776036f6d1d0e65faa7473be9f3135d37a463c5eba5efcdb24c8"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-win32.whl", hash = "sha256:f48ed89dd11c3c586f45e9eec1e437b355b3b6f6884ea4a4c3111a3358fd0c18"},
- {file = "SQLAlchemy-2.0.23-cp37-cp37m-win_amd64.whl", hash = "sha256:1e018aba8363adb0599e745af245306cb8c46b9ad0a6fc0a86745b6ff7d940fc"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:64ac935a90bc479fee77f9463f298943b0e60005fe5de2aa654d9cdef46c54df"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c4722f3bc3c1c2fcc3702dbe0016ba31148dd6efcd2a2fd33c1b4897c6a19693"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4af79c06825e2836de21439cb2a6ce22b2ca129bad74f359bddd173f39582bf5"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:683ef58ca8eea4747737a1c35c11372ffeb84578d3aab8f3e10b1d13d66f2bc4"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d4041ad05b35f1f4da481f6b811b4af2f29e83af253bf37c3c4582b2c68934ab"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aeb397de65a0a62f14c257f36a726945a7f7bb60253462e8602d9b97b5cbe204"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-win32.whl", hash = "sha256:42ede90148b73fe4ab4a089f3126b2cfae8cfefc955c8174d697bb46210c8306"},
- {file = "SQLAlchemy-2.0.23-cp38-cp38-win_amd64.whl", hash = "sha256:964971b52daab357d2c0875825e36584d58f536e920f2968df8d581054eada4b"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:616fe7bcff0a05098f64b4478b78ec2dfa03225c23734d83d6c169eb41a93e55"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e680527245895aba86afbd5bef6c316831c02aa988d1aad83c47ffe92655e74"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9585b646ffb048c0250acc7dad92536591ffe35dba624bb8fd9b471e25212a35"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4895a63e2c271ffc7a81ea424b94060f7b3b03b4ea0cd58ab5bb676ed02f4221"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cc1d21576f958c42d9aec68eba5c1a7d715e5fc07825a629015fe8e3b0657fb0"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:967c0b71156f793e6662dd839da54f884631755275ed71f1539c95bbada9aaab"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-win32.whl", hash = "sha256:0a8c6aa506893e25a04233bc721c6b6cf844bafd7250535abb56cb6cc1368884"},
- {file = "SQLAlchemy-2.0.23-cp39-cp39-win_amd64.whl", hash = "sha256:f3420d00d2cb42432c1d0e44540ae83185ccbbc67a6054dcc8ab5387add6620b"},
- {file = "SQLAlchemy-2.0.23-py3-none-any.whl", hash = "sha256:31952bbc527d633b9479f5f81e8b9dfada00b91d6baba021a869095f1a97006d"},
- {file = "SQLAlchemy-2.0.23.tar.gz", hash = "sha256:c1bda93cbbe4aa2aa0aa8655c5aeda505cd219ff3e8da91d1d329e143e4aff69"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4344d059265cc8b1b1be351bfb88749294b87a8b2bbe21dfbe066c4199541ebd"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9e2e59cbcc6ba1488404aad43de005d05ca56e069477b33ff74e91b6319735"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84daa0a2055df9ca0f148a64fdde12ac635e30edbca80e87df9b3aaf419e144a"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc8b7dabe8e67c4832891a5d322cec6d44ef02f432b4588390017f5cec186a84"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f5693145220517b5f42393e07a6898acdfe820e136c98663b971906120549da5"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db854730a25db7c956423bb9fb4bdd1216c839a689bf9cc15fada0a7fb2f4570"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-win32.whl", hash = "sha256:14a6f68e8fc96e5e8f5647ef6cda6250c780612a573d99e4d881581432ef1669"},
+ {file = "SQLAlchemy-2.0.25-cp310-cp310-win_amd64.whl", hash = "sha256:87f6e732bccd7dcf1741c00f1ecf33797383128bd1c90144ac8adc02cbb98643"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:342d365988ba88ada8af320d43df4e0b13a694dbd75951f537b2d5e4cb5cd002"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f37c0caf14b9e9b9e8f6dbc81bc56db06acb4363eba5a633167781a48ef036ed"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa9373708763ef46782d10e950b49d0235bfe58facebd76917d3f5cbf5971aed"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d24f571990c05f6b36a396218f251f3e0dda916e0c687ef6fdca5072743208f5"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75432b5b14dc2fff43c50435e248b45c7cdadef73388e5610852b95280ffd0e9"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:884272dcd3ad97f47702965a0e902b540541890f468d24bd1d98bcfe41c3f018"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-win32.whl", hash = "sha256:e607cdd99cbf9bb80391f54446b86e16eea6ad309361942bf88318bcd452363c"},
+ {file = "SQLAlchemy-2.0.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d505815ac340568fd03f719446a589162d55c52f08abd77ba8964fbb7eb5b5f"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0dacf67aee53b16f365c589ce72e766efaabd2b145f9de7c917777b575e3659d"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b801154027107461ee992ff4b5c09aa7cc6ec91ddfe50d02bca344918c3265c6"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59a21853f5daeb50412d459cfb13cb82c089ad4c04ec208cd14dddd99fc23b39"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29049e2c299b5ace92cbed0c1610a7a236f3baf4c6b66eb9547c01179f638ec5"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b64b183d610b424a160b0d4d880995e935208fc043d0302dd29fee32d1ee3f95"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4f7a7d7fcc675d3d85fbf3b3828ecd5990b8d61bd6de3f1b260080b3beccf215"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-win32.whl", hash = "sha256:cf18ff7fc9941b8fc23437cc3e68ed4ebeff3599eec6ef5eebf305f3d2e9a7c2"},
+ {file = "SQLAlchemy-2.0.25-cp312-cp312-win_amd64.whl", hash = "sha256:91f7d9d1c4dd1f4f6e092874c128c11165eafcf7c963128f79e28f8445de82d5"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bb209a73b8307f8fe4fe46f6ad5979649be01607f11af1eb94aa9e8a3aaf77f0"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:798f717ae7c806d67145f6ae94dc7c342d3222d3b9a311a784f371a4333212c7"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fdd402169aa00df3142149940b3bf9ce7dde075928c1886d9a1df63d4b8de62"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0d3cab3076af2e4aa5693f89622bef7fa770c6fec967143e4da7508b3dceb9b9"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:74b080c897563f81062b74e44f5a72fa44c2b373741a9ade701d5f789a10ba23"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-win32.whl", hash = "sha256:87d91043ea0dc65ee583026cb18e1b458d8ec5fc0a93637126b5fc0bc3ea68c4"},
+ {file = "SQLAlchemy-2.0.25-cp37-cp37m-win_amd64.whl", hash = "sha256:75f99202324383d613ddd1f7455ac908dca9c2dd729ec8584c9541dd41822a2c"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:420362338681eec03f53467804541a854617faed7272fe71a1bfdb07336a381e"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c88f0c7dcc5f99bdb34b4fd9b69b93c89f893f454f40219fe923a3a2fd11625"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3be4987e3ee9d9a380b66393b77a4cd6d742480c951a1c56a23c335caca4ce3"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a159111a0f58fb034c93eeba211b4141137ec4b0a6e75789ab7a3ef3c7e7e3"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8b8cb63d3ea63b29074dcd29da4dc6a97ad1349151f2d2949495418fd6e48db9"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:736ea78cd06de6c21ecba7416499e7236a22374561493b456a1f7ffbe3f6cdb4"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-win32.whl", hash = "sha256:10331f129982a19df4284ceac6fe87353ca3ca6b4ca77ff7d697209ae0a5915e"},
+ {file = "SQLAlchemy-2.0.25-cp38-cp38-win_amd64.whl", hash = "sha256:c55731c116806836a5d678a70c84cb13f2cedba920212ba7dcad53260997666d"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:605b6b059f4b57b277f75ace81cc5bc6335efcbcc4ccb9066695e515dbdb3900"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:665f0a3954635b5b777a55111ababf44b4fc12b1f3ba0a435b602b6387ffd7cf"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecf6d4cda1f9f6cb0b45803a01ea7f034e2f1aed9475e883410812d9f9e3cfcf"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c51db269513917394faec5e5c00d6f83829742ba62e2ac4fa5c98d58be91662f"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:790f533fa5c8901a62b6fef5811d48980adeb2f51f1290ade8b5e7ba990ba3de"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1b1180cda6df7af84fe72e4530f192231b1f29a7496951db4ff38dac1687202d"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-win32.whl", hash = "sha256:555651adbb503ac7f4cb35834c5e4ae0819aab2cd24857a123370764dc7d7e24"},
+ {file = "SQLAlchemy-2.0.25-cp39-cp39-win_amd64.whl", hash = "sha256:dc55990143cbd853a5d038c05e79284baedf3e299661389654551bd02a6a68d7"},
+ {file = "SQLAlchemy-2.0.25-py3-none-any.whl", hash = "sha256:a86b4240e67d4753dc3092d9511886795b3c2852abe599cffe108952f7af7ac3"},
+ {file = "SQLAlchemy-2.0.25.tar.gz", hash = "sha256:a2c69a7664fb2d54b8682dd774c3b54f67f84fa123cf84dda2a5f40dcaa04e08"},
]
[package.dependencies]
greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""}
-typing-extensions = ">=4.2.0"
+typing-extensions = ">=4.6.0"
[package.extras]
aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"]
aioodbc = ["aioodbc", "greenlet (!=0.4.17)"]
-aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"]
+aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"]
asyncio = ["greenlet (!=0.4.17)"]
asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"]
mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"]
@@ -3582,7 +4023,7 @@ mssql-pyodbc = ["pyodbc"]
mypy = ["mypy (>=0.910)"]
mysql = ["mysqlclient (>=1.4.0)"]
mysql-connector = ["mysql-connector-python"]
-oracle = ["cx-oracle (>=8)"]
+oracle = ["cx_oracle (>=8)"]
oracle-oracledb = ["oracledb (>=1.0.1)"]
postgresql = ["psycopg2 (>=2.7)"]
postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
@@ -3592,7 +4033,7 @@ postgresql-psycopg2binary = ["psycopg2-binary"]
postgresql-psycopg2cffi = ["psycopg2cffi"]
postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"]
pymysql = ["pymysql"]
-sqlcipher = ["sqlcipher3-binary"]
+sqlcipher = ["sqlcipher3_binary"]
[[package]]
name = "stack-data"
@@ -3615,20 +4056,20 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
[[package]]
name = "starlette"
-version = "0.27.0"
+version = "0.36.3"
description = "The little ASGI library that shines."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"},
- {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"},
+ {file = "starlette-0.36.3-py3-none-any.whl", hash = "sha256:13d429aa93a61dc40bf503e8c801db1f1bca3dc706b10ef2434a36123568f044"},
+ {file = "starlette-0.36.3.tar.gz", hash = "sha256:90a671733cfb35771d8cc605e0b679d23b992f8dcfad48cc60b38cb29aeb7080"},
]
[package.dependencies]
anyio = ">=3.4.0,<5"
[package.extras]
-full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"]
+full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"]
[[package]]
name = "sympy"
@@ -3645,6 +4086,20 @@ files = [
mpmath = ">=0.19"
[[package]]
+name = "tabulate"
+version = "0.9.0"
+description = "Pretty-print tabular data"
+optional = true
+python-versions = ">=3.7"
+files = [
+ {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"},
+ {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"},
+]
+
+[package.extras]
+widechars = ["wcwidth"]
+
+[[package]]
name = "tenacity"
version = "8.2.3"
description = "Retry code until it succeeds"
@@ -3869,13 +4324,13 @@ telegram = ["requests"]
[[package]]
name = "traitlets"
-version = "5.14.0"
+version = "5.14.1"
description = "Traitlets Python configuration system"
optional = true
python-versions = ">=3.8"
files = [
- {file = "traitlets-5.14.0-py3-none-any.whl", hash = "sha256:f14949d23829023013c47df20b4a76ccd1a85effb786dc060f34de7948361b33"},
- {file = "traitlets-5.14.0.tar.gz", hash = "sha256:fcdaa8ac49c04dfa0ed3ee3384ef6dfdb5d6f3741502be247279407679296772"},
+ {file = "traitlets-5.14.1-py3-none-any.whl", hash = "sha256:2e5a030e6eff91737c643231bfcf04a65b0132078dad75e4936700b213652e74"},
+ {file = "traitlets-5.14.1.tar.gz", hash = "sha256:8585105b371a04b8316a43d5ce29c098575c2e477850b62b848b964f1444527e"},
]
[package.extras]
@@ -3884,19 +4339,19 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,
[[package]]
name = "trio"
-version = "0.23.1"
+version = "0.24.0"
description = "A friendly Python library for async concurrency and I/O"
optional = false
python-versions = ">=3.8"
files = [
- {file = "trio-0.23.1-py3-none-any.whl", hash = "sha256:bb4abb3f4af23f96679e7c8cdabb8b234520f2498550d2cf63ebfd95f2ce27fe"},
- {file = "trio-0.23.1.tar.gz", hash = "sha256:16f89f7dcc8f7b9dcdec1fcd863e0c039af6d0f9a22f8dfd56f75d75ec73fd48"},
+ {file = "trio-0.24.0-py3-none-any.whl", hash = "sha256:c3bd3a4e3e3025cd9a2241eae75637c43fe0b9e88b4c97b9161a55b9e54cd72c"},
+ {file = "trio-0.24.0.tar.gz", hash = "sha256:ffa09a74a6bf81b84f8613909fb0beaee84757450183a7a2e0b47b455c0cac5d"},
]
[package.dependencies]
attrs = ">=20.1.0"
cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""}
-exceptiongroup = {version = ">=1.0.0rc9", markers = "python_version < \"3.11\""}
+exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
idna = "*"
outcome = "*"
sniffio = ">=1.3.0"
@@ -3941,17 +4396,28 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.
[[package]]
name = "types-requests"
-version = "2.31.0.10"
+version = "2.31.0.6"
description = "Typing stubs for requests"
optional = false
python-versions = ">=3.7"
files = [
- {file = "types-requests-2.31.0.10.tar.gz", hash = "sha256:dc5852a76f1eaf60eafa81a2e50aefa3d1f015c34cf0cba130930866b1b22a92"},
- {file = "types_requests-2.31.0.10-py3-none-any.whl", hash = "sha256:b32b9a86beffa876c0c3ac99a4cd3b8b51e973fb8e3bd4e0a6bb32c7efad80fc"},
+ {file = "types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0"},
+ {file = "types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9"},
]
[package.dependencies]
-urllib3 = ">=2"
+types-urllib3 = "*"
+
+[[package]]
+name = "types-urllib3"
+version = "1.26.25.14"
+description = "Typing stubs for urllib3"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"},
+ {file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"},
+]
[[package]]
name = "typing-extensions"
@@ -3966,33 +4432,33 @@ files = [
[[package]]
name = "tzdata"
-version = "2023.3"
+version = "2023.4"
description = "Provider of IANA time zone data"
optional = true
python-versions = ">=2"
files = [
- {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"},
- {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"},
+ {file = "tzdata-2023.4-py2.py3-none-any.whl", hash = "sha256:aa3ace4329eeacda5b7beb7ea08ece826c28d761cda36e747cfbf97996d39bf3"},
+ {file = "tzdata-2023.4.tar.gz", hash = "sha256:dd54c94f294765522c77399649b4fefd95522479a664a0cec87f41bebc6148c9"},
]
[[package]]
name = "urllib3"
-version = "2.1.0"
+version = "1.26.18"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
-python-versions = ">=3.8"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
- {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"},
- {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"},
+ {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"},
+ {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"},
]
[package.dependencies]
-pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""}
+PySocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""}
[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
-socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
-zstd = ["zstandard (>=0.18.0)"]
+brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
+secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
+socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "uvicorn"
@@ -4212,13 +4678,13 @@ anyio = ">=3.0.0"
[[package]]
name = "wcwidth"
-version = "0.2.12"
+version = "0.2.13"
description = "Measures the displayed width of unicode strings in a terminal"
optional = true
python-versions = "*"
files = [
- {file = "wcwidth-0.2.12-py2.py3-none-any.whl", hash = "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c"},
- {file = "wcwidth-0.2.12.tar.gz", hash = "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02"},
+ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
+ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
]
[[package]]
@@ -4238,6 +4704,22 @@ python-dotenv = "*"
requests = "*"
[[package]]
+name = "websocket-client"
+version = "1.7.0"
+description = "WebSocket client for Python with low level API options"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "websocket-client-1.7.0.tar.gz", hash = "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6"},
+ {file = "websocket_client-1.7.0-py3-none-any.whl", hash = "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588"},
+]
+
+[package.extras]
+docs = ["Sphinx (>=6.0)", "sphinx-rtd-theme (>=1.1.0)"]
+optional = ["python-socks", "wsaccel"]
+test = ["websockets"]
+
+[[package]]
name = "websockets"
version = "12.0"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
@@ -4319,6 +4801,85 @@ files = [
]
[[package]]
+name = "wrapt"
+version = "1.16.0"
+description = "Module for decorators, wrappers and monkey patching."
+optional = false
+python-versions = ">=3.6"
+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"},
+]
+
+[[package]]
name = "wsproto"
version = "1.2.0"
description = "WebSockets state-machine based protocol implementation"
@@ -4456,4 +5017,4 @@ benchmark = ["agbenchmark"]
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
-content-hash = "81f4f5234aba898f6127f0d55cc1d7a759ec9a6dbd59a12b894a9582070c510d"
+content-hash = "ffc627b17d9f92302ebc7a92088f839cfeb85830f412ca950dd1cbf3c09860e8"
diff --git a/autogpts/forge/pyproject.toml b/autogpts/forge/pyproject.toml
index 175d2e3e1..bd5575304 100644
--- a/autogpts/forge/pyproject.toml
+++ b/autogpts/forge/pyproject.toml
@@ -10,22 +10,22 @@ packages = [{ include = "forge" }]
[tool.poetry.dependencies]
python = "^3.10"
python-dotenv = "^1.0.0"
-openai = "^0.27.8"
+openai = "^1.7.2"
tenacity = "^8.2.2"
sqlalchemy = "^2.0.19"
aiohttp = "^3.8.5"
colorlog = "^6.7.0"
chromadb = "^0.4.10"
-python-multipart = "^0.0.6"
+python-multipart = "^0.0.7"
toml = "^0.10.2"
jinja2 = "^3.1.2"
uvicorn = "^0.23.2"
-litellm = "^0.1.821"
-duckduckgo-search = "^4.0.0"
+litellm = "^1.17.9"
+duckduckgo-search = "^5.0.0"
selenium = "^4.13.0"
bs4 = "^0.0.1"
-# agbenchmark = { path = "../../benchmark", optional = true }
-agbenchmark = {git = "https://github.com/Significant-Gravitas/AutoGPT.git", subdirectory = "benchmark", optional = true}
+agbenchmark = { path = "../../benchmark", optional = true }
+# agbenchmark = {git = "https://github.com/Significant-Gravitas/AutoGPT.git", subdirectory = "benchmark", optional = true}
webdriver-manager = "^4.0.1"
google-cloud-storage = "^2.13.0"
diff --git a/autogpts/forge/tutorials/003_crafting_agent_logic.md b/autogpts/forge/tutorials/003_crafting_agent_logic.md
index 4a5066fa9..9be40ad06 100644
--- a/autogpts/forge/tutorials/003_crafting_agent_logic.md
+++ b/autogpts/forge/tutorials/003_crafting_agent_logic.md
@@ -242,7 +242,7 @@ try:
}
# Get the LLM's response and interpret it
chat_response = await chat_completion_request(**chat_completion_kwargs)
- answer = json.loads(chat_response["choices"][0]["message"]["content"])
+ answer = json.loads(chat_response.choices[0].message.content)
# Log the answer for reference
LOG.info(pprint.pformat(answer))
@@ -264,16 +264,16 @@ Extracting clear messages from LLM outputs can be complex. Our method is simple
Abilities are the gears and levers that enable the agent to interact with tasks at hand. Let's unpack the mechanisms behind these abilities and how you can harness, and even extend, them.
-In the SDK, there's a `abilities` folder containing `registry.py`, `finish.py`, and a `file_system` subfolder. You can also add your own abilities here. `registry.py` is the main file for abilities. It contains the `@ability` decorator and the `AbilityRegister` class. This class actively tracks abilities and outlines their function. The base Agent class includes a default ability register available via `self.abilities`. It looks like this:
+In the Forge folder, there's a `actions` folder containing `registry.py`, `finish.py`, and a `file_system` subfolder. You can also add your own abilities here. `registry.py` is the main file for abilities. It contains the `@action` decorator and the `ActionRegister` class. This class actively tracks abilities and outlines their function. The base Agent class includes a default Action register available via `self.abilities`. It looks like this:
```python
-self.abilities = AbilityRegister(self)
+self.abilities = ActionRegister(self)
```
-The `AbilityRegister` has two key methods. `list_abilities_for_prompt` prepares abilities for prompts. `run_ability` makes the ability work. An ability is a function with the `@ability` decorator. It must have specific parameters, including the agent and `task_id`.
+The `ActionRegister` has two key methods. `list_abilities_for_prompt` prepares abilities for prompts. `run_action` makes the ability work. An ability is a function with the `@action` decorator. It must have specific parameters, including the agent and `task_id`.
```python
-@ability(
+@action(
name="write_file",
description="Write data to a file",
parameters=[
@@ -296,14 +296,14 @@ async def write_file(agent, task_id: str, file_path: str, data: bytes) -> None:
pass
```
-The `@ability` decorator defines the ability's details, like its identity (name), functionality (description), and operational parameters.
+The `@action` decorator defines the ability's details, like its identity (name), functionality (description), and operational parameters.
## Example of a Custom Ability: Webpage Fetcher
```python
import requests
-@ability(
+@action(
name="fetch_webpage",
description="Retrieve the content of a webpage",
parameters=[
@@ -339,7 +339,7 @@ With the ability details, we use it. We call the `run_ability` function:
```python
# Run the ability and get the output
# We don't actually use the output in this example
-output = await self.abilities.run_ability(
+output = await self.abilities.run_action(
task_id, ability["name"], **ability["args"]
)
```
@@ -403,7 +403,7 @@ async def execute_step(self, task_id: str, step_request: StepRequestBody) -> Ste
}
# Make the chat completion request and parse the response
chat_response = await chat_completion_request(**chat_completion_kwargs)
- answer = json.loads(chat_response["choices"][0]["message"]["content"])
+ answer = json.loads(chat_response.choices[0].message.content)
# Log the answer for debugging purposes
LOG.info(pprint.pformat(answer))
@@ -420,7 +420,7 @@ async def execute_step(self, task_id: str, step_request: StepRequestBody) -> Ste
# Run the ability and get the output
# We don't actually use the output in this example
- output = await self.abilities.run_ability(
+ output = await self.abilities.run_action(
task_id, ability["name"], **ability["args"]
)
diff --git a/benchmark/.env.example b/benchmark/.env.example
index 2b08b7906..e4fb03486 100644
--- a/benchmark/.env.example
+++ b/benchmark/.env.example
@@ -1,4 +1,4 @@
AGENT_NAME=mini-agi
-REPORT_LOCATION="reports/mini-agi"
+REPORTS_FOLDER="reports/mini-agi"
OPENAI_API_KEY="sk-" # for LLM eval
BUILD_SKILL_TREE=false # set to true to build the skill tree.
diff --git a/benchmark/agbenchmark/README.md b/benchmark/agbenchmark/README.md
index 7bc493a63..ee35e0d1d 100644
--- a/benchmark/agbenchmark/README.md
+++ b/benchmark/agbenchmark/README.md
@@ -30,7 +30,7 @@
1. Navigate to `auto-gpt-benchmarks/agent/mini-agi`
2. `pip install -r requirements.txt`
3. `cp .env_example .env`, set `PROMPT_USER=false` and add your `OPENAI_API_KEY=`. Sset `MODEL="gpt-3.5-turbo"` if you don't have access to `gpt-4` yet. Also make sure you have Python 3.10^ installed
-4. set `AGENT_NAME=mini-agi` in `.env` file and where you want your `REPORT_LOCATION` to be
+4. set `AGENT_NAME=mini-agi` in `.env` file and where you want your `REPORTS_FOLDER` to be
5. Make sure to follow the commands above, and remove mock flag `agbenchmark`
- To add requirements `poetry add requirement`.
diff --git a/benchmark/agbenchmark/__main__.py b/benchmark/agbenchmark/__main__.py
index 76ca7529a..ca2cc1826 100644
--- a/benchmark/agbenchmark/__main__.py
+++ b/benchmark/agbenchmark/__main__.py
@@ -1,5 +1,4 @@
-import glob
-import json
+import logging
import os
import sys
from datetime import datetime, timezone
@@ -7,205 +6,100 @@ from pathlib import Path
from typing import Any, Optional
import click
-import pytest
-import toml
+from click_default_group import DefaultGroup
from dotenv import load_dotenv
-from helicone.lock import HeliconeLockManager
-from agbenchmark.app import app
-from agbenchmark.reports.ReportManager import SingletonReportManager
-from agbenchmark.utils.data_types import AgentBenchmarkConfig
+from agbenchmark.config import AgentBenchmarkConfig
+from agbenchmark.utils.logging import configure_logging
load_dotenv()
+# try:
+# if os.getenv("HELICONE_API_KEY"):
+# import helicone # noqa
+
+# helicone_enabled = True
+# else:
+# helicone_enabled = False
+# except ImportError:
+# helicone_enabled = False
+
+
+class InvalidInvocationError(ValueError):
+ pass
+
+
+logger = logging.getLogger(__name__)
+
BENCHMARK_START_TIME_DT = datetime.now(timezone.utc)
BENCHMARK_START_TIME = BENCHMARK_START_TIME_DT.strftime("%Y-%m-%dT%H:%M:%S+00:00")
-TEMP_FOLDER_ABS_PATH = Path.cwd() / "agbenchmark_config" / "temp_folder"
-CHALLENGES_ALREADY_BEATEN = (
- Path.cwd() / "agbenchmark_config" / "challenges_already_beaten.json"
-)
-UPDATES_JSON_PATH = Path.cwd() / "agbenchmark_config" / "updates.json"
-if os.environ.get("HELICONE_API_KEY"):
- HeliconeLockManager.write_custom_property(
- "benchmark_start_time", BENCHMARK_START_TIME
- )
+# if helicone_enabled:
+# from helicone.lock import HeliconeLockManager
-with open(
- Path(__file__).resolve().parent / "challenges" / "optional_categories.json"
-) as f:
- OPTIONAL_CATEGORIES = json.load(f)["optional_categories"]
-
-
-def get_unique_categories() -> set[str]:
- """Find all data.json files in the directory relative to this file and its subdirectories,
- read the "category" field from each file, and return a set of unique categories."""
- categories = set()
-
- # Get the directory of this file
- this_dir = os.path.dirname(os.path.abspath(__file__))
-
- glob_path = os.path.join(this_dir, "./challenges/**/data.json")
- # Use it as the base for the glob pattern
- for data_file in glob.glob(glob_path, recursive=True):
- with open(data_file, "r") as f:
- try:
- data = json.load(f)
- categories.update(data.get("category", []))
- except json.JSONDecodeError:
- print(f"Error: {data_file} is not a valid JSON file.")
- continue
- except IOError:
- print(f"IOError: file could not be read: {data_file}")
- continue
-
- return categories
-
-
-def run_benchmark(
- maintain: bool = False,
- improve: bool = False,
- explore: bool = False,
- mock: bool = False,
- no_dep: bool = False,
- nc: bool = False,
- keep_answers: bool = False,
- category: Optional[tuple[str]] = None,
- skip_category: Optional[tuple[str]] = None,
- test: Optional[str] = None,
- cutoff: Optional[int] = None,
- server: bool = False,
-) -> int:
- """Start the benchmark tests. If a category flag is provided, run the categories with that mark."""
- # Check if configuration file exists and is not empty
-
- initialize_updates_file()
- SingletonReportManager()
- agent_benchmark_config_path = str(Path.cwd() / "agbenchmark_config" / "config.json")
- try:
- with open(agent_benchmark_config_path, "r") as f:
- agent_benchmark_config = AgentBenchmarkConfig(**json.load(f))
- agent_benchmark_config.agent_benchmark_config_path = (
- agent_benchmark_config_path
- )
- except json.JSONDecodeError:
- print("Error: benchmark_config.json is not a valid JSON file.")
- return 1
+# HeliconeLockManager.write_custom_property(
+# "benchmark_start_time", BENCHMARK_START_TIME
+# )
- if maintain and improve and explore:
- print(
- "Error: You can't use --maintain, --improve or --explore at the same time. Please choose one."
- )
- return 1
- if test and (category or skip_category or maintain or improve or explore):
- print(
- "Error: If you're running a specific test make sure no other options are selected. Please just pass the --test."
- )
- return 1
+@click.group(cls=DefaultGroup, default_if_no_args=True)
+@click.option("--debug", is_flag=True, help="Enable debug output")
+def cli(
+ debug: bool,
+) -> Any:
+ configure_logging(logging.DEBUG if debug else logging.INFO)
- assert agent_benchmark_config.host, "Error: host needs to be added to the config."
- print("Current configuration:")
- for key, value in vars(agent_benchmark_config).items():
- print(f"{key}: {value}")
+@cli.command(hidden=True)
+def start():
+ raise DeprecationWarning(
+ "`agbenchmark start` is deprecated. Use `agbenchmark run` instead."
+ )
- pytest_args = ["-vs"]
- if keep_answers:
- pytest_args.append("--keep-answers")
- if test:
- print("Running specific test:", test)
- else:
- # Categories that are used in the challenges
- categories = get_unique_categories()
- if category:
- invalid_categories = set(category) - categories
- assert (
- not invalid_categories
- ), f"Invalid categories: {invalid_categories}. Valid categories are: {categories}"
-
- if category:
- categories_to_run = set(category)
- if skip_category:
- categories_to_run = categories_to_run.difference(set(skip_category))
- assert categories_to_run, "Error: You can't skip all categories"
- pytest_args.extend(["-m", " or ".join(categories_to_run), "--category"])
- print("Running tests of category:", categories_to_run)
- elif skip_category:
- categories_to_run = categories - set(skip_category)
- assert categories_to_run, "Error: You can't skip all categories"
- pytest_args.extend(["-m", " or ".join(categories_to_run), "--category"])
- print("Running tests of category:", categories_to_run)
- else:
- print("Running all categories")
-
- if maintain:
- print("Running only regression tests")
- pytest_args.append("--maintain")
- elif improve:
- print("Running only non-regression tests")
- pytest_args.append("--improve")
- elif explore:
- print("Only attempt challenges that have never been beaten")
- pytest_args.append("--explore")
-
- if mock:
- pytest_args.append("--mock")
- os.environ[
- "IS_MOCK"
- ] = "True" # ugly hack to make the mock work when calling from API
-
- if no_dep:
- pytest_args.append("--no_dep")
-
- if nc and cutoff:
- print(
- "Error: You can't use both --nc and --cutoff at the same time. Please choose one."
- )
- return 1
-
- if nc:
- pytest_args.append("--nc")
- if cutoff:
- pytest_args.append("--cutoff")
- print(f"Setting cuttoff override to {cutoff} seconds.")
- current_dir = Path(__file__).resolve().parent
- print(f"Current directory: {current_dir}")
- pytest_args.extend((str(current_dir), "--cache-clear"))
- exit_code = pytest.main(pytest_args)
- SingletonReportManager().clear_instance()
-
-
-@click.group(invoke_without_command=True)
-@click.option("--backend", is_flag=True, help="If it's being run from the cli")
-@click.option("-c", "--category", multiple=True, help="Specific category to run")
+@cli.command(default=True)
+@click.option(
+ "-N", "--attempts", default=1, help="Number of times to run each challenge."
+)
+@click.option(
+ "-c",
+ "--category",
+ multiple=True,
+ help="(+) Select a category to run.",
+)
@click.option(
"-s",
"--skip-category",
multiple=True,
- help="Skips preventing the tests from this category from running",
+ help="(+) Exclude a category from running.",
)
-@click.option("--test", multiple=True, help="Specific test to run")
-@click.option("--maintain", is_flag=True, help="Runs only regression tests")
-@click.option("--improve", is_flag=True, help="Run only non-regression tests")
+@click.option("--test", multiple=True, help="(+) Select a test to run.")
+@click.option("--maintain", is_flag=True, help="Run only regression tests.")
+@click.option("--improve", is_flag=True, help="Run only non-regression tests.")
@click.option(
"--explore",
is_flag=True,
- help="Only attempt challenges that have never been beaten",
+ help="Run only challenges that have never been beaten.",
)
-@click.option("--mock", is_flag=True, help="Run with mock")
@click.option(
- "--no_dep",
+ "--no-dep",
is_flag=True,
- help="Run without dependencies",
+ help="Run all (selected) challenges, regardless of dependency success/failure.",
)
-@click.option("--nc", is_flag=True, help="Run without cutoff")
+@click.option("--cutoff", type=int, help="Override the challenge time limit (seconds).")
+@click.option("--nc", is_flag=True, help="Disable the challenge time limit.")
+@click.option("--mock", is_flag=True, help="Run with mock")
@click.option("--keep-answers", is_flag=True, help="Keep answers")
-@click.option("--cutoff", help="Set or override tests cutoff (seconds)")
-@click.argument("value", type=str, required=False)
-def cli(
+@click.option(
+ "--backend",
+ is_flag=True,
+ help="Write log output to a file instead of the terminal.",
+)
+# @click.argument(
+# "agent_path", type=click.Path(exists=True, file_okay=False), required=False
+# )
+def run(
maintain: bool,
improve: bool,
explore: bool,
@@ -213,18 +107,38 @@ def cli(
no_dep: bool,
nc: bool,
keep_answers: bool,
- category: Optional[list[str]] = None,
- skip_category: Optional[list[str]] = None,
- test: Optional[str] = None,
+ test: tuple[str],
+ category: tuple[str],
+ skip_category: tuple[str],
+ attempts: int,
cutoff: Optional[int] = None,
backend: Optional[bool] = False,
- value: Optional[str] = None,
-) -> Any:
- # Redirect stdout if backend is True
- if value == "start":
- raise ("`agbenchmark start` is removed. Run `agbenchmark` instead.")
- if value == "serve":
- return serve()
+ # agent_path: Optional[Path] = None,
+) -> None:
+ """
+ Run the benchmark on the agent in the current directory.
+
+ Options marked with (+) can be specified multiple times, to select multiple items.
+ """
+ from agbenchmark.main import run_benchmark, validate_args
+
+ agbenchmark_config = AgentBenchmarkConfig.load()
+ logger.debug(f"agbenchmark_config: {agbenchmark_config.agbenchmark_config_dir}")
+ try:
+ validate_args(
+ maintain=maintain,
+ improve=improve,
+ explore=explore,
+ tests=test,
+ categories=category,
+ skip_categories=skip_category,
+ no_cutoff=nc,
+ cutoff=cutoff,
+ )
+ except InvalidInvocationError as e:
+ logger.error("Error: " + "\n".join(e.args))
+ sys.exit(1)
+
original_stdout = sys.stdout # Save the original standard output
exit_code = None
@@ -232,16 +146,18 @@ def cli(
with open("backend/backend_stdout.txt", "w") as f:
sys.stdout = f
exit_code = run_benchmark(
+ config=agbenchmark_config,
maintain=maintain,
improve=improve,
explore=explore,
mock=mock,
no_dep=no_dep,
- nc=nc,
+ no_cutoff=nc,
keep_answers=keep_answers,
- category=category,
- skip_category=skip_category,
- test=test,
+ tests=test,
+ categories=category,
+ skip_categories=skip_category,
+ attempts_per_challenge=attempts,
cutoff=cutoff,
)
@@ -249,16 +165,18 @@ def cli(
else:
exit_code = run_benchmark(
+ config=agbenchmark_config,
maintain=maintain,
improve=improve,
explore=explore,
mock=mock,
no_dep=no_dep,
- nc=nc,
+ no_cutoff=nc,
keep_answers=keep_answers,
- category=category,
- skip_category=skip_category,
- test=test,
+ tests=test,
+ categories=category,
+ skip_categories=skip_category,
+ attempts_per_challenge=attempts,
cutoff=cutoff,
)
@@ -266,33 +184,164 @@ def cli(
@cli.command()
-def version():
- """Print the version of the benchmark tool."""
- current_directory = Path(__file__).resolve().parent
- version = toml.load(current_directory / ".." / "pyproject.toml")["tool"]["poetry"][
- "version"
- ]
- print(f"Benchmark Tool Version {version}")
+@click.option("--port", type=int, help="Port to run the API on.")
+def serve(port: Optional[int] = None):
+ """Serve the benchmark frontend and API on port 8080."""
+ import uvicorn
+ from agbenchmark.app import setup_fastapi_app
-def serve():
- import uvicorn
+ config = AgentBenchmarkConfig.load()
+ app = setup_fastapi_app(config)
# Run the FastAPI application using uvicorn
- uvicorn.run(app, host="0.0.0.0", port=8080)
+ port = port or int(os.getenv("PORT", 8080))
+ uvicorn.run(app, host="0.0.0.0", port=port)
+
+
+@cli.command()
+def config():
+ """Displays info regarding the present AGBenchmark config."""
+ from .utils.utils import pretty_print_model
+
+ try:
+ config = AgentBenchmarkConfig.load()
+ except FileNotFoundError as e:
+ click.echo(e, err=True)
+ return 1
+
+ pretty_print_model(config, include_header=False)
+
+
+@cli.group()
+def challenge():
+ logging.getLogger().setLevel(logging.WARNING)
+
+
+@challenge.command("list")
+@click.option(
+ "--all", "include_unavailable", is_flag=True, help="Include unavailable challenges."
+)
+@click.option(
+ "--names", "only_names", is_flag=True, help="List only the challenge names."
+)
+@click.option("--json", "output_json", is_flag=True)
+def list_challenges(include_unavailable: bool, only_names: bool, output_json: bool):
+ """Lists [available|all] challenges."""
+ import json
+
+ from tabulate import tabulate
+
+ from .challenges.builtin import load_builtin_challenges
+ from .challenges.webarena import load_webarena_challenges
+ from .utils.data_types import Category, DifficultyLevel
+ from .utils.utils import sorted_by_enum_index
+
+ DIFFICULTY_COLORS = {
+ difficulty: color
+ for difficulty, color in zip(
+ DifficultyLevel,
+ ["black", "blue", "cyan", "green", "yellow", "red", "magenta", "white"],
+ )
+ }
+ CATEGORY_COLORS = {
+ category: f"bright_{color}"
+ for category, color in zip(
+ Category,
+ ["blue", "cyan", "green", "yellow", "magenta", "red", "white", "black"],
+ )
+ }
+
+ # Load challenges
+ challenges = filter(
+ lambda c: c.info.available or include_unavailable,
+ [
+ *load_builtin_challenges(),
+ *load_webarena_challenges(skip_unavailable=False),
+ ],
+ )
+ challenges = sorted_by_enum_index(
+ challenges, DifficultyLevel, key=lambda c: c.info.difficulty
+ )
+
+ if only_names:
+ if output_json:
+ click.echo(json.dumps([c.info.name for c in challenges]))
+ return
+
+ for c in challenges:
+ click.echo(
+ click.style(c.info.name, fg=None if c.info.available else "black")
+ )
+ return
+ if output_json:
+ click.echo(json.dumps([json.loads(c.info.json()) for c in challenges]))
+ return
+
+ headers = tuple(
+ click.style(h, bold=True) for h in ("Name", "Difficulty", "Categories")
+ )
+ table = [
+ tuple(
+ v if challenge.info.available else click.style(v, fg="black")
+ for v in (
+ challenge.info.name,
+ (
+ click.style(
+ challenge.info.difficulty.value,
+ fg=DIFFICULTY_COLORS[challenge.info.difficulty],
+ )
+ if challenge.info.difficulty
+ else click.style("-", fg="black")
+ ),
+ " ".join(
+ click.style(cat.value, fg=CATEGORY_COLORS[cat])
+ for cat in sorted_by_enum_index(challenge.info.category, Category)
+ ),
+ )
+ )
+ for challenge in challenges
+ ]
+ click.echo(tabulate(table, headers=headers))
-def initialize_updates_file():
- if os.path.exists(UPDATES_JSON_PATH):
- # If the file already exists, overwrite it with an empty list
- with open(UPDATES_JSON_PATH, "w") as file:
- json.dump([], file, indent=2)
- print("Initialized updates.json by overwriting with an empty array")
+
+@challenge.command()
+@click.option("--json", is_flag=True)
+@click.argument("name")
+def info(name: str, json: bool):
+ from itertools import chain
+
+ from .challenges.builtin import load_builtin_challenges
+ from .challenges.webarena import load_webarena_challenges
+ from .utils.utils import pretty_print_model
+
+ for challenge in chain(
+ load_builtin_challenges(),
+ load_webarena_challenges(skip_unavailable=False),
+ ):
+ if challenge.info.name != name:
+ continue
+
+ if json:
+ click.echo(challenge.info.json())
+ break
+
+ pretty_print_model(challenge.info)
+ break
else:
- # If the file doesn't exist, create it and write an empty list
- with open(UPDATES_JSON_PATH, "w") as file:
- json.dump([], file, indent=2)
- print("Created updates.json and initialized it with an empty array")
+ click.echo(click.style(f"Unknown challenge '{name}'", fg="red"), err=True)
+
+
+@cli.command()
+def version():
+ """Print version info for the AGBenchmark application."""
+ import toml
+
+ package_root = Path(__file__).resolve().parent.parent
+ pyproject = toml.load(package_root / "pyproject.toml")
+ version = pyproject["tool"]["poetry"]["version"]
+ click.echo(f"AGBenchmark version {version}")
if __name__ == "__main__":
diff --git a/benchmark/agbenchmark/agent_api_interface.py b/benchmark/agbenchmark/agent_api_interface.py
index 18ff4520e..0bd00a148 100644
--- a/benchmark/agbenchmark/agent_api_interface.py
+++ b/benchmark/agbenchmark/agent_api_interface.py
@@ -1,33 +1,34 @@
-import json
import logging
-import os
-import pathlib
import time
-from typing import Any, Dict, Optional
+from pathlib import Path
+from typing import AsyncIterator, Optional
-from agbenchmark.__main__ import TEMP_FOLDER_ABS_PATH, UPDATES_JSON_PATH
-from agbenchmark.agent_interface import get_list_of_file_paths
-from agbenchmark.agent_protocol_client import (
+from agent_protocol_client import (
AgentApi,
ApiClient,
Configuration,
+ Step,
TaskRequestBody,
)
-from agbenchmark.agent_protocol_client.models.step import Step
-from agbenchmark.utils.data_types import ChallengeData
-LOG = logging.getLogger(__name__)
+from agbenchmark.agent_interface import get_list_of_file_paths
+from agbenchmark.config import AgentBenchmarkConfig
+logger = logging.getLogger(__name__)
-async def run_api_agent(
- task: ChallengeData, config: Dict[str, Any], artifacts_location: str, timeout: int
-) -> None:
- host_value = None
- configuration = Configuration(host=config["AgentBenchmarkConfig"].host + "/ap/v1")
+async def run_api_agent(
+ task: str,
+ config: AgentBenchmarkConfig,
+ timeout: int,
+ artifacts_location: Optional[Path] = None,
+ *,
+ mock: bool = False,
+) -> AsyncIterator[Step]:
+ configuration = Configuration(host=config.host)
async with ApiClient(configuration) as api_client:
api_instance = AgentApi(api_client)
- task_request_body = TaskRequestBody(input=task.task)
+ task_request_body = TaskRequestBody(input=task)
start_time = time.time()
response = await api_instance.create_agent_task(
@@ -35,54 +36,58 @@ async def run_api_agent(
)
task_id = response.task_id
- await upload_artifacts(
- api_instance, artifacts_location, task_id, "artifacts_in"
- )
-
- i = 1
- steps_remaining = True
- while steps_remaining:
- # Read the existing JSON data from the file
+ if artifacts_location:
+ logger.debug("Uploading task input artifacts to agent...")
+ await upload_artifacts(
+ api_instance, artifacts_location, task_id, "artifacts_in"
+ )
+ logger.debug("Running agent until finished or timeout...")
+ while True:
step = await api_instance.execute_agent_task_step(task_id=task_id)
- await append_updates_file(step)
-
- print(f"[{task.name}] - step {step.name} ({i}. request)")
- i += 1
+ yield step
if time.time() - start_time > timeout:
raise TimeoutError("Time limit exceeded")
+ if step and mock:
+ step.is_last = True
if not step or step.is_last:
- steps_remaining = False
- # if we're calling a mock agent, we "cheat" and give the correct artifacts to pass the tests
- if os.getenv("IS_MOCK"):
- await upload_artifacts(
- api_instance, artifacts_location, task_id, "artifacts_out"
+ break
+
+ if artifacts_location:
+ # In "mock" mode, we cheat by giving the correct artifacts to pass the test
+ if mock:
+ logger.debug("Uploading mock artifacts to agent...")
+ await upload_artifacts(
+ api_instance, artifacts_location, task_id, "artifacts_out"
+ )
+
+ logger.debug("Downloading agent artifacts...")
+ await download_agent_artifacts_into_folder(
+ api_instance, task_id, config.temp_folder
)
- await copy_agent_artifacts_into_temp_folder(api_instance, task_id)
-
-async def copy_agent_artifacts_into_temp_folder(api_instance, task_id):
+async def download_agent_artifacts_into_folder(
+ api_instance: AgentApi, task_id: str, folder: Path
+):
artifacts = await api_instance.list_agent_task_artifacts(task_id=task_id)
+
for artifact in artifacts.artifacts:
# current absolute path of the directory of the file
- directory_location = pathlib.Path(TEMP_FOLDER_ABS_PATH)
if artifact.relative_path:
- path = (
+ path: str = (
artifact.relative_path
if not artifact.relative_path.startswith("/")
else artifact.relative_path[1:]
)
- directory_location = pathlib.Path(
- os.path.dirname(directory_location / path)
- )
- LOG.info(f"Creating directory {directory_location}")
+ folder = (folder / path).parent
- directory_location.mkdir(parents=True, exist_ok=True)
+ if not folder.exists():
+ folder.mkdir(parents=True)
- file_path = directory_location / artifact.file_name
- LOG.info(f"Writing file {file_path}")
+ file_path = folder / artifact.file_name
+ logger.debug(f"Downloading agent artifact {artifact.file_name} to {folder}")
with open(file_path, "wb") as f:
content = await api_instance.download_agent_task_artifact(
task_id=task_id, artifact_id=artifact.artifact_id
@@ -91,35 +96,16 @@ async def copy_agent_artifacts_into_temp_folder(api_instance, task_id):
f.write(content)
-async def append_updates_file(step: Step):
- with open(UPDATES_JSON_PATH, "r") as file:
- existing_data = json.load(file)
- # Append the new update to the existing array
- new_update = create_update_json(step)
-
- existing_data.append(new_update)
- # Write the updated array back to the file
- with open(UPDATES_JSON_PATH, "w") as file:
- file.write(json.dumps(existing_data, indent=2))
-
-
async def upload_artifacts(
- api_instance: ApiClient, artifacts_location: str, task_id: str, type: str
+ api_instance: AgentApi, artifacts_location: Path, task_id: str, type: str
) -> None:
for file_path in get_list_of_file_paths(artifacts_location, type):
relative_path: Optional[str] = "/".join(
- file_path.split(f"{type}/", 1)[-1].split("/")[:-1]
+ str(file_path).split(f"{type}/", 1)[-1].split("/")[:-1]
)
if not relative_path:
relative_path = None
await api_instance.upload_agent_task_artifacts(
- task_id=task_id, file=file_path, relative_path=relative_path
+ task_id=task_id, file=str(file_path), relative_path=relative_path
)
-
-
-def create_update_json(step: Step):
- now = int(time.time())
- content = {"content": step.to_dict(), "timestamp": now}
-
- return content
diff --git a/benchmark/agbenchmark/agent_interface.py b/benchmark/agbenchmark/agent_interface.py
index 269e8f8ff..52bd2093c 100644
--- a/benchmark/agbenchmark/agent_interface.py
+++ b/benchmark/agbenchmark/agent_interface.py
@@ -1,45 +1,27 @@
import os
import shutil
-import sys
-from typing import List
+from pathlib import Path
from dotenv import load_dotenv
-from agbenchmark.execute_sub_process import execute_subprocess
-
load_dotenv()
-helicone_graphql_logs = os.getenv("HELICONE_GRAPHQL_LOGS")
-HELICONE_GRAPHQL_LOGS = (
- helicone_graphql_logs.lower() == "true" if helicone_graphql_logs else False
-)
-
-
-def run_agent(task: str, timeout: int) -> None:
- print(f"Running agbenchmark/benchmarks.py with timeout {timeout}")
-
- command = [sys.executable, "-m", "agbenchmark_config.benchmarks", str(task)]
-
- execute_subprocess(command, timeout)
+HELICONE_GRAPHQL_LOGS = os.getenv("HELICONE_GRAPHQL_LOGS", "").lower() == "true"
def get_list_of_file_paths(
- challenge_dir_path: str, artifact_folder_name: str
-) -> List[str]:
- # this file is at agbenchmark\agent_interface.py
- source_dir = os.path.join(
- challenge_dir_path,
- artifact_folder_name,
- )
- if not os.path.exists(source_dir):
+ challenge_dir_path: str | Path, artifact_folder_name: str
+) -> list[Path]:
+ source_dir = Path(challenge_dir_path) / artifact_folder_name
+ if not source_dir.exists():
return []
- return [os.path.join(source_dir, file_name) for file_name in os.listdir(source_dir)]
+ return list(source_dir.iterdir())
-def copy_artifacts_into_temp_folder(
- workspace: str | dict[str, str], artifact_folder_name: str, challenge_dir_path: str
+def copy_challenge_artifacts_into_workspace(
+ challenge_dir_path: str | Path, artifact_folder_name: str, workspace: str | Path
) -> None:
file_paths = get_list_of_file_paths(challenge_dir_path, artifact_folder_name)
for file_path in file_paths:
- if os.path.isfile(file_path):
+ if file_path.is_file():
shutil.copy(file_path, workspace)
diff --git a/benchmark/agbenchmark/agent_protocol_client/__init__.py b/benchmark/agbenchmark/agent_protocol_client/__init__.py
deleted file mode 100644
index c393f2f83..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/__init__.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# coding: utf-8
-
-# flake8: noqa
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-__version__ = "1.0.0"
-
-# import apis into sdk package
-from agbenchmark.agent_protocol_client.api.agent_api import AgentApi
-from agbenchmark.agent_protocol_client.api_client import ApiClient
-
-# import ApiClient
-from agbenchmark.agent_protocol_client.api_response import ApiResponse
-from agbenchmark.agent_protocol_client.configuration import Configuration
-from agbenchmark.agent_protocol_client.exceptions import (
- ApiAttributeError,
- ApiException,
- ApiKeyError,
- ApiTypeError,
- ApiValueError,
- OpenApiException,
-)
-
-# import models into sdk package
-from agbenchmark.agent_protocol_client.models.artifact import Artifact
-from agbenchmark.agent_protocol_client.models.step import Step
-from agbenchmark.agent_protocol_client.models.step_all_of import StepAllOf
-from agbenchmark.agent_protocol_client.models.step_request_body import StepRequestBody
-from agbenchmark.agent_protocol_client.models.task import Task
-from agbenchmark.agent_protocol_client.models.task_all_of import TaskAllOf
-from agbenchmark.agent_protocol_client.models.task_request_body import TaskRequestBody
diff --git a/benchmark/agbenchmark/agent_protocol_client/api/__init__.py b/benchmark/agbenchmark/agent_protocol_client/api/__init__.py
deleted file mode 100644
index 3b2e21069..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/api/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# flake8: noqa
-
-# import apis into api package
-from agbenchmark.agent_protocol_client.api.agent_api import AgentApi
diff --git a/benchmark/agbenchmark/agent_protocol_client/api/agent_api.py b/benchmark/agbenchmark/agent_protocol_client/api/agent_api.py
deleted file mode 100644
index 2597c880f..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/api/agent_api.py
+++ /dev/null
@@ -1,1647 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-import re # noqa: F401
-from typing import Any, Awaitable, List, Optional, Union, overload
-
-from pydantic import Field, StrictBytes, StrictStr, validate_arguments
-from typing_extensions import Annotated
-
-from agbenchmark.agent_protocol_client.api_client import ApiClient
-from agbenchmark.agent_protocol_client.api_response import ApiResponse
-from agbenchmark.agent_protocol_client.exceptions import ( # noqa: F401
- ApiTypeError,
- ApiValueError,
-)
-from agbenchmark.agent_protocol_client.models.artifact import Artifact
-from agbenchmark.agent_protocol_client.models.step import Step
-from agbenchmark.agent_protocol_client.models.step_request_body import StepRequestBody
-from agbenchmark.agent_protocol_client.models.task import Task
-from agbenchmark.agent_protocol_client.models.task_request_body import TaskRequestBody
-
-
-class AgentApi(object):
- """NOTE: This class is auto generated by OpenAPI Generator
- Ref: https://openapi-generator.tech
-
- Do not edit the class manually.
- """
-
- def __init__(self, api_client=None):
- if api_client is None:
- api_client = ApiClient.get_default()
- self.api_client = api_client
-
- @overload
- async def create_agent_task(
- self, task_request_body: Optional[TaskRequestBody] = None, **kwargs
- ) -> Task: # noqa: E501
- ...
-
- @overload
- def create_agent_task(
- self,
- task_request_body: Optional[TaskRequestBody] = None,
- async_req: Optional[bool] = True,
- **kwargs,
- ) -> Task: # noqa: E501
- ...
-
- @validate_arguments
- def create_agent_task(
- self,
- task_request_body: Optional[TaskRequestBody] = None,
- async_req: Optional[bool] = None,
- **kwargs,
- ) -> Union[Task, Awaitable[Task]]: # noqa: E501
- """Creates a task for the agent. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.create_agent_task(task_request_body, async_req=True)
- >>> result = thread.get()
-
- :param task_request_body:
- :type task_request_body: TaskRequestBody
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: Task
- """
- kwargs["_return_http_data_only"] = True
- if "_preload_content" in kwargs:
- raise ValueError(
- "Error! Please call the create_agent_task_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"
- )
- if async_req is not None:
- kwargs["async_req"] = async_req
- return self.create_agent_task_with_http_info(
- task_request_body, **kwargs
- ) # noqa: E501
-
- @validate_arguments
- def create_agent_task_with_http_info(
- self, task_request_body: Optional[TaskRequestBody] = None, **kwargs
- ) -> ApiResponse: # noqa: E501
- """Creates a task for the agent. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.create_agent_task_with_http_info(task_request_body, async_req=True)
- >>> result = thread.get()
-
- :param task_request_body:
- :type task_request_body: TaskRequestBody
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _preload_content: if False, the ApiResponse.data will
- be set to none and raw_data will store the
- HTTP response body without reading/decoding.
- Default is True.
- :type _preload_content: bool, optional
- :param _return_http_data_only: response data instead of ApiResponse
- object with status code, headers, etc
- :type _return_http_data_only: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :param _request_auth: set to override the auth_settings for an a single
- request; this effectively ignores the authentication
- in the spec for a single request.
- :type _request_auth: dict, optional
- :type _content_type: string, optional: force content-type for the request
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: tuple(Task, status_code(int), headers(HTTPHeaderDict))
- """
-
- _params = locals()
-
- _all_params = ["task_request_body"]
- _all_params.extend(
- [
- "async_req",
- "_return_http_data_only",
- "_preload_content",
- "_request_timeout",
- "_request_auth",
- "_content_type",
- "_headers",
- ]
- )
-
- # validate the arguments
- for _key, _val in _params["kwargs"].items():
- if _key not in _all_params:
- raise ApiTypeError(
- "Got an unexpected keyword argument '%s'"
- " to method create_agent_task" % _key
- )
- _params[_key] = _val
- del _params["kwargs"]
-
- _collection_formats = {}
-
- # process the path parameters
- _path_params = {}
-
- # process the query parameters
- _query_params = []
- # process the header parameters
- _header_params = dict(_params.get("_headers", {}))
- # process the form parameters
- _form_params = []
- _files = {}
- # process the body parameter
- _body_params = None
- if _params["task_request_body"] is not None:
- _body_params = _params["task_request_body"]
-
- # set the HTTP header `Accept`
- _header_params["Accept"] = self.api_client.select_header_accept(
- ["application/json"]
- ) # noqa: E501
-
- # set the HTTP header `Content-Type`
- _content_types_list = _params.get(
- "_content_type",
- self.api_client.select_header_content_type(["application/json"]),
- )
- if _content_types_list:
- _header_params["Content-Type"] = _content_types_list
-
- # authentication setting
- _auth_settings = [] # noqa: E501
-
- _response_types_map = {
- "200": "Task",
- }
-
- return self.api_client.call_api(
- "/agent/tasks",
- "POST",
- _path_params,
- _query_params,
- _header_params,
- body=_body_params,
- post_params=_form_params,
- files=_files,
- response_types_map=_response_types_map,
- auth_settings=_auth_settings,
- async_req=_params.get("async_req"),
- _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501
- _preload_content=_params.get("_preload_content", True),
- _request_timeout=_params.get("_request_timeout"),
- collection_formats=_collection_formats,
- _request_auth=_params.get("_request_auth"),
- )
-
- @overload
- async def download_agent_task_artifact(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- artifact_id: Annotated[StrictStr, Field(..., description="ID of the artifact")],
- **kwargs,
- ) -> bytearray: # noqa: E501
- ...
-
- @overload
- def download_agent_task_artifact(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- artifact_id: Annotated[StrictStr, Field(..., description="ID of the artifact")],
- async_req: Optional[bool] = True,
- **kwargs,
- ) -> bytearray: # noqa: E501
- ...
-
- @validate_arguments
- def download_agent_task_artifact(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- artifact_id: Annotated[StrictStr, Field(..., description="ID of the artifact")],
- async_req: Optional[bool] = None,
- **kwargs,
- ) -> Union[bytearray, Awaitable[bytearray]]: # noqa: E501
- """Download a specified artifact. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.download_agent_task_artifact(task_id, artifact_id, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param artifact_id: ID of the artifact (required)
- :type artifact_id: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: bytearray
- """
- kwargs["_return_http_data_only"] = True
- if "_preload_content" in kwargs:
- raise ValueError(
- "Error! Please call the download_agent_task_artifact_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"
- )
- if async_req is not None:
- kwargs["async_req"] = async_req
- return self.download_agent_task_artifact_with_http_info(
- task_id, artifact_id, **kwargs
- ) # noqa: E501
-
- @validate_arguments
- def download_agent_task_artifact_with_http_info(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- artifact_id: Annotated[StrictStr, Field(..., description="ID of the artifact")],
- **kwargs,
- ) -> ApiResponse: # noqa: E501
- """Download a specified artifact. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.download_agent_task_artifact_with_http_info(task_id, artifact_id, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param artifact_id: ID of the artifact (required)
- :type artifact_id: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _preload_content: if False, the ApiResponse.data will
- be set to none and raw_data will store the
- HTTP response body without reading/decoding.
- Default is True.
- :type _preload_content: bool, optional
- :param _return_http_data_only: response data instead of ApiResponse
- object with status code, headers, etc
- :type _return_http_data_only: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :param _request_auth: set to override the auth_settings for an a single
- request; this effectively ignores the authentication
- in the spec for a single request.
- :type _request_auth: dict, optional
- :type _content_type: string, optional: force content-type for the request
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: tuple(bytearray, status_code(int), headers(HTTPHeaderDict))
- """
-
- _params = locals()
-
- _all_params = ["task_id", "artifact_id"]
- _all_params.extend(
- [
- "async_req",
- "_return_http_data_only",
- "_preload_content",
- "_request_timeout",
- "_request_auth",
- "_content_type",
- "_headers",
- ]
- )
-
- # validate the arguments
- for _key, _val in _params["kwargs"].items():
- if _key not in _all_params:
- raise ApiTypeError(
- "Got an unexpected keyword argument '%s'"
- " to method download_agent_task_artifact" % _key
- )
- _params[_key] = _val
- del _params["kwargs"]
-
- _collection_formats = {}
-
- # process the path parameters
- _path_params = {}
- if _params["task_id"]:
- _path_params["task_id"] = _params["task_id"]
-
- if _params["artifact_id"]:
- _path_params["artifact_id"] = _params["artifact_id"]
-
- # process the query parameters
- _query_params = []
- # process the header parameters
- _header_params = dict(_params.get("_headers", {}))
- # process the form parameters
- _form_params = []
- _files = {}
- # process the body parameter
- _body_params = None
- # set the HTTP header `Accept`
- _header_params["Accept"] = self.api_client.select_header_accept(
- ["application/octet-stream"]
- ) # noqa: E501
-
- # authentication setting
- _auth_settings = [] # noqa: E501
-
- _response_types_map = {
- "200": "bytearray",
- }
-
- return self.api_client.call_api(
- "/agent/tasks/{task_id}/artifacts/{artifact_id}",
- "GET",
- _path_params,
- _query_params,
- _header_params,
- body=_body_params,
- post_params=_form_params,
- files=_files,
- response_types_map=_response_types_map,
- auth_settings=_auth_settings,
- async_req=_params.get("async_req"),
- _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501
- _preload_content=_params.get("_preload_content", True),
- _request_timeout=_params.get("_request_timeout"),
- collection_formats=_collection_formats,
- _request_auth=_params.get("_request_auth"),
- )
-
- @overload
- async def execute_agent_task_step(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- step_request_body: Optional[StepRequestBody] = None,
- **kwargs,
- ) -> Step: # noqa: E501
- ...
-
- @overload
- def execute_agent_task_step(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- step_request_body: Optional[StepRequestBody] = None,
- async_req: Optional[bool] = True,
- **kwargs,
- ) -> Step: # noqa: E501
- ...
-
- @validate_arguments
- def execute_agent_task_step(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- step_request_body: Optional[StepRequestBody] = None,
- async_req: Optional[bool] = None,
- **kwargs,
- ) -> Union[Step, Awaitable[Step]]: # noqa: E501
- """Execute a step in the specified agent task. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.execute_agent_task_step(task_id, step_request_body, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param step_request_body:
- :type step_request_body: StepRequestBody
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: Step
- """
- kwargs["_return_http_data_only"] = True
- if "_preload_content" in kwargs:
- raise ValueError(
- "Error! Please call the execute_agent_task_step_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"
- )
- if async_req is not None:
- kwargs["async_req"] = async_req
- return self.execute_agent_task_step_with_http_info(
- task_id, step_request_body, **kwargs
- ) # noqa: E501
-
- @validate_arguments
- def execute_agent_task_step_with_http_info(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- step_request_body: Optional[StepRequestBody] = None,
- **kwargs,
- ) -> ApiResponse: # noqa: E501
- """Execute a step in the specified agent task. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.execute_agent_task_step_with_http_info(task_id, step_request_body, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param step_request_body:
- :type step_request_body: StepRequestBody
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _preload_content: if False, the ApiResponse.data will
- be set to none and raw_data will store the
- HTTP response body without reading/decoding.
- Default is True.
- :type _preload_content: bool, optional
- :param _return_http_data_only: response data instead of ApiResponse
- object with status code, headers, etc
- :type _return_http_data_only: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :param _request_auth: set to override the auth_settings for an a single
- request; this effectively ignores the authentication
- in the spec for a single request.
- :type _request_auth: dict, optional
- :type _content_type: string, optional: force content-type for the request
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: tuple(Step, status_code(int), headers(HTTPHeaderDict))
- """
-
- _params = locals()
-
- _all_params = ["task_id", "step_request_body"]
- _all_params.extend(
- [
- "async_req",
- "_return_http_data_only",
- "_preload_content",
- "_request_timeout",
- "_request_auth",
- "_content_type",
- "_headers",
- ]
- )
-
- # validate the arguments
- for _key, _val in _params["kwargs"].items():
- if _key not in _all_params:
- raise ApiTypeError(
- "Got an unexpected keyword argument '%s'"
- " to method execute_agent_task_step" % _key
- )
- _params[_key] = _val
- del _params["kwargs"]
-
- _collection_formats = {}
-
- # process the path parameters
- _path_params = {}
- if _params["task_id"]:
- _path_params["task_id"] = _params["task_id"]
-
- # process the query parameters
- _query_params = []
- # process the header parameters
- _header_params = dict(_params.get("_headers", {}))
- # process the form parameters
- _form_params = []
- _files = {}
- # process the body parameter
- _body_params = None
- if _params["step_request_body"] is not None:
- _body_params = _params["step_request_body"]
-
- # set the HTTP header `Accept`
- _header_params["Accept"] = self.api_client.select_header_accept(
- ["application/json"]
- ) # noqa: E501
-
- # set the HTTP header `Content-Type`
- _content_types_list = _params.get(
- "_content_type",
- self.api_client.select_header_content_type(["application/json"]),
- )
- if _content_types_list:
- _header_params["Content-Type"] = _content_types_list
-
- # authentication setting
- _auth_settings = [] # noqa: E501
-
- _response_types_map = {
- "200": "Step",
- }
-
- return self.api_client.call_api(
- "/agent/tasks/{task_id}/steps",
- "POST",
- _path_params,
- _query_params,
- _header_params,
- body=_body_params,
- post_params=_form_params,
- files=_files,
- response_types_map=_response_types_map,
- auth_settings=_auth_settings,
- async_req=_params.get("async_req"),
- _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501
- _preload_content=_params.get("_preload_content", True),
- _request_timeout=_params.get("_request_timeout"),
- collection_formats=_collection_formats,
- _request_auth=_params.get("_request_auth"),
- )
-
- @overload
- async def get_agent_task(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- **kwargs,
- ) -> Task: # noqa: E501
- ...
-
- @overload
- def get_agent_task(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- async_req: Optional[bool] = True,
- **kwargs,
- ) -> Task: # noqa: E501
- ...
-
- @validate_arguments
- def get_agent_task(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- async_req: Optional[bool] = None,
- **kwargs,
- ) -> Union[Task, Awaitable[Task]]: # noqa: E501
- """Get details about a specified agent task. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.get_agent_task(task_id, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: Task
- """
- kwargs["_return_http_data_only"] = True
- if "_preload_content" in kwargs:
- raise ValueError(
- "Error! Please call the get_agent_task_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"
- )
- if async_req is not None:
- kwargs["async_req"] = async_req
- return self.get_agent_task_with_http_info(task_id, **kwargs) # noqa: E501
-
- @validate_arguments
- def get_agent_task_with_http_info(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- **kwargs,
- ) -> ApiResponse: # noqa: E501
- """Get details about a specified agent task. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.get_agent_task_with_http_info(task_id, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _preload_content: if False, the ApiResponse.data will
- be set to none and raw_data will store the
- HTTP response body without reading/decoding.
- Default is True.
- :type _preload_content: bool, optional
- :param _return_http_data_only: response data instead of ApiResponse
- object with status code, headers, etc
- :type _return_http_data_only: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :param _request_auth: set to override the auth_settings for an a single
- request; this effectively ignores the authentication
- in the spec for a single request.
- :type _request_auth: dict, optional
- :type _content_type: string, optional: force content-type for the request
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: tuple(Task, status_code(int), headers(HTTPHeaderDict))
- """
-
- _params = locals()
-
- _all_params = ["task_id"]
- _all_params.extend(
- [
- "async_req",
- "_return_http_data_only",
- "_preload_content",
- "_request_timeout",
- "_request_auth",
- "_content_type",
- "_headers",
- ]
- )
-
- # validate the arguments
- for _key, _val in _params["kwargs"].items():
- if _key not in _all_params:
- raise ApiTypeError(
- "Got an unexpected keyword argument '%s'"
- " to method get_agent_task" % _key
- )
- _params[_key] = _val
- del _params["kwargs"]
-
- _collection_formats = {}
-
- # process the path parameters
- _path_params = {}
- if _params["task_id"]:
- _path_params["task_id"] = _params["task_id"]
-
- # process the query parameters
- _query_params = []
- # process the header parameters
- _header_params = dict(_params.get("_headers", {}))
- # process the form parameters
- _form_params = []
- _files = {}
- # process the body parameter
- _body_params = None
- # set the HTTP header `Accept`
- _header_params["Accept"] = self.api_client.select_header_accept(
- ["application/json"]
- ) # noqa: E501
-
- # authentication setting
- _auth_settings = [] # noqa: E501
-
- _response_types_map = {
- "200": "Task",
- }
-
- return self.api_client.call_api(
- "/agent/tasks/{task_id}",
- "GET",
- _path_params,
- _query_params,
- _header_params,
- body=_body_params,
- post_params=_form_params,
- files=_files,
- response_types_map=_response_types_map,
- auth_settings=_auth_settings,
- async_req=_params.get("async_req"),
- _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501
- _preload_content=_params.get("_preload_content", True),
- _request_timeout=_params.get("_request_timeout"),
- collection_formats=_collection_formats,
- _request_auth=_params.get("_request_auth"),
- )
-
- @overload
- async def get_agent_task_step(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- step_id: Annotated[StrictStr, Field(..., description="ID of the step")],
- **kwargs,
- ) -> Step: # noqa: E501
- ...
-
- @overload
- def get_agent_task_step(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- step_id: Annotated[StrictStr, Field(..., description="ID of the step")],
- async_req: Optional[bool] = True,
- **kwargs,
- ) -> Step: # noqa: E501
- ...
-
- @validate_arguments
- def get_agent_task_step(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- step_id: Annotated[StrictStr, Field(..., description="ID of the step")],
- async_req: Optional[bool] = None,
- **kwargs,
- ) -> Union[Step, Awaitable[Step]]: # noqa: E501
- """Get details about a specified task step. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.get_agent_task_step(task_id, step_id, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param step_id: ID of the step (required)
- :type step_id: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: Step
- """
- kwargs["_return_http_data_only"] = True
- if "_preload_content" in kwargs:
- raise ValueError(
- "Error! Please call the get_agent_task_step_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"
- )
- if async_req is not None:
- kwargs["async_req"] = async_req
- return self.get_agent_task_step_with_http_info(
- task_id, step_id, **kwargs
- ) # noqa: E501
-
- @validate_arguments
- def get_agent_task_step_with_http_info(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- step_id: Annotated[StrictStr, Field(..., description="ID of the step")],
- **kwargs,
- ) -> ApiResponse: # noqa: E501
- """Get details about a specified task step. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.get_agent_task_step_with_http_info(task_id, step_id, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param step_id: ID of the step (required)
- :type step_id: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _preload_content: if False, the ApiResponse.data will
- be set to none and raw_data will store the
- HTTP response body without reading/decoding.
- Default is True.
- :type _preload_content: bool, optional
- :param _return_http_data_only: response data instead of ApiResponse
- object with status code, headers, etc
- :type _return_http_data_only: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :param _request_auth: set to override the auth_settings for an a single
- request; this effectively ignores the authentication
- in the spec for a single request.
- :type _request_auth: dict, optional
- :type _content_type: string, optional: force content-type for the request
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: tuple(Step, status_code(int), headers(HTTPHeaderDict))
- """
-
- _params = locals()
-
- _all_params = ["task_id", "step_id"]
- _all_params.extend(
- [
- "async_req",
- "_return_http_data_only",
- "_preload_content",
- "_request_timeout",
- "_request_auth",
- "_content_type",
- "_headers",
- ]
- )
-
- # validate the arguments
- for _key, _val in _params["kwargs"].items():
- if _key not in _all_params:
- raise ApiTypeError(
- "Got an unexpected keyword argument '%s'"
- " to method get_agent_task_step" % _key
- )
- _params[_key] = _val
- del _params["kwargs"]
-
- _collection_formats = {}
-
- # process the path parameters
- _path_params = {}
- if _params["task_id"]:
- _path_params["task_id"] = _params["task_id"]
-
- if _params["step_id"]:
- _path_params["step_id"] = _params["step_id"]
-
- # process the query parameters
- _query_params = []
- # process the header parameters
- _header_params = dict(_params.get("_headers", {}))
- # process the form parameters
- _form_params = []
- _files = {}
- # process the body parameter
- _body_params = None
- # set the HTTP header `Accept`
- _header_params["Accept"] = self.api_client.select_header_accept(
- ["application/json"]
- ) # noqa: E501
-
- # authentication setting
- _auth_settings = [] # noqa: E501
-
- _response_types_map = {
- "200": "Step",
- }
-
- return self.api_client.call_api(
- "/agent/tasks/{task_id}/steps/{step_id}",
- "GET",
- _path_params,
- _query_params,
- _header_params,
- body=_body_params,
- post_params=_form_params,
- files=_files,
- response_types_map=_response_types_map,
- auth_settings=_auth_settings,
- async_req=_params.get("async_req"),
- _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501
- _preload_content=_params.get("_preload_content", True),
- _request_timeout=_params.get("_request_timeout"),
- collection_formats=_collection_formats,
- _request_auth=_params.get("_request_auth"),
- )
-
- @overload
- async def list_agent_task_artifacts(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- **kwargs,
- ) -> Any: # noqa: E501
- ...
-
- @overload
- def list_agent_task_artifacts(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- async_req: Optional[bool] = True,
- **kwargs,
- ) -> Any: # noqa: E501
- ...
-
- @validate_arguments
- def list_agent_task_artifacts(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- async_req: Optional[bool] = None,
- **kwargs,
- ) -> Union[Any, Awaitable[Any]]: # noqa: E501
- """List all artifacts that have been created for the given task. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.list_agent_task_artifacts(task_id, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: List[Artifact]
- """
- kwargs["_return_http_data_only"] = True
- if "_preload_content" in kwargs:
- raise ValueError(
- "Error! Please call the list_agent_task_artifacts_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"
- )
- if async_req is not None:
- kwargs["async_req"] = async_req
- return self.list_agent_task_artifacts_with_http_info(
- task_id, **kwargs
- ) # noqa: E501
-
- @validate_arguments
- def list_agent_task_artifacts_with_http_info(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- **kwargs,
- ) -> ApiResponse: # noqa: E501
- """List all artifacts that have been created for the given task. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.list_agent_task_artifacts_with_http_info(task_id, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _preload_content: if False, the ApiResponse.data will
- be set to none and raw_data will store the
- HTTP response body without reading/decoding.
- Default is True.
- :type _preload_content: bool, optional
- :param _return_http_data_only: response data instead of ApiResponse
- object with status code, headers, etc
- :type _return_http_data_only: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :param _request_auth: set to override the auth_settings for an a single
- request; this effectively ignores the authentication
- in the spec for a single request.
- :type _request_auth: dict, optional
- :type _content_type: string, optional: force content-type for the request
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: tuple(List[Artifact], status_code(int), headers(HTTPHeaderDict))
- """
-
- _params = locals()
-
- _all_params = ["task_id"]
- _all_params.extend(
- [
- "async_req",
- "_return_http_data_only",
- "_preload_content",
- "_request_timeout",
- "_request_auth",
- "_content_type",
- "_headers",
- ]
- )
-
- # validate the arguments
- for _key, _val in _params["kwargs"].items():
- if _key not in _all_params:
- raise ApiTypeError(
- "Got an unexpected keyword argument '%s'"
- " to method list_agent_task_artifacts" % _key
- )
- _params[_key] = _val
- del _params["kwargs"]
-
- _collection_formats = {}
-
- # process the path parameters
- _path_params = {}
- if _params["task_id"]:
- _path_params["task_id"] = _params["task_id"]
-
- # process the query parameters
- _query_params = []
- # process the header parameters
- _header_params = dict(_params.get("_headers", {}))
- # process the form parameters
- _form_params = []
- _files = {}
- # process the body parameter
- _body_params = None
- # set the HTTP header `Accept`
- _header_params["Accept"] = self.api_client.select_header_accept(
- ["application/json"]
- ) # noqa: E501
-
- # authentication setting
- _auth_settings = [] # noqa: E501
-
- _response_types_map = {
- "200": "Artifacts",
- }
-
- return self.api_client.call_api(
- "/agent/tasks/{task_id}/artifacts",
- "GET",
- _path_params,
- _query_params,
- _header_params,
- body=_body_params,
- post_params=_form_params,
- files=_files,
- response_types_map=_response_types_map,
- auth_settings=_auth_settings,
- async_req=_params.get("async_req"),
- _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501
- _preload_content=_params.get("_preload_content", True),
- _request_timeout=_params.get("_request_timeout"),
- collection_formats=_collection_formats,
- _request_auth=_params.get("_request_auth"),
- )
-
- @overload
- async def list_agent_task_steps(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- **kwargs,
- ) -> List[str]: # noqa: E501
- ...
-
- @overload
- def list_agent_task_steps(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- async_req: Optional[bool] = True,
- **kwargs,
- ) -> List[str]: # noqa: E501
- ...
-
- @validate_arguments
- def list_agent_task_steps(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- async_req: Optional[bool] = None,
- **kwargs,
- ) -> Union[List[str], Awaitable[List[str]]]: # noqa: E501
- """List all steps for the specified task. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.list_agent_task_steps(task_id, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: List[str]
- """
- kwargs["_return_http_data_only"] = True
- if "_preload_content" in kwargs:
- raise ValueError(
- "Error! Please call the list_agent_task_steps_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"
- )
- if async_req is not None:
- kwargs["async_req"] = async_req
- return self.list_agent_task_steps_with_http_info(
- task_id, **kwargs
- ) # noqa: E501
-
- @validate_arguments
- def list_agent_task_steps_with_http_info(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- **kwargs,
- ) -> ApiResponse: # noqa: E501
- """List all steps for the specified task. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.list_agent_task_steps_with_http_info(task_id, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _preload_content: if False, the ApiResponse.data will
- be set to none and raw_data will store the
- HTTP response body without reading/decoding.
- Default is True.
- :type _preload_content: bool, optional
- :param _return_http_data_only: response data instead of ApiResponse
- object with status code, headers, etc
- :type _return_http_data_only: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :param _request_auth: set to override the auth_settings for an a single
- request; this effectively ignores the authentication
- in the spec for a single request.
- :type _request_auth: dict, optional
- :type _content_type: string, optional: force content-type for the request
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: tuple(List[str], status_code(int), headers(HTTPHeaderDict))
- """
-
- _params = locals()
-
- _all_params = ["task_id"]
- _all_params.extend(
- [
- "async_req",
- "_return_http_data_only",
- "_preload_content",
- "_request_timeout",
- "_request_auth",
- "_content_type",
- "_headers",
- ]
- )
-
- # validate the arguments
- for _key, _val in _params["kwargs"].items():
- if _key not in _all_params:
- raise ApiTypeError(
- "Got an unexpected keyword argument '%s'"
- " to method list_agent_task_steps" % _key
- )
- _params[_key] = _val
- del _params["kwargs"]
-
- _collection_formats = {}
-
- # process the path parameters
- _path_params = {}
- if _params["task_id"]:
- _path_params["task_id"] = _params["task_id"]
-
- # process the query parameters
- _query_params = []
- # process the header parameters
- _header_params = dict(_params.get("_headers", {}))
- # process the form parameters
- _form_params = []
- _files = {}
- # process the body parameter
- _body_params = None
- # set the HTTP header `Accept`
- _header_params["Accept"] = self.api_client.select_header_accept(
- ["application/json"]
- ) # noqa: E501
-
- # authentication setting
- _auth_settings = [] # noqa: E501
-
- _response_types_map = {
- "200": "List[str]",
- }
-
- return self.api_client.call_api(
- "/agent/tasks/{task_id}/steps",
- "GET",
- _path_params,
- _query_params,
- _header_params,
- body=_body_params,
- post_params=_form_params,
- files=_files,
- response_types_map=_response_types_map,
- auth_settings=_auth_settings,
- async_req=_params.get("async_req"),
- _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501
- _preload_content=_params.get("_preload_content", True),
- _request_timeout=_params.get("_request_timeout"),
- collection_formats=_collection_formats,
- _request_auth=_params.get("_request_auth"),
- )
-
- @overload
- async def list_agent_tasks_ids(self, **kwargs) -> List[str]: # noqa: E501
- ...
-
- @overload
- def list_agent_tasks_ids(
- self, async_req: Optional[bool] = True, **kwargs
- ) -> List[str]: # noqa: E501
- ...
-
- @validate_arguments
- def list_agent_tasks_ids(
- self, async_req: Optional[bool] = None, **kwargs
- ) -> Union[List[str], Awaitable[List[str]]]: # noqa: E501
- """List all tasks that have been created for the agent. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.list_agent_tasks_ids(async_req=True)
- >>> result = thread.get()
-
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: List[str]
- """
- kwargs["_return_http_data_only"] = True
- if "_preload_content" in kwargs:
- raise ValueError(
- "Error! Please call the list_agent_tasks_ids_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"
- )
- if async_req is not None:
- kwargs["async_req"] = async_req
- return self.list_agent_tasks_ids_with_http_info(**kwargs) # noqa: E501
-
- @validate_arguments
- def list_agent_tasks_ids_with_http_info(
- self, **kwargs
- ) -> ApiResponse: # noqa: E501
- """List all tasks that have been created for the agent. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.list_agent_tasks_ids_with_http_info(async_req=True)
- >>> result = thread.get()
-
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _preload_content: if False, the ApiResponse.data will
- be set to none and raw_data will store the
- HTTP response body without reading/decoding.
- Default is True.
- :type _preload_content: bool, optional
- :param _return_http_data_only: response data instead of ApiResponse
- object with status code, headers, etc
- :type _return_http_data_only: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :param _request_auth: set to override the auth_settings for an a single
- request; this effectively ignores the authentication
- in the spec for a single request.
- :type _request_auth: dict, optional
- :type _content_type: string, optional: force content-type for the request
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: tuple(List[str], status_code(int), headers(HTTPHeaderDict))
- """
-
- _params = locals()
-
- _all_params = []
- _all_params.extend(
- [
- "async_req",
- "_return_http_data_only",
- "_preload_content",
- "_request_timeout",
- "_request_auth",
- "_content_type",
- "_headers",
- ]
- )
-
- # validate the arguments
- for _key, _val in _params["kwargs"].items():
- if _key not in _all_params:
- raise ApiTypeError(
- "Got an unexpected keyword argument '%s'"
- " to method list_agent_tasks_ids" % _key
- )
- _params[_key] = _val
- del _params["kwargs"]
-
- _collection_formats = {}
-
- # process the path parameters
- _path_params = {}
-
- # process the query parameters
- _query_params = []
- # process the header parameters
- _header_params = dict(_params.get("_headers", {}))
- # process the form parameters
- _form_params = []
- _files = {}
- # process the body parameter
- _body_params = None
- # set the HTTP header `Accept`
- _header_params["Accept"] = self.api_client.select_header_accept(
- ["application/json"]
- ) # noqa: E501
-
- # authentication setting
- _auth_settings = [] # noqa: E501
-
- _response_types_map = {
- "200": "List[str]",
- }
-
- return self.api_client.call_api(
- "/agent/tasks",
- "GET",
- _path_params,
- _query_params,
- _header_params,
- body=_body_params,
- post_params=_form_params,
- files=_files,
- response_types_map=_response_types_map,
- auth_settings=_auth_settings,
- async_req=_params.get("async_req"),
- _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501
- _preload_content=_params.get("_preload_content", True),
- _request_timeout=_params.get("_request_timeout"),
- collection_formats=_collection_formats,
- _request_auth=_params.get("_request_auth"),
- )
-
- @overload
- async def upload_agent_task_artifacts(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- file: Annotated[
- Union[StrictBytes, StrictStr], Field(..., description="File to upload.")
- ],
- relative_path: Annotated[
- Optional[StrictStr],
- Field(
- description="Relative path of the artifact in the agent's workspace."
- ),
- ] = None,
- **kwargs,
- ) -> Artifact: # noqa: E501
- ...
-
- @overload
- def upload_agent_task_artifacts(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- file: Annotated[
- Union[StrictBytes, StrictStr], Field(..., description="File to upload.")
- ],
- relative_path: Annotated[
- Optional[StrictStr],
- Field(
- description="Relative path of the artifact in the agent's workspace."
- ),
- ] = None,
- async_req: Optional[bool] = True,
- **kwargs,
- ) -> Artifact: # noqa: E501
- ...
-
- @validate_arguments
- def upload_agent_task_artifacts(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- file: Annotated[
- Union[StrictBytes, StrictStr], Field(..., description="File to upload.")
- ],
- relative_path: Annotated[
- Optional[StrictStr],
- Field(
- description="Relative path of the artifact in the agent's workspace."
- ),
- ] = None,
- async_req: Optional[bool] = None,
- **kwargs,
- ) -> Union[Artifact, Awaitable[Artifact]]: # noqa: E501
- """Upload an artifact for the specified task. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.upload_agent_task_artifacts(task_id, file, relative_path, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param file: File to upload. (required)
- :type file: bytearray
- :param relative_path: Relative path of the artifact in the agent's workspace.
- :type relative_path: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: Artifact
- """
- kwargs["_return_http_data_only"] = True
- if "_preload_content" in kwargs:
- raise ValueError(
- "Error! Please call the upload_agent_task_artifacts_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"
- )
- if async_req is not None:
- kwargs["async_req"] = async_req
- return self.upload_agent_task_artifacts_with_http_info(
- task_id, file, relative_path, **kwargs
- ) # noqa: E501
-
- @validate_arguments
- def upload_agent_task_artifacts_with_http_info(
- self,
- task_id: Annotated[StrictStr, Field(..., description="ID of the task")],
- file: Annotated[
- Union[StrictBytes, StrictStr], Field(..., description="File to upload.")
- ],
- relative_path: Annotated[
- Optional[StrictStr],
- Field(
- description="Relative path of the artifact in the agent's workspace."
- ),
- ] = None,
- **kwargs,
- ) -> ApiResponse: # noqa: E501
- """Upload an artifact for the specified task. # noqa: E501
-
- This method makes a synchronous HTTP request by default. To make an
- asynchronous HTTP request, please pass async_req=True
-
- >>> thread = api.upload_agent_task_artifacts_with_http_info(task_id, file, relative_path, async_req=True)
- >>> result = thread.get()
-
- :param task_id: ID of the task (required)
- :type task_id: str
- :param file: File to upload. (required)
- :type file: bytearray
- :param relative_path: Relative path of the artifact in the agent's workspace.
- :type relative_path: str
- :param async_req: Whether to execute the request asynchronously.
- :type async_req: bool, optional
- :param _preload_content: if False, the ApiResponse.data will
- be set to none and raw_data will store the
- HTTP response body without reading/decoding.
- Default is True.
- :type _preload_content: bool, optional
- :param _return_http_data_only: response data instead of ApiResponse
- object with status code, headers, etc
- :type _return_http_data_only: bool, optional
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :param _request_auth: set to override the auth_settings for an a single
- request; this effectively ignores the authentication
- in the spec for a single request.
- :type _request_auth: dict, optional
- :type _content_type: string, optional: force content-type for the request
- :return: Returns the result object.
- If the method is called asynchronously,
- returns the request thread.
- :rtype: tuple(Artifact, status_code(int), headers(HTTPHeaderDict))
- """
-
- _params = locals()
-
- _all_params = ["task_id", "file", "relative_path"]
- _all_params.extend(
- [
- "async_req",
- "_return_http_data_only",
- "_preload_content",
- "_request_timeout",
- "_request_auth",
- "_content_type",
- "_headers",
- ]
- )
-
- # validate the arguments
- for _key, _val in _params["kwargs"].items():
- if _key not in _all_params:
- raise ApiTypeError(
- "Got an unexpected keyword argument '%s'"
- " to method upload_agent_task_artifacts" % _key
- )
- _params[_key] = _val
- del _params["kwargs"]
-
- _collection_formats = {}
-
- # process the path parameters
- _path_params = {}
- if _params["task_id"]:
- _path_params["task_id"] = _params["task_id"]
-
- # process the query parameters
- _query_params = []
- # process the header parameters
- _header_params = dict(_params.get("_headers", {}))
- # process the form parameters
- _form_params = []
- _files = {}
- if _params["file"]:
- _files["file"] = _params["file"]
-
- if _params["relative_path"]:
- _form_params.append(("relative_path", _params["relative_path"]))
-
- # process the body parameter
- _body_params = None
- # set the HTTP header `Accept`
- _header_params["Accept"] = self.api_client.select_header_accept(
- ["application/json"]
- ) # noqa: E501
-
- # set the HTTP header `Content-Type`
- _content_types_list = _params.get(
- "_content_type",
- self.api_client.select_header_content_type(["multipart/form-data"]),
- )
- if _content_types_list:
- _header_params["Content-Type"] = _content_types_list
-
- # authentication setting
- _auth_settings = [] # noqa: E501
-
- _response_types_map = {
- "200": "Artifact",
- }
-
- return self.api_client.call_api(
- "/agent/tasks/{task_id}/artifacts",
- "POST",
- _path_params,
- _query_params,
- _header_params,
- body=_body_params,
- post_params=_form_params,
- files=_files,
- response_types_map=_response_types_map,
- auth_settings=_auth_settings,
- async_req=_params.get("async_req"),
- _return_http_data_only=_params.get("_return_http_data_only"), # noqa: E501
- _preload_content=_params.get("_preload_content", True),
- _request_timeout=_params.get("_request_timeout"),
- collection_formats=_collection_formats,
- _request_auth=_params.get("_request_auth"),
- )
diff --git a/benchmark/agbenchmark/agent_protocol_client/api_client.py b/benchmark/agbenchmark/agent_protocol_client/api_client.py
deleted file mode 100644
index ce178a96b..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/api_client.py
+++ /dev/null
@@ -1,838 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-import atexit
-import datetime
-import json
-import mimetypes
-import os
-import re
-import tempfile
-from multiprocessing.pool import ThreadPool
-from urllib.parse import quote
-
-from dateutil.parser import parse
-
-import agbenchmark.agent_protocol_client.models
-from agbenchmark.agent_protocol_client import rest
-from agbenchmark.agent_protocol_client.api_response import ApiResponse
-from agbenchmark.agent_protocol_client.configuration import Configuration
-from agbenchmark.agent_protocol_client.exceptions import ApiException, ApiValueError
-
-
-class ApiClient(object):
- """Generic API client for OpenAPI client library builds.
-
- OpenAPI generic API client. This client handles the client-
- server communication, and is invariant across implementations. Specifics of
- the methods and models for each application are generated from the OpenAPI
- templates.
-
- :param configuration: .Configuration object for this client
- :param header_name: a header to pass when making calls to the API.
- :param header_value: a header value to pass when making calls to
- the API.
- :param cookie: a cookie to include in the header when making calls
- to the API
- :param pool_threads: The number of threads to use for async requests
- to the API. More threads means more concurrent API requests.
- """
-
- PRIMITIVE_TYPES = (float, bool, bytes, str, int)
- NATIVE_TYPES_MAPPING = {
- "int": int,
- "long": int, # TODO remove as only py3 is supported?
- "float": float,
- "str": str,
- "bool": bool,
- "date": datetime.date,
- "datetime": datetime.datetime,
- "object": object,
- }
- _pool = None
-
- def __init__(
- self,
- configuration=None,
- header_name=None,
- header_value=None,
- cookie=None,
- pool_threads=1,
- ):
- # use default configuration if none is provided
- if configuration is None:
- configuration = Configuration.get_default()
- self.configuration = configuration
- self.pool_threads = pool_threads
-
- self.rest_client = rest.RESTClientObject(configuration)
- self.default_headers = {}
- if header_name is not None:
- self.default_headers[header_name] = header_value
- self.cookie = cookie
- # Set default User-Agent.
- self.user_agent = "OpenAPI-Generator/1.0.0/python"
- self.client_side_validation = configuration.client_side_validation
-
- async def __aenter__(self):
- return self
-
- async def __aexit__(self, exc_type, exc_value, traceback):
- await self.close()
-
- async def close(self):
- await self.rest_client.close()
- if self._pool:
- self._pool.close()
- self._pool.join()
- self._pool = None
- if hasattr(atexit, "unregister"):
- atexit.unregister(self.close)
-
- @property
- def pool(self):
- """Create thread pool on first request
- avoids instantiating unused threadpool for blocking clients.
- """
- if self._pool is None:
- atexit.register(self.close)
- self._pool = ThreadPool(self.pool_threads)
- return self._pool
-
- @property
- def user_agent(self):
- """User agent for this API client"""
- return self.default_headers["User-Agent"]
-
- @user_agent.setter
- def user_agent(self, value):
- self.default_headers["User-Agent"] = value
-
- def set_default_header(self, header_name, header_value):
- self.default_headers[header_name] = header_value
-
- _default = None
-
- @classmethod
- def get_default(cls):
- """Return new instance of ApiClient.
-
- This method returns newly created, based on default constructor,
- object of ApiClient class or returns a copy of default
- ApiClient.
-
- :return: The ApiClient object.
- """
- if cls._default is None:
- cls._default = ApiClient()
- return cls._default
-
- @classmethod
- def set_default(cls, default):
- """Set default instance of ApiClient.
-
- It stores default ApiClient.
-
- :param default: object of ApiClient.
- """
- cls._default = default
-
- async def __call_api(
- self,
- resource_path,
- method,
- path_params=None,
- query_params=None,
- header_params=None,
- body=None,
- post_params=None,
- files=None,
- response_types_map=None,
- auth_settings=None,
- _return_http_data_only=None,
- collection_formats=None,
- _preload_content=True,
- _request_timeout=None,
- _host=None,
- _request_auth=None,
- ):
- config = self.configuration
-
- # header parameters
- header_params = header_params or {}
- header_params.update(self.default_headers)
- if self.cookie:
- header_params["Cookie"] = self.cookie
- if header_params:
- header_params = self.sanitize_for_serialization(header_params)
- header_params = dict(
- self.parameters_to_tuples(header_params, collection_formats)
- )
-
- # path parameters
- if path_params:
- path_params = self.sanitize_for_serialization(path_params)
- path_params = self.parameters_to_tuples(path_params, collection_formats)
- for k, v in path_params:
- # specified safe chars, encode everything
- resource_path = resource_path.replace(
- "{%s}" % k, quote(str(v), safe=config.safe_chars_for_path_param)
- )
-
- # post parameters
- if post_params or files:
- post_params = post_params if post_params else []
- post_params = self.sanitize_for_serialization(post_params)
- post_params = self.parameters_to_tuples(post_params, collection_formats)
- post_params.extend(self.files_parameters(files))
-
- # auth setting
- self.update_params_for_auth(
- header_params,
- query_params,
- auth_settings,
- resource_path,
- method,
- body,
- request_auth=_request_auth,
- )
-
- # body
- if body:
- body = self.sanitize_for_serialization(body)
-
- # request url
- if _host is None:
- url = self.configuration.host + resource_path
- else:
- # use server/host defined in path or operation instead
- url = _host + resource_path
-
- # query parameters
- if query_params:
- query_params = self.sanitize_for_serialization(query_params)
- url_query = self.parameters_to_url_query(query_params, collection_formats)
- url += "?" + url_query
-
- try:
- # perform request and return response
- response_data = await self.request(
- method,
- url,
- query_params=query_params,
- headers=header_params,
- post_params=post_params,
- body=body,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- )
- except ApiException as e:
- if e.body:
- e.body = e.body.decode("utf-8")
- raise e
-
- self.last_response = response_data
-
- return_data = None # assuming derialization is not needed
- # data needs deserialization or returns HTTP data (deserialized) only
- if _preload_content or _return_http_data_only:
- response_type = response_types_map.get(str(response_data.status), None)
-
- if response_type == "bytearray":
- response_data.data = response_data.data
- else:
- match = None
- content_type = response_data.getheader("content-type")
- if content_type is not None:
- match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type)
- encoding = match.group(1) if match else "utf-8"
- response_data.data = response_data.data.decode(encoding)
-
- # deserialize response data
- if response_type == "bytearray":
- return_data = response_data.data
- elif response_type:
- return_data = self.deserialize(response_data, response_type)
- else:
- return_data = None
-
- if _return_http_data_only:
- return return_data
- else:
- return ApiResponse(
- status_code=response_data.status,
- data=return_data,
- headers=response_data.getheaders(),
- raw_data=response_data.data,
- )
-
- def sanitize_for_serialization(self, obj):
- """Builds a JSON POST object.
-
- If obj is None, return None.
- If obj is str, int, long, float, bool, return directly.
- If obj is datetime.datetime, datetime.date
- convert to string in iso8601 format.
- If obj is list, sanitize each element in the list.
- If obj is dict, return the dict.
- If obj is OpenAPI model, return the properties dict.
-
- :param obj: The data to serialize.
- :return: The serialized form of data.
- """
- if obj is None:
- return None
- elif isinstance(obj, self.PRIMITIVE_TYPES):
- return obj
- elif isinstance(obj, list):
- return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj]
- elif isinstance(obj, tuple):
- return tuple(self.sanitize_for_serialization(sub_obj) for sub_obj in obj)
- elif isinstance(obj, (datetime.datetime, datetime.date)):
- return obj.isoformat()
-
- if isinstance(obj, dict):
- obj_dict = obj
- else:
- # Convert model obj to dict except
- # attributes `openapi_types`, `attribute_map`
- # and attributes which value is not None.
- # Convert attribute name to json key in
- # model definition for request.
- obj_dict = obj.to_dict()
-
- return {
- key: self.sanitize_for_serialization(val) for key, val in obj_dict.items()
- }
-
- def deserialize(self, response, response_type):
- """Deserializes response into an object.
-
- :param response: RESTResponse object to be deserialized.
- :param response_type: class literal for
- deserialized object, or string of class name.
-
- :return: deserialized object.
- """
- # handle file downloading
- # save response body into a tmp file and return the instance
- if response_type == "file":
- return self.__deserialize_file(response)
-
- # fetch data from response object
- try:
- data = json.loads(response.data)
- except ValueError:
- data = response.data
-
- return self.__deserialize(data, response_type)
-
- def __deserialize(self, data, klass):
- """Deserializes dict, list, str into an object.
-
- :param data: dict, list or str.
- :param klass: class literal, or string of class name.
-
- :return: object.
- """
- if data is None:
- return None
-
- if type(klass) == str:
- if klass.startswith("List["):
- sub_kls = re.match(r"List\[(.*)]", klass).group(1)
- return [self.__deserialize(sub_data, sub_kls) for sub_data in data]
-
- if klass.startswith("Dict["):
- sub_kls = re.match(r"Dict\[([^,]*), (.*)]", klass).group(2)
- return {k: self.__deserialize(v, sub_kls) for k, v in data.items()}
-
- # convert str to class
- if klass in self.NATIVE_TYPES_MAPPING:
- klass = self.NATIVE_TYPES_MAPPING[klass]
- else:
- klass = getattr(agbenchmark.agent_protocol_client.models, klass)
-
- if klass in self.PRIMITIVE_TYPES:
- return self.__deserialize_primitive(data, klass)
- elif klass == object:
- return self.__deserialize_object(data)
- elif klass == datetime.date:
- return self.__deserialize_date(data)
- elif klass == datetime.datetime:
- return self.__deserialize_datetime(data)
- else:
- return self.__deserialize_model(data, klass)
-
- def call_api(
- self,
- resource_path,
- method,
- path_params=None,
- query_params=None,
- header_params=None,
- body=None,
- post_params=None,
- files=None,
- response_types_map=None,
- auth_settings=None,
- async_req=None,
- _return_http_data_only=None,
- collection_formats=None,
- _preload_content=True,
- _request_timeout=None,
- _host=None,
- _request_auth=None,
- ):
- """Makes the HTTP request (synchronous) and returns deserialized data.
-
- To make an async_req request, set the async_req parameter.
-
- :param resource_path: Path to method endpoint.
- :param method: Method to call.
- :param path_params: Path parameters in the url.
- :param query_params: Query parameters in the url.
- :param header_params: Header parameters to be
- placed in the request header.
- :param body: Request body.
- :param post_params dict: Request post form parameters,
- for `application/x-www-form-urlencoded`, `multipart/form-data`.
- :param auth_settings list: Auth Settings names for the request.
- :param response: Response data type.
- :param files dict: key -> filename, value -> filepath,
- for `multipart/form-data`.
- :param async_req bool: execute request asynchronously
- :param _return_http_data_only: response data instead of ApiResponse
- object with status code, headers, etc
- :param _preload_content: if False, the ApiResponse.data will
- be set to none and raw_data will store the
- HTTP response body without reading/decoding.
- Default is True.
- :param collection_formats: dict of collection formats for path, query,
- header, and post parameters.
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- :param _request_auth: set to override the auth_settings for an a single
- request; this effectively ignores the authentication
- in the spec for a single request.
- :type _request_token: dict, optional
- :return:
- If async_req parameter is True,
- the request will be called asynchronously.
- The method will return the request thread.
- If parameter async_req is False or missing,
- then the method will return the response directly.
- """
- if not async_req:
- return self.__call_api(
- resource_path,
- method,
- path_params,
- query_params,
- header_params,
- body,
- post_params,
- files,
- response_types_map,
- auth_settings,
- _return_http_data_only,
- collection_formats,
- _preload_content,
- _request_timeout,
- _host,
- _request_auth,
- )
-
- return self.pool.apply_async(
- self.__call_api,
- (
- resource_path,
- method,
- path_params,
- query_params,
- header_params,
- body,
- post_params,
- files,
- response_types_map,
- auth_settings,
- _return_http_data_only,
- collection_formats,
- _preload_content,
- _request_timeout,
- _host,
- _request_auth,
- ),
- )
-
- def request(
- self,
- method,
- url,
- query_params=None,
- headers=None,
- post_params=None,
- body=None,
- _preload_content=True,
- _request_timeout=None,
- ):
- """Makes the HTTP request using RESTClient."""
- if method == "GET":
- return self.rest_client.get_request(
- url,
- query_params=query_params,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- headers=headers,
- )
- elif method == "HEAD":
- return self.rest_client.head_request(
- url,
- query_params=query_params,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- headers=headers,
- )
- elif method == "OPTIONS":
- return self.rest_client.options_request(
- url,
- query_params=query_params,
- headers=headers,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- )
- elif method == "POST":
- return self.rest_client.post_request(
- url,
- query_params=query_params,
- headers=headers,
- post_params=post_params,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- body=body,
- )
- elif method == "PUT":
- return self.rest_client.put_request(
- url,
- query_params=query_params,
- headers=headers,
- post_params=post_params,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- body=body,
- )
- elif method == "PATCH":
- return self.rest_client.patch_request(
- url,
- query_params=query_params,
- headers=headers,
- post_params=post_params,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- body=body,
- )
- elif method == "DELETE":
- return self.rest_client.delete_request(
- url,
- query_params=query_params,
- headers=headers,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- body=body,
- )
- else:
- raise ApiValueError(
- "http method must be `GET`, `HEAD`, `OPTIONS`,"
- " `POST`, `PATCH`, `PUT` or `DELETE`."
- )
-
- def parameters_to_tuples(self, params, collection_formats):
- """Get parameters as list of tuples, formatting collections.
-
- :param params: Parameters as dict or list of two-tuples
- :param dict collection_formats: Parameter collection formats
- :return: Parameters as list of tuples, collections formatted
- """
- new_params = []
- if collection_formats is None:
- collection_formats = {}
- for k, v in (
- params.items() if isinstance(params, dict) else params
- ): # noqa: E501
- if k in collection_formats:
- collection_format = collection_formats[k]
- if collection_format == "multi":
- new_params.extend((k, value) for value in v)
- else:
- if collection_format == "ssv":
- delimiter = " "
- elif collection_format == "tsv":
- delimiter = "\t"
- elif collection_format == "pipes":
- delimiter = "|"
- else: # csv is the default
- delimiter = ","
- new_params.append((k, delimiter.join(str(value) for value in v)))
- else:
- new_params.append((k, v))
- return new_params
-
- def parameters_to_url_query(self, params, collection_formats):
- """Get parameters as list of tuples, formatting collections.
-
- :param params: Parameters as dict or list of two-tuples
- :param dict collection_formats: Parameter collection formats
- :return: URL query string (e.g. a=Hello%20World&b=123)
- """
- new_params = []
- if collection_formats is None:
- collection_formats = {}
- for k, v in (
- params.items() if isinstance(params, dict) else params
- ): # noqa: E501
- if isinstance(v, (int, float)):
- v = str(v)
- if isinstance(v, bool):
- v = str(v).lower()
- if isinstance(v, dict):
- v = json.dumps(v)
-
- if k in collection_formats:
- collection_format = collection_formats[k]
- if collection_format == "multi":
- new_params.extend((k, value) for value in v)
- else:
- if collection_format == "ssv":
- delimiter = " "
- elif collection_format == "tsv":
- delimiter = "\t"
- elif collection_format == "pipes":
- delimiter = "|"
- else: # csv is the default
- delimiter = ","
- new_params.append(
- (k, delimiter.join(quote(str(value)) for value in v))
- )
- else:
- new_params.append((k, quote(str(v))))
-
- return "&".join(["=".join(item) for item in new_params])
-
- def files_parameters(self, files=None):
- """Builds form parameters.
-
- :param files: File parameters.
- :return: Form parameters with files.
- """
- params = []
-
- if files:
- for k, v in files.items():
- if not v:
- continue
- file_names = v if type(v) is list else [v]
- for n in file_names:
- with open(n, "rb") as f:
- filename = os.path.basename(f.name)
- filedata = f.read()
- mimetype = (
- mimetypes.guess_type(filename)[0]
- or "application/octet-stream"
- )
- params.append(tuple([k, tuple([filename, filedata, mimetype])]))
-
- return params
-
- def select_header_accept(self, accepts):
- """Returns `Accept` based on an array of accepts provided.
-
- :param accepts: List of headers.
- :return: Accept (e.g. application/json).
- """
- if not accepts:
- return
-
- for accept in accepts:
- if re.search("json", accept, re.IGNORECASE):
- return accept
-
- return accepts[0]
-
- def select_header_content_type(self, content_types):
- """Returns `Content-Type` based on an array of content_types provided.
-
- :param content_types: List of content-types.
- :return: Content-Type (e.g. application/json).
- """
- if not content_types:
- return None
-
- for content_type in content_types:
- if re.search("json", content_type, re.IGNORECASE):
- return content_type
-
- return content_types[0]
-
- def update_params_for_auth(
- self,
- headers,
- queries,
- auth_settings,
- resource_path,
- method,
- body,
- request_auth=None,
- ):
- """Updates header and query params based on authentication setting.
-
- :param headers: Header parameters dict to be updated.
- :param queries: Query parameters tuple list to be updated.
- :param auth_settings: Authentication setting identifiers list.
- :resource_path: A string representation of the HTTP request resource path.
- :method: A string representation of the HTTP request method.
- :body: A object representing the body of the HTTP request.
- The object type is the return value of sanitize_for_serialization().
- :param request_auth: if set, the provided settings will
- override the token in the configuration.
- """
- if not auth_settings:
- return
-
- if request_auth:
- self._apply_auth_params(
- headers, queries, resource_path, method, body, request_auth
- )
- return
-
- for auth in auth_settings:
- auth_setting = self.configuration.auth_settings().get(auth)
- if auth_setting:
- self._apply_auth_params(
- headers, queries, resource_path, method, body, auth_setting
- )
-
- def _apply_auth_params(
- self, headers, queries, resource_path, method, body, auth_setting
- ):
- """Updates the request parameters based on a single auth_setting
-
- :param headers: Header parameters dict to be updated.
- :param queries: Query parameters tuple list to be updated.
- :resource_path: A string representation of the HTTP request resource path.
- :method: A string representation of the HTTP request method.
- :body: A object representing the body of the HTTP request.
- The object type is the return value of sanitize_for_serialization().
- :param auth_setting: auth settings for the endpoint
- """
- if auth_setting["in"] == "cookie":
- headers["Cookie"] = auth_setting["value"]
- elif auth_setting["in"] == "header":
- if auth_setting["type"] != "http-signature":
- headers[auth_setting["key"]] = auth_setting["value"]
- elif auth_setting["in"] == "query":
- queries.append((auth_setting["key"], auth_setting["value"]))
- else:
- raise ApiValueError("Authentication token must be in `query` or `header`")
-
- def __deserialize_file(self, response):
- """Deserializes body to file
-
- Saves response body into a file in a temporary folder,
- using the filename from the `Content-Disposition` header if provided.
-
- :param response: RESTResponse.
- :return: file path.
- """
- fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path)
- os.close(fd)
- os.remove(path)
-
- content_disposition = response.getheader("Content-Disposition")
- if content_disposition:
- filename = re.search(
- r'filename=[\'"]?([^\'"\s]+)[\'"]?', content_disposition
- ).group(1)
- path = os.path.join(os.path.dirname(path), filename)
-
- with open(path, "wb") as f:
- f.write(response.data)
-
- return path
-
- def __deserialize_primitive(self, data, klass):
- """Deserializes string to primitive type.
-
- :param data: str.
- :param klass: class literal.
-
- :return: int, long, float, str, bool.
- """
- try:
- return klass(data)
- except UnicodeEncodeError:
- return str(data)
- except TypeError:
- return data
-
- def __deserialize_object(self, value):
- """Return an original value.
-
- :return: object.
- """
- return value
-
- def __deserialize_date(self, string):
- """Deserializes string to date.
-
- :param string: str.
- :return: date.
- """
- try:
- return parse(string).date()
- except ImportError:
- return string
- except ValueError:
- raise rest.ApiException(
- status=0, reason="Failed to parse `{0}` as date object".format(string)
- )
-
- def __deserialize_datetime(self, string):
- """Deserializes string to datetime.
-
- The string should be in iso8601 datetime format.
-
- :param string: str.
- :return: datetime.
- """
- try:
- return parse(string)
- except ImportError:
- return string
- except ValueError:
- raise rest.ApiException(
- status=0,
- reason=("Failed to parse `{0}` as datetime object".format(string)),
- )
-
- def __deserialize_model(self, data, klass):
- """Deserializes list or dict to model.
-
- :param data: dict, list.
- :param klass: class literal.
- :return: model object.
- """
-
- return klass.from_dict(data)
diff --git a/benchmark/agbenchmark/agent_protocol_client/api_response.py b/benchmark/agbenchmark/agent_protocol_client/api_response.py
deleted file mode 100644
index d1fdefc1e..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/api_response.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""API response object."""
-
-from __future__ import annotations
-
-from typing import Any, Dict, Optional
-
-from pydantic import Field, StrictInt, StrictStr
-
-
-class ApiResponse:
- """
- API response object
- """
-
- status_code: Optional[StrictInt] = Field(None, description="HTTP status code")
- headers: Optional[Dict[StrictStr, StrictStr]] = Field(
- None, description="HTTP headers"
- )
- data: Optional[Any] = Field(
- None, description="Deserialized data given the data type"
- )
- raw_data: Optional[Any] = Field(None, description="Raw data (HTTP response body)")
-
- def __init__(self, status_code=None, headers=None, data=None, raw_data=None):
- self.status_code = status_code
- self.headers = headers
- self.data = data
- self.raw_data = raw_data
diff --git a/benchmark/agbenchmark/agent_protocol_client/configuration.py b/benchmark/agbenchmark/agent_protocol_client/configuration.py
deleted file mode 100644
index 8bbcec716..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/configuration.py
+++ /dev/null
@@ -1,447 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-import copy
-import http.client as httplib
-import logging
-import sys
-
-import urllib3
-
-JSON_SCHEMA_VALIDATION_KEYWORDS = {
- "multipleOf",
- "maximum",
- "exclusiveMaximum",
- "minimum",
- "exclusiveMinimum",
- "maxLength",
- "minLength",
- "pattern",
- "maxItems",
- "minItems",
-}
-
-
-class Configuration(object):
- """This class contains various settings of the API client.
-
- :param host: Base url.
- :param api_key: Dict to store API key(s).
- Each entry in the dict specifies an API key.
- The dict key is the name of the security scheme in the OAS specification.
- The dict value is the API key secret.
- :param api_key_prefix: Dict to store API prefix (e.g. Bearer).
- The dict key is the name of the security scheme in the OAS specification.
- The dict value is an API key prefix when generating the auth data.
- :param username: Username for HTTP basic authentication.
- :param password: Password for HTTP basic authentication.
- :param access_token: Access token.
- :param server_index: Index to servers configuration.
- :param server_variables: Mapping with string values to replace variables in
- templated server configuration. The validation of enums is performed for
- variables with defined enum values before.
- :param server_operation_index: Mapping from operation ID to an index to server
- configuration.
- :param server_operation_variables: Mapping from operation ID to a mapping with
- string values to replace variables in templated server configuration.
- The validation of enums is performed for variables with defined enum values before.
- :param ssl_ca_cert: str - the path to a file of concatenated CA certificates
- in PEM format.
-
- """
-
- _default = None
-
- def __init__(
- self,
- host=None,
- api_key=None,
- api_key_prefix=None,
- username=None,
- password=None,
- access_token=None,
- server_index=None,
- server_variables=None,
- server_operation_index=None,
- server_operation_variables=None,
- ssl_ca_cert=None,
- ):
- """Constructor"""
- self._base_path = "http://localhost" if host is None else host
- """Default Base url
- """
- self.server_index = 0 if server_index is None and host is None else server_index
- self.server_operation_index = server_operation_index or {}
- """Default server index
- """
- self.server_variables = server_variables or {}
- self.server_operation_variables = server_operation_variables or {}
- """Default server variables
- """
- self.temp_folder_path = None
- """Temp file folder for downloading files
- """
- # Authentication Settings
- self.api_key = {}
- if api_key:
- self.api_key = api_key
- """dict to store API key(s)
- """
- self.api_key_prefix = {}
- if api_key_prefix:
- self.api_key_prefix = api_key_prefix
- """dict to store API prefix (e.g. Bearer)
- """
- self.refresh_api_key_hook = None
- """function hook to refresh API key if expired
- """
- self.username = username
- """Username for HTTP basic authentication
- """
- self.password = password
- """Password for HTTP basic authentication
- """
- self.access_token = access_token
- """Access token
- """
- self.logger = {}
- """Logging Settings
- """
- self.logger["package_logger"] = logging.getLogger("agent_protocol_client")
- self.logger["urllib3_logger"] = logging.getLogger("urllib3")
- self.logger_format = "%(asctime)s %(levelname)s %(message)s"
- """Log format
- """
- self.logger_stream_handler = None
- """Log stream handler
- """
- self.logger_file_handler = None
- """Log file handler
- """
- self.logger_file = None
- """Debug file location
- """
- self.debug = False
- """Debug switch
- """
-
- self.verify_ssl = True
- """SSL/TLS verification
- Set this to false to skip verifying SSL certificate when calling API
- from https server.
- """
- self.ssl_ca_cert = ssl_ca_cert
- """Set this to customize the certificate file to verify the peer.
- """
- self.cert_file = None
- """client certificate file
- """
- self.key_file = None
- """client key file
- """
- self.assert_hostname = None
- """Set this to True/False to enable/disable SSL hostname verification.
- """
- self.tls_server_name = None
- """SSL/TLS Server Name Indication (SNI)
- Set this to the SNI value expected by the server.
- """
-
- self.connection_pool_maxsize = 100
- """This value is passed to the aiohttp to limit simultaneous connections.
- Default values is 100, None means no-limit.
- """
-
- self.proxy = None
- """Proxy URL
- """
- self.proxy_headers = None
- """Proxy headers
- """
- self.safe_chars_for_path_param = ""
- """Safe chars for path_param
- """
- self.retries = None
- """Adding retries to override urllib3 default value 3
- """
- # Enable client side validation
- self.client_side_validation = True
-
- self.socket_options = None
- """Options to pass down to the underlying urllib3 socket
- """
-
- self.datetime_format = "%Y-%m-%dT%H:%M:%S.%f%z"
- """datetime format
- """
-
- self.date_format = "%Y-%m-%d"
- """date format
- """
-
- def __deepcopy__(self, memo):
- cls = self.__class__
- result = cls.__new__(cls)
- memo[id(self)] = result
- for k, v in self.__dict__.items():
- if k not in ("logger", "logger_file_handler"):
- setattr(result, k, copy.deepcopy(v, memo))
- # shallow copy of loggers
- result.logger = copy.copy(self.logger)
- # use setters to configure loggers
- result.logger_file = self.logger_file
- result.debug = self.debug
- return result
-
- def __setattr__(self, name, value):
- object.__setattr__(self, name, value)
-
- @classmethod
- def set_default(cls, default):
- """Set default instance of configuration.
-
- It stores default configuration, which can be
- returned by get_default_copy method.
-
- :param default: object of Configuration
- """
- cls._default = default
-
- @classmethod
- def get_default_copy(cls):
- """Deprecated. Please use `get_default` instead.
-
- Deprecated. Please use `get_default` instead.
-
- :return: The configuration object.
- """
- return cls.get_default()
-
- @classmethod
- def get_default(cls):
- """Return the default configuration.
-
- This method returns newly created, based on default constructor,
- object of Configuration class or returns a copy of default
- configuration.
-
- :return: The configuration object.
- """
- if cls._default is None:
- cls._default = Configuration()
- return cls._default
-
- @property
- def logger_file(self):
- """The logger file.
-
- If the logger_file is None, then add stream handler and remove file
- handler. Otherwise, add file handler and remove stream handler.
-
- :param value: The logger_file path.
- :type: str
- """
- return self.__logger_file
-
- @logger_file.setter
- def logger_file(self, value):
- """The logger file.
-
- If the logger_file is None, then add stream handler and remove file
- handler. Otherwise, add file handler and remove stream handler.
-
- :param value: The logger_file path.
- :type: str
- """
- self.__logger_file = value
- if self.__logger_file:
- # If set logging file,
- # then add file handler and remove stream handler.
- self.logger_file_handler = logging.FileHandler(self.__logger_file)
- self.logger_file_handler.setFormatter(self.logger_formatter)
- for _, logger in self.logger.items():
- logger.addHandler(self.logger_file_handler)
-
- @property
- def debug(self):
- """Debug status
-
- :param value: The debug status, True or False.
- :type: bool
- """
- return self.__debug
-
- @debug.setter
- def debug(self, value):
- """Debug status
-
- :param value: The debug status, True or False.
- :type: bool
- """
- self.__debug = value
- if self.__debug:
- # if debug status is True, turn on debug logging
- for _, logger in self.logger.items():
- logger.setLevel(logging.DEBUG)
- # turn on httplib debug
- httplib.HTTPConnection.debuglevel = 1
- else:
- # if debug status is False, turn off debug logging,
- # setting log level to default `logging.WARNING`
- for _, logger in self.logger.items():
- logger.setLevel(logging.WARNING)
- # turn off httplib debug
- httplib.HTTPConnection.debuglevel = 0
-
- @property
- def logger_format(self):
- """The logger format.
-
- The logger_formatter will be updated when sets logger_format.
-
- :param value: The format string.
- :type: str
- """
- return self.__logger_format
-
- @logger_format.setter
- def logger_format(self, value):
- """The logger format.
-
- The logger_formatter will be updated when sets logger_format.
-
- :param value: The format string.
- :type: str
- """
- self.__logger_format = value
- self.logger_formatter = logging.Formatter(self.__logger_format)
-
- def get_api_key_with_prefix(self, identifier, alias=None):
- """Gets API key (with prefix if set).
-
- :param identifier: The identifier of apiKey.
- :param alias: The alternative identifier of apiKey.
- :return: The token for api key authentication.
- """
- if self.refresh_api_key_hook is not None:
- self.refresh_api_key_hook(self)
- key = self.api_key.get(
- identifier, self.api_key.get(alias) if alias is not None else None
- )
- if key:
- prefix = self.api_key_prefix.get(identifier)
- if prefix:
- return "%s %s" % (prefix, key)
- else:
- return key
-
- def get_basic_auth_token(self):
- """Gets HTTP basic authentication header (string).
-
- :return: The token for basic HTTP authentication.
- """
- username = ""
- if self.username is not None:
- username = self.username
- password = ""
- if self.password is not None:
- password = self.password
- return urllib3.util.make_headers(basic_auth=username + ":" + password).get(
- "authorization"
- )
-
- def auth_settings(self):
- """Gets Auth Settings dict for api client.
-
- :return: The Auth Settings information dict.
- """
- auth = {}
- return auth
-
- def to_debug_report(self):
- """Gets the essential information for debugging.
-
- :return: The report for debugging.
- """
- return (
- "Python SDK Debug Report:\n"
- "OS: {env}\n"
- "Python Version: {pyversion}\n"
- "Version of the API: v0.2\n"
- "SDK Package Version: 1.0.0".format(env=sys.platform, pyversion=sys.version)
- )
-
- def get_host_settings(self):
- """Gets an array of host settings
-
- :return: An array of host settings
- """
- return [
- {
- "url": "",
- "description": "No description provided",
- }
- ]
-
- def get_host_from_settings(self, index, variables=None, servers=None):
- """Gets host URL based on the index and variables
- :param index: array index of the host settings
- :param variables: hash of variable and the corresponding value
- :param servers: an array of host settings or None
- :return: URL based on host settings
- """
- if index is None:
- return self._base_path
-
- variables = {} if variables is None else variables
- servers = self.get_host_settings() if servers is None else servers
-
- try:
- server = servers[index]
- except IndexError:
- raise ValueError(
- "Invalid index {0} when selecting the host settings. "
- "Must be less than {1}".format(index, len(servers))
- )
-
- url = server["url"]
-
- # go through variables and replace placeholders
- for variable_name, variable in server.get("variables", {}).items():
- used_value = variables.get(variable_name, variable["default_value"])
-
- if "enum_values" in variable and used_value not in variable["enum_values"]:
- raise ValueError(
- "The variable `{0}` in the host URL has invalid value "
- "{1}. Must be {2}.".format(
- variable_name, variables[variable_name], variable["enum_values"]
- )
- )
-
- url = url.replace("{" + variable_name + "}", used_value)
-
- return url
-
- @property
- def host(self):
- """Return generated host."""
- return self.get_host_from_settings(
- self.server_index, variables=self.server_variables
- )
-
- @host.setter
- def host(self, value):
- """Fix base path."""
- self._base_path = value
- self.server_index = None
diff --git a/benchmark/agbenchmark/agent_protocol_client/docs/AgentApi.md b/benchmark/agbenchmark/agent_protocol_client/docs/AgentApi.md
deleted file mode 100644
index 7f0be780c..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/docs/AgentApi.md
+++ /dev/null
@@ -1,615 +0,0 @@
-# agbenchmark.agent_protocol_client.AgentApi
-
-All URIs are relative to _http://localhost_
-
-| Method | HTTP request | Description |
-| ---------------------------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------- |
-| [**create_agent_task**](AgentApi.md#create_agent_task) | **POST** /agent/tasks | Creates a task for the agent. |
-| [**download_agent_task_artifact**](AgentApi.md#download_agent_task_artifact) | **GET** /agent/tasks/{task_id}/artifacts/{artifact_id} | Download a specified artifact. |
-| [**execute_agent_task_step**](AgentApi.md#execute_agent_task_step) | **POST** /agent/tasks/{task_id}/steps | Execute a step in the specified agent task. |
-| [**get_agent_task**](AgentApi.md#get_agent_task) | **GET** /agent/tasks/{task_id} | Get details about a specified agent task. |
-| [**get_agent_task_step**](AgentApi.md#get_agent_task_step) | **GET** /agent/tasks/{task_id}/steps/{step_id} | Get details about a specified task step. |
-| [**list_agent_task_artifacts**](AgentApi.md#list_agent_task_artifacts) | **GET** /agent/tasks/{task_id}/artifacts | List all artifacts that have been created for the given task. |
-| [**list_agent_task_steps**](AgentApi.md#list_agent_task_steps) | **GET** /agent/tasks/{task_id}/steps | List all steps for the specified task. |
-| [**list_agent_tasks_ids**](AgentApi.md#list_agent_tasks_ids) | **GET** /agent/tasks | List all tasks that have been created for the agent. |
-| [**upload_agent_task_artifacts**](AgentApi.md#upload_agent_task_artifacts) | **POST** /agent/tasks/{task_id}/artifacts | Upload an artifact for the specified task. |
-
-# **create_agent_task**
-
-> Task create_agent_task(task_request_body=task_request_body)
-
-Creates a task for the agent.
-
-### Example
-
-```python
-import time
-import os
-import agent_protocol_client
-from agbenchmark.agent_protocol_client.models.task import Task
-from agbenchmark.agent_protocol_client.models.task_request_body import TaskRequestBody
-from agbenchmark.agent_protocol_client.rest import ApiException
-from pprint import pprint
-
-# Defining the host is optional and defaults to http://localhost
-# See configuration.py for a list of all supported configuration parameters.
-configuration = agbenchmark.agent_protocol_client.Configuration(
- host = "http://localhost"
-)
-
-
-# Enter a context with an instance of the API client
-async with agbenchmark.agent_protocol_client.ApiClient(configuration) as api_client:
- # Create an instance of the API class
- api_instance = agbenchmark.agent_protocol_client.AgentApi(api_client)
- task_request_body = agbenchmark.agent_protocol_client.TaskRequestBody() # TaskRequestBody | (optional)
-
- try:
- # Creates a task for the agent.
- api_response = await api_instance.create_agent_task(task_request_body=task_request_body)
- print("The response of AgentApi->create_agent_task:\n")
- pprint(api_response)
- except Exception as e:
- print("Exception when calling AgentApi->create_agent_task: %s\n" % e)
-```
-
-### Parameters
-
-| Name | Type | Description | Notes |
-| --------------------- | ----------------------------------------- | ----------- | ---------- |
-| **task_request_body** | [**TaskRequestBody**](TaskRequestBody.md) | | [optional] |
-
-### Return type
-
-[**Task**](Task.md)
-
-### Authorization
-
-No authorization required
-
-### HTTP request headers
-
-- **Content-Type**: application/json
-- **Accept**: application/json
-
-### HTTP response details
-
-| Status code | Description | Response headers |
-| ----------- | ------------------------------------------ | ---------------- |
-| **200** | A new agent task was successfully created. | - |
-| **0** | Internal Server Error | - |
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-
-# **download_agent_task_artifact**
-
-> bytearray download_agent_task_artifact(task_id, artifact_id)
-
-Download a specified artifact.
-
-### Example
-
-```python
-import time
-import os
-import agent_protocol_client
-from agbenchmark.agent_protocol_client.rest import ApiException
-from pprint import pprint
-
-# Defining the host is optional and defaults to http://localhost
-# See configuration.py for a list of all supported configuration parameters.
-configuration = agbenchmark.agent_protocol_client.Configuration(
- host = "http://localhost"
-)
-
-
-# Enter a context with an instance of the API client
-async with agbenchmark.agent_protocol_client.ApiClient(configuration) as api_client:
- # Create an instance of the API class
- api_instance = agbenchmark.agent_protocol_client.AgentApi(api_client)
- task_id = 'task_id_example' # str | ID of the task
- artifact_id = 'artifact_id_example' # str | ID of the artifact
-
- try:
- # Download a specified artifact.
- api_response = await api_instance.download_agent_task_artifact(task_id, artifact_id)
- print("The response of AgentApi->download_agent_task_artifact:\n")
- pprint(api_response)
- except Exception as e:
- print("Exception when calling AgentApi->download_agent_task_artifact: %s\n" % e)
-```
-
-### Parameters
-
-| Name | Type | Description | Notes |
-| --------------- | ------- | ------------------ | ----- |
-| **task_id** | **str** | ID of the task |
-| **artifact_id** | **str** | ID of the artifact |
-
-### Return type
-
-**bytearray**
-
-### Authorization
-
-No authorization required
-
-### HTTP request headers
-
-- **Content-Type**: Not defined
-- **Accept**: application/octet-stream
-
-### HTTP response details
-
-| Status code | Description | Response headers |
-| ----------- | ------------------------------------- | ---------------- |
-| **200** | Returned the content of the artifact. | - |
-| **0** | Internal Server Error | - |
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-
-# **execute_agent_task_step**
-
-> Step execute_agent_task_step(task_id, step_request_body=step_request_body)
-
-Execute a step in the specified agent task.
-
-### Example
-
-```python
-import time
-import os
-import agent_protocol_client
-from agbenchmark.agent_protocol_client.models.step import Step
-from agbenchmark.agent_protocol_client.models.step_request_body import StepRequestBody
-from agbenchmark.agent_protocol_client.rest import ApiException
-from pprint import pprint
-
-# Defining the host is optional and defaults to http://localhost
-# See configuration.py for a list of all supported configuration parameters.
-configuration = agbenchmark.agent_protocol_client.Configuration(
- host = "http://localhost"
-)
-
-
-# Enter a context with an instance of the API client
-async with agbenchmark.agent_protocol_client.ApiClient(configuration) as api_client:
- # Create an instance of the API class
- api_instance = agbenchmark.agent_protocol_client.AgentApi(api_client)
- task_id = 'task_id_example' # str | ID of the task
- step_request_body = agbenchmark.agent_protocol_client.StepRequestBody() # StepRequestBody | (optional)
-
- try:
- # Execute a step in the specified agent task.
- api_response = await api_instance.execute_agent_task_step(task_id, step_request_body=step_request_body)
- print("The response of AgentApi->execute_agent_task_step:\n")
- pprint(api_response)
- except Exception as e:
- print("Exception when calling AgentApi->execute_agent_task_step: %s\n" % e)
-```
-
-### Parameters
-
-| Name | Type | Description | Notes |
-| --------------------- | ----------------------------------------- | -------------- | ---------- |
-| **task_id** | **str** | ID of the task |
-| **step_request_body** | [**StepRequestBody**](StepRequestBody.md) | | [optional] |
-
-### Return type
-
-[**Step**](Step.md)
-
-### Authorization
-
-No authorization required
-
-### HTTP request headers
-
-- **Content-Type**: application/json
-- **Accept**: application/json
-
-### HTTP response details
-
-| Status code | Description | Response headers |
-| ----------- | --------------------------------- | ---------------- |
-| **200** | Executed step for the agent task. | - |
-| **0** | Internal Server Error | - |
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-
-# **get_agent_task**
-
-> Task get_agent_task(task_id)
-
-Get details about a specified agent task.
-
-### Example
-
-```python
-import time
-import os
-import agent_protocol_client
-from agbenchmark.agent_protocol_client.models.task import Task
-from agbenchmark.agent_protocol_client.rest import ApiException
-from pprint import pprint
-
-# Defining the host is optional and defaults to http://localhost
-# See configuration.py for a list of all supported configuration parameters.
-configuration = agbenchmark.agent_protocol_client.Configuration(
- host = "http://localhost"
-)
-
-
-# Enter a context with an instance of the API client
-async with agbenchmark.agent_protocol_client.ApiClient(configuration) as api_client:
- # Create an instance of the API class
- api_instance = agbenchmark.agent_protocol_client.AgentApi(api_client)
- task_id = 'task_id_example' # str | ID of the task
-
- try:
- # Get details about a specified agent task.
- api_response = await api_instance.get_agent_task(task_id)
- print("The response of AgentApi->get_agent_task:\n")
- pprint(api_response)
- except Exception as e:
- print("Exception when calling AgentApi->get_agent_task: %s\n" % e)
-```
-
-### Parameters
-
-| Name | Type | Description | Notes |
-| ----------- | ------- | -------------- | ----- |
-| **task_id** | **str** | ID of the task |
-
-### Return type
-
-[**Task**](Task.md)
-
-### Authorization
-
-No authorization required
-
-### HTTP request headers
-
-- **Content-Type**: Not defined
-- **Accept**: application/json
-
-### HTTP response details
-
-| Status code | Description | Response headers |
-| ----------- | ------------------------------------- | ---------------- |
-| **200** | Returned details about an agent task. | - |
-| **0** | Internal Server Error | - |
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-
-# **get_agent_task_step**
-
-> Step get_agent_task_step(task_id, step_id)
-
-Get details about a specified task step.
-
-### Example
-
-```python
-import time
-import os
-import agent_protocol_client
-from agbenchmark.agent_protocol_client.models.step import Step
-from agbenchmark.agent_protocol_client.rest import ApiException
-from pprint import pprint
-
-# Defining the host is optional and defaults to http://localhost
-# See configuration.py for a list of all supported configuration parameters.
-configuration = agbenchmark.agent_protocol_client.Configuration(
- host = "http://localhost"
-)
-
-
-# Enter a context with an instance of the API client
-async with agbenchmark.agent_protocol_client.ApiClient(configuration) as api_client:
- # Create an instance of the API class
- api_instance = agbenchmark.agent_protocol_client.AgentApi(api_client)
- task_id = 'task_id_example' # str | ID of the task
- step_id = 'step_id_example' # str | ID of the step
-
- try:
- # Get details about a specified task step.
- api_response = await api_instance.get_agent_task_step(task_id, step_id)
- print("The response of AgentApi->get_agent_task_step:\n")
- pprint(api_response)
- except Exception as e:
- print("Exception when calling AgentApi->get_agent_task_step: %s\n" % e)
-```
-
-### Parameters
-
-| Name | Type | Description | Notes |
-| ----------- | ------- | -------------- | ----- |
-| **task_id** | **str** | ID of the task |
-| **step_id** | **str** | ID of the step |
-
-### Return type
-
-[**Step**](Step.md)
-
-### Authorization
-
-No authorization required
-
-### HTTP request headers
-
-- **Content-Type**: Not defined
-- **Accept**: application/json
-
-### HTTP response details
-
-| Status code | Description | Response headers |
-| ----------- | ------------------------------------------ | ---------------- |
-| **200** | Returned details about an agent task step. | - |
-| **0** | Internal Server Error | - |
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-
-# **list_agent_task_artifacts**
-
-> List[Artifact] list_agent_task_artifacts(task_id)
-
-List all artifacts that have been created for the given task.
-
-### Example
-
-```python
-import time
-import os
-import agent_protocol_client
-from agbenchmark.agent_protocol_client.models.artifact import Artifact
-from agbenchmark.agent_protocol_client.rest import ApiException
-from pprint import pprint
-
-# Defining the host is optional and defaults to http://localhost
-# See configuration.py for a list of all supported configuration parameters.
-configuration = agbenchmark.agent_protocol_client.Configuration(
- host = "http://localhost"
-)
-
-
-# Enter a context with an instance of the API client
-async with agbenchmark.agent_protocol_client.ApiClient(configuration) as api_client:
- # Create an instance of the API class
- api_instance = agbenchmark.agent_protocol_client.AgentApi(api_client)
- task_id = 'task_id_example' # str | ID of the task
-
- try:
- # List all artifacts that have been created for the given task.
- api_response = await api_instance.list_agent_task_artifacts(task_id)
- print("The response of AgentApi->list_agent_task_artifacts:\n")
- pprint(api_response)
- except Exception as e:
- print("Exception when calling AgentApi->list_agent_task_artifacts: %s\n" % e)
-```
-
-### Parameters
-
-| Name | Type | Description | Notes |
-| ----------- | ------- | -------------- | ----- |
-| **task_id** | **str** | ID of the task |
-
-### Return type
-
-[**List[Artifact]**](Artifact.md)
-
-### Authorization
-
-No authorization required
-
-### HTTP request headers
-
-- **Content-Type**: Not defined
-- **Accept**: application/json
-
-### HTTP response details
-
-| Status code | Description | Response headers |
-| ----------- | ------------------------------------- | ---------------- |
-| **200** | Returned the content of the artifact. | - |
-| **0** | Internal Server Error | - |
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-
-# **list_agent_task_steps**
-
-> List[str] list_agent_task_steps(task_id)
-
-List all steps for the specified task.
-
-### Example
-
-```python
-import time
-import os
-import agent_protocol_client
-from agbenchmark.agent_protocol_client.rest import ApiException
-from pprint import pprint
-
-# Defining the host is optional and defaults to http://localhost
-# See configuration.py for a list of all supported configuration parameters.
-configuration = agbenchmark.agent_protocol_client.Configuration(
- host = "http://localhost"
-)
-
-
-# Enter a context with an instance of the API client
-async with agbenchmark.agent_protocol_client.ApiClient(configuration) as api_client:
- # Create an instance of the API class
- api_instance = agbenchmark.agent_protocol_client.AgentApi(api_client)
- task_id = 'task_id_example' # str | ID of the task
-
- try:
- # List all steps for the specified task.
- api_response = await api_instance.list_agent_task_steps(task_id)
- print("The response of AgentApi->list_agent_task_steps:\n")
- pprint(api_response)
- except Exception as e:
- print("Exception when calling AgentApi->list_agent_task_steps: %s\n" % e)
-```
-
-### Parameters
-
-| Name | Type | Description | Notes |
-| ----------- | ------- | -------------- | ----- |
-| **task_id** | **str** | ID of the task |
-
-### Return type
-
-**List[str]**
-
-### Authorization
-
-No authorization required
-
-### HTTP request headers
-
-- **Content-Type**: Not defined
-- **Accept**: application/json
-
-### HTTP response details
-
-| Status code | Description | Response headers |
-| ----------- | ------------------------------------------------------------- | ---------------- |
-| **200** | Returned list of agent&#39;s step IDs for the specified task. | - |
-| **0** | Internal Server Error | - |
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-
-# **list_agent_tasks_ids**
-
-> List[str] list_agent_tasks_ids()
-
-List all tasks that have been created for the agent.
-
-### Example
-
-```python
-import time
-import os
-import agent_protocol_client
-from agbenchmark.agent_protocol_client.rest import ApiException
-from pprint import pprint
-
-# Defining the host is optional and defaults to http://localhost
-# See configuration.py for a list of all supported configuration parameters.
-configuration = agbenchmark.agent_protocol_client.Configuration(
- host = "http://localhost"
-)
-
-
-# Enter a context with an instance of the API client
-async with agbenchmark.agent_protocol_client.ApiClient(configuration) as api_client:
- # Create an instance of the API class
- api_instance = agbenchmark.agent_protocol_client.AgentApi(api_client)
-
- try:
- # List all tasks that have been created for the agent.
- api_response = await api_instance.list_agent_tasks_ids()
- print("The response of AgentApi->list_agent_tasks_ids:\n")
- pprint(api_response)
- except Exception as e:
- print("Exception when calling AgentApi->list_agent_tasks_ids: %s\n" % e)
-```
-
-### Parameters
-
-This endpoint does not need any parameter.
-
-### Return type
-
-**List[str]**
-
-### Authorization
-
-No authorization required
-
-### HTTP request headers
-
-- **Content-Type**: Not defined
-- **Accept**: application/json
-
-### HTTP response details
-
-| Status code | Description | Response headers |
-| ----------- | -------------------------------------- | ---------------- |
-| **200** | Returned list of agent&#39;s task IDs. | - |
-| **0** | Internal Server Error | - |
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
-
-# **upload_agent_task_artifacts**
-
-> Artifact upload_agent_task_artifacts(task_id, file, relative_path=relative_path)
-
-Upload an artifact for the specified task.
-
-### Example
-
-```python
-import time
-import os
-import agent_protocol_client
-from agbenchmark.agent_protocol_client.models.artifact import Artifact
-from agbenchmark.agent_protocol_client.rest import ApiException
-from pprint import pprint
-
-# Defining the host is optional and defaults to http://localhost
-# See configuration.py for a list of all supported configuration parameters.
-configuration = agbenchmark.agent_protocol_client.Configuration(
- host = "http://localhost"
-)
-
-
-# Enter a context with an instance of the API client
-async with agbenchmark.agent_protocol_client.ApiClient(configuration) as api_client:
- # Create an instance of the API class
- api_instance = agbenchmark.agent_protocol_client.AgentApi(api_client)
- task_id = 'task_id_example' # str | ID of the task
- file = None # bytearray | File to upload.
- relative_path = 'relative_path_example' # str | Relative path of the artifact in the agent's workspace. (optional)
-
- try:
- # Upload an artifact for the specified task.
- api_response = await api_instance.upload_agent_task_artifacts(task_id, file, relative_path=relative_path)
- print("The response of AgentApi->upload_agent_task_artifacts:\n")
- pprint(api_response)
- except Exception as e:
- print("Exception when calling AgentApi->upload_agent_task_artifacts: %s\n" % e)
-```
-
-### Parameters
-
-| Name | Type | Description | Notes |
-| ----------------- | ------------- | ----------------------------------------------------------- | ---------- |
-| **task_id** | **str** | ID of the task |
-| **file** | **bytearray** | File to upload. |
-| **relative_path** | **str** | Relative path of the artifact in the agent&#39;s workspace. | [optional] |
-
-### Return type
-
-[**Artifact**](Artifact.md)
-
-### Authorization
-
-No authorization required
-
-### HTTP request headers
-
-- **Content-Type**: multipart/form-data
-- **Accept**: application/json
-
-### HTTP response details
-
-| Status code | Description | Response headers |
-| ----------- | ------------------------------------- | ---------------- |
-| **200** | Returned the content of the artifact. | - |
-| **0** | Internal Server Error | - |
-
-[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
diff --git a/benchmark/agbenchmark/agent_protocol_client/exceptions.py b/benchmark/agbenchmark/agent_protocol_client/exceptions.py
deleted file mode 100644
index bd26eac3c..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/exceptions.py
+++ /dev/null
@@ -1,154 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-class OpenApiException(Exception):
- """The base exception class for all OpenAPIExceptions"""
-
-
-class ApiTypeError(OpenApiException, TypeError):
- def __init__(self, msg, path_to_item=None, valid_classes=None, key_type=None):
- """Raises an exception for TypeErrors
-
- Args:
- msg (str): the exception message
-
- Keyword Args:
- path_to_item (list): a list of keys an indices to get to the
- current_item
- None if unset
- valid_classes (tuple): the primitive classes that current item
- should be an instance of
- None if unset
- key_type (bool): False if our value is a value in a dict
- True if it is a key in a dict
- False if our item is an item in a list
- None if unset
- """
- self.path_to_item = path_to_item
- self.valid_classes = valid_classes
- self.key_type = key_type
- full_msg = msg
- if path_to_item:
- full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
- super(ApiTypeError, self).__init__(full_msg)
-
-
-class ApiValueError(OpenApiException, ValueError):
- def __init__(self, msg, path_to_item=None):
- """
- Args:
- msg (str): the exception message
-
- Keyword Args:
- path_to_item (list) the path to the exception in the
- received_data dict. None if unset
- """
-
- self.path_to_item = path_to_item
- full_msg = msg
- if path_to_item:
- full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
- super(ApiValueError, self).__init__(full_msg)
-
-
-class ApiAttributeError(OpenApiException, AttributeError):
- def __init__(self, msg, path_to_item=None):
- """
- Raised when an attribute reference or assignment fails.
-
- Args:
- msg (str): the exception message
-
- Keyword Args:
- path_to_item (None/list) the path to the exception in the
- received_data dict
- """
- self.path_to_item = path_to_item
- full_msg = msg
- if path_to_item:
- full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
- super(ApiAttributeError, self).__init__(full_msg)
-
-
-class ApiKeyError(OpenApiException, KeyError):
- def __init__(self, msg, path_to_item=None):
- """
- Args:
- msg (str): the exception message
-
- Keyword Args:
- path_to_item (None/list) the path to the exception in the
- received_data dict
- """
- self.path_to_item = path_to_item
- full_msg = msg
- if path_to_item:
- full_msg = "{0} at {1}".format(msg, render_path(path_to_item))
- super(ApiKeyError, self).__init__(full_msg)
-
-
-class ApiException(OpenApiException):
- def __init__(self, status=None, reason=None, http_resp=None):
- if http_resp:
- self.status = http_resp.status
- self.reason = http_resp.reason
- self.body = http_resp.data
- self.headers = http_resp.getheaders()
- else:
- self.status = status
- self.reason = reason
- self.body = None
- self.headers = None
-
- def __str__(self):
- """Custom error messages for exception"""
- error_message = "({0})\n" "Reason: {1}\n".format(self.status, self.reason)
- if self.headers:
- error_message += "HTTP response headers: {0}\n".format(self.headers)
-
- if self.body:
- error_message += "HTTP response body: {0}\n".format(self.body)
-
- return error_message
-
-
-class NotFoundException(ApiException):
- def __init__(self, status=None, reason=None, http_resp=None):
- super(NotFoundException, self).__init__(status, reason, http_resp)
-
-
-class UnauthorizedException(ApiException):
- def __init__(self, status=None, reason=None, http_resp=None):
- super(UnauthorizedException, self).__init__(status, reason, http_resp)
-
-
-class ForbiddenException(ApiException):
- def __init__(self, status=None, reason=None, http_resp=None):
- super(ForbiddenException, self).__init__(status, reason, http_resp)
-
-
-class ServiceException(ApiException):
- def __init__(self, status=None, reason=None, http_resp=None):
- super(ServiceException, self).__init__(status, reason, http_resp)
-
-
-def render_path(path_to_item):
- """Returns a string representation of a path"""
- result = ""
- for pth in path_to_item:
- if isinstance(pth, int):
- result += "[{0}]".format(pth)
- else:
- result += "['{0}']".format(pth)
- return result
diff --git a/benchmark/agbenchmark/agent_protocol_client/models/__init__.py b/benchmark/agbenchmark/agent_protocol_client/models/__init__.py
deleted file mode 100644
index c7bd82dcd..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/models/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# coding: utf-8
-
-# flake8: noqa
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-# import models into model package
-from agbenchmark.agent_protocol_client.models.artifact import Artifact
-from agbenchmark.agent_protocol_client.models.artifacts import Artifacts
-from agbenchmark.agent_protocol_client.models.pagination import Pagination
-from agbenchmark.agent_protocol_client.models.step import Step
-from agbenchmark.agent_protocol_client.models.step_all_of import StepAllOf
-from agbenchmark.agent_protocol_client.models.step_request_body import StepRequestBody
-from agbenchmark.agent_protocol_client.models.task import Task
-from agbenchmark.agent_protocol_client.models.task_all_of import TaskAllOf
-from agbenchmark.agent_protocol_client.models.task_request_body import TaskRequestBody
diff --git a/benchmark/agbenchmark/agent_protocol_client/models/artifact.py b/benchmark/agbenchmark/agent_protocol_client/models/artifact.py
deleted file mode 100644
index d2e7c101b..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/models/artifact.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# coding: utf-8
-
-
-from __future__ import annotations
-
-import json
-import pprint
-import re # noqa: F401
-from typing import Optional
-
-from pydantic import BaseModel, Field, StrictStr
-
-
-class Artifact(BaseModel):
- """
- Artifact that the task has produced.
- """
-
- artifact_id: StrictStr = Field(..., description="ID of the artifact.")
- file_name: StrictStr = Field(..., description="Filename of the artifact.")
- relative_path: Optional[StrictStr] = Field(
- None, description="Relative path of the artifact in the agent's workspace."
- )
- __properties = ["artifact_id", "file_name", "relative_path"]
- created_at: StrictStr = Field(..., description="Creation date of the artifact.")
- # modified_at: StrictStr = Field(..., description="Modification date of the artifact.")
- agent_created: bool = Field(..., description="True if created by the agent")
-
- class Config:
- """Pydantic configuration"""
-
- allow_population_by_field_name = True
- validate_assignment = True
-
- def to_str(self) -> str:
- """Returns the string representation of the model using alias"""
- return pprint.pformat(self.dict(by_alias=True))
-
- def to_json(self) -> str:
- """Returns the JSON representation of the model using alias"""
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_json(cls, json_str: str) -> Artifact:
- """Create an instance of Artifact from a JSON string"""
- return cls.from_dict(json.loads(json_str))
-
- def to_dict(self):
- """Returns the dictionary representation of the model using alias"""
- _dict = self.dict(by_alias=True, exclude={}, exclude_none=True)
- return _dict
-
- @classmethod
- def from_dict(cls, obj: dict) -> Artifact:
- """Create an instance of Artifact from a dict"""
- if obj is None:
- return None
-
- if not isinstance(obj, dict):
- return Artifact.parse_obj(obj)
-
- _obj = Artifact.parse_obj(
- {
- "artifact_id": obj.get("artifact_id"),
- "file_name": obj.get("file_name"),
- "relative_path": obj.get("relative_path"),
- "created_at": obj.get("created_at"),
- "modified_at": obj.get("modified_at"),
- "agent_created": obj.get("agent_created"),
- }
- )
- return _obj
diff --git a/benchmark/agbenchmark/agent_protocol_client/models/artifacts.py b/benchmark/agbenchmark/agent_protocol_client/models/artifacts.py
deleted file mode 100644
index 1d61a0558..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/models/artifacts.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-from __future__ import annotations
-
-import json
-import pprint
-import re # noqa: F401
-
-from pydantic import BaseModel
-
-from agbenchmark.agent_protocol_client.models.artifact import Artifact
-from agbenchmark.agent_protocol_client.models.pagination import Pagination
-
-
-class Artifacts(BaseModel):
- """
- Artifacts that the task has produced.
- """
-
- artifacts: list[Artifact]
- pagination: Pagination
-
- class Config:
- """Pydantic configuration"""
-
- allow_population_by_field_name = True
- validate_assignment = True
-
- def to_str(self) -> str:
- """Returns the string representation of the model using alias"""
- return pprint.pformat(self.dict(by_alias=True))
-
- def to_json(self) -> str:
- """Returns the JSON representation of the model using alias"""
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_json(cls, json_str: str) -> Artifacts:
- """Create an instance of Artifacts from a JSON string"""
- return cls.from_dict(json.loads(json_str))
-
- def to_dict(self):
- """Returns the dictionary representation of the model using alias"""
- _dict = self.dict(by_alias=True, exclude={}, exclude_none=True)
- return _dict
-
- @classmethod
- def from_dict(cls, obj: dict) -> Artifacts:
- """Create an instance of Artifacts from a dict"""
- if obj is None:
- return None
-
- if not isinstance(obj, dict):
- return Artifacts.parse_obj(obj)
-
- _obj = Artifacts.parse_obj(
- {
- "artifacts": obj.get("artifacts"),
- "pagination": obj.get("pagination"),
- }
- )
- return _obj
-
-
-Artifacts.update_forward_refs()
diff --git a/benchmark/agbenchmark/agent_protocol_client/models/pagination.py b/benchmark/agbenchmark/agent_protocol_client/models/pagination.py
deleted file mode 100644
index 433de1f28..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/models/pagination.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-from __future__ import annotations
-
-import json
-import pprint
-import re # noqa: F401
-
-from pydantic import BaseModel
-
-
-class Pagination(BaseModel):
- """
- Pagination that the task has produced.
- """
-
- total_items: int
- total_pages: int
- current_page: int
- page_size: int
-
- class Config:
- """Pydantic configuration"""
-
- allow_population_by_field_name = True
- validate_assignment = True
-
- def to_str(self) -> str:
- """Returns the string representation of the model using alias"""
- return pprint.pformat(self.dict(by_alias=True))
-
- def to_json(self) -> str:
- """Returns the JSON representation of the model using alias"""
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_json(cls, json_str: str) -> Pagination:
- """Create an instance of Pagination from a JSON string"""
- return cls.from_dict(json.loads(json_str))
-
- def to_dict(self):
- """Returns the dictionary representation of the model using alias"""
- _dict = self.dict(by_alias=True, exclude={}, exclude_none=True)
- return _dict
-
- @classmethod
- def from_dict(cls, obj: dict) -> Pagination:
- """Create an instance of Pagination from a dict"""
- if obj is None:
- return None
-
- if not isinstance(obj, dict):
- return Pagination.parse_obj(obj)
-
- _obj = Pagination.parse_obj(
- {
- "total_items": obj.get("total_items"),
- "total_pages": obj.get("total_pages"),
- "current_page": obj.get("current_page"),
- "page_size": obj.get("page_size"),
- }
- )
- return _obj
diff --git a/benchmark/agbenchmark/agent_protocol_client/models/step.py b/benchmark/agbenchmark/agent_protocol_client/models/step.py
deleted file mode 100644
index befef1abc..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/models/step.py
+++ /dev/null
@@ -1,146 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-from __future__ import annotations
-
-import json
-import pprint
-import re # noqa: F401
-from typing import Any, Optional
-
-from pydantic import BaseModel, Field, StrictBool, StrictStr, conlist, validator
-
-from agbenchmark.agent_protocol_client.models.artifact import Artifact
-
-
-class Step(BaseModel):
- """
- Step
- """
-
- input: Optional[StrictStr] = Field(None, description="Input prompt for the step.")
- additional_input: Optional[Any] = Field(
- None, description="Input parameters for the task step. Any value is allowed."
- )
- task_id: StrictStr = Field(
- ..., description="The ID of the task this step belongs to."
- )
- step_id: StrictStr = Field(..., description="The ID of the task step.")
- name: Optional[StrictStr] = Field(None, description="The name of the task step.")
- status: StrictStr = Field(..., description="The status of the task step.")
- output: Optional[StrictStr] = Field(None, description="Output of the task step.")
- additional_output: Optional[Any] = Field(
- None,
- description="Output that the task step has produced. Any value is allowed.",
- )
- artifacts: conlist(Artifact) = Field(
- ..., description="A list of artifacts that the step has produced."
- )
- is_last: Optional[StrictBool] = Field(
- False, description="Whether this is the last step in the task."
- )
- __properties = [
- "input",
- "additional_input",
- "task_id",
- "step_id",
- "name",
- "status",
- "output",
- "additional_output",
- "artifacts",
- "is_last",
- ]
-
- @validator("status")
- def status_validate_enum(cls, value):
- """Validates the enum"""
- if value not in ("created", "completed"):
- raise ValueError("must be one of enum values ('created', 'completed')")
- return value
-
- class Config:
- """Pydantic configuration"""
-
- allow_population_by_field_name = True
- validate_assignment = True
-
- def to_str(self) -> str:
- """Returns the string representation of the model using alias"""
- return pprint.pformat(self.dict(by_alias=True))
-
- def to_json(self) -> str:
- """Returns the JSON representation of the model using alias"""
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_json(cls, json_str: str) -> Step:
- """Create an instance of Step from a JSON string"""
- return cls.from_dict(json.loads(json_str))
-
- def to_dict(self):
- """Returns the dictionary representation of the model using alias"""
- _dict = self.dict(by_alias=True, exclude={}, exclude_none=True)
- # override the default output from pydantic by calling `to_dict()` of each item in artifacts (list)
- _items = []
- if self.artifacts:
- for _item in self.artifacts:
- if _item:
- _items.append(_item.to_dict())
- _dict["artifacts"] = _items
- # set to None if additional_input (nullable) is None
- # and __fields_set__ contains the field
- if self.additional_input is None and "additional_input" in self.__fields_set__:
- _dict["additional_input"] = None
-
- # set to None if additional_output (nullable) is None
- # and __fields_set__ contains the field
- if (
- self.additional_output is None
- and "additional_output" in self.__fields_set__
- ):
- _dict["additional_output"] = None
-
- return _dict
-
- @classmethod
- def from_dict(cls, obj: dict) -> Step:
- """Create an instance of Step from a dict"""
- if obj is None:
- return None
-
- if not isinstance(obj, dict):
- return Step.parse_obj(obj)
-
- _obj = Step.parse_obj(
- {
- "input": obj.get("input"),
- "additional_input": obj.get("additional_input"),
- "task_id": obj.get("task_id"),
- "step_id": obj.get("step_id"),
- "name": obj.get("name"),
- "status": obj.get("status"),
- "output": obj.get("output"),
- "additional_output": obj.get("additional_output"),
- "artifacts": [
- Artifact.from_dict(_item) for _item in obj.get("artifacts")
- ]
- if obj.get("artifacts") is not None
- else None,
- "is_last": obj.get("is_last")
- if obj.get("is_last") is not None
- else False,
- }
- )
- return _obj
diff --git a/benchmark/agbenchmark/agent_protocol_client/models/step_all_of.py b/benchmark/agbenchmark/agent_protocol_client/models/step_all_of.py
deleted file mode 100644
index 8770f3b31..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/models/step_all_of.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-from __future__ import annotations
-
-import json
-import pprint
-import re # noqa: F401
-from typing import Any, Optional
-
-from pydantic import BaseModel, Field, StrictBool, StrictStr, conlist, validator
-
-from agbenchmark.agent_protocol_client.models.artifact import Artifact
-
-
-class StepAllOf(BaseModel):
- """
- StepAllOf
- """
-
- task_id: StrictStr = Field(
- ..., description="The ID of the task this step belongs to."
- )
- step_id: StrictStr = Field(..., description="The ID of the task step.")
- name: Optional[StrictStr] = Field(None, description="The name of the task step.")
- status: StrictStr = Field(..., description="The status of the task step.")
- output: Optional[StrictStr] = Field(None, description="Output of the task step.")
- additional_output: Optional[Any] = Field(
- None,
- description="Output that the task step has produced. Any value is allowed.",
- )
- artifacts: conlist(Artifact) = Field(
- ..., description="A list of artifacts that the step has produced."
- )
- is_last: Optional[StrictBool] = Field(
- False, description="Whether this is the last step in the task."
- )
- __properties = [
- "task_id",
- "step_id",
- "name",
- "status",
- "output",
- "additional_output",
- "artifacts",
- "is_last",
- ]
-
- @validator("status")
- def status_validate_enum(cls, value):
- """Validates the enum"""
- if value not in ("created", "completed"):
- raise ValueError("must be one of enum values ('created', 'completed')")
- return value
-
- class Config:
- """Pydantic configuration"""
-
- allow_population_by_field_name = True
- validate_assignment = True
-
- def to_str(self) -> str:
- """Returns the string representation of the model using alias"""
- return pprint.pformat(self.dict(by_alias=True))
-
- def to_json(self) -> str:
- """Returns the JSON representation of the model using alias"""
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_json(cls, json_str: str) -> StepAllOf:
- """Create an instance of StepAllOf from a JSON string"""
- return cls.from_dict(json.loads(json_str))
-
- def to_dict(self):
- """Returns the dictionary representation of the model using alias"""
- _dict = self.dict(by_alias=True, exclude={}, exclude_none=True)
- # override the default output from pydantic by calling `to_dict()` of each item in artifacts (list)
- _items = []
- if self.artifacts:
- for _item in self.artifacts:
- if _item:
- _items.append(_item.to_dict())
- _dict["artifacts"] = _items
- # set to None if additional_output (nullable) is None
- # and __fields_set__ contains the field
- if (
- self.additional_output is None
- and "additional_output" in self.__fields_set__
- ):
- _dict["additional_output"] = None
-
- return _dict
-
- @classmethod
- def from_dict(cls, obj: dict) -> StepAllOf:
- """Create an instance of StepAllOf from a dict"""
- if obj is None:
- return None
-
- if not isinstance(obj, dict):
- return StepAllOf.parse_obj(obj)
-
- _obj = StepAllOf.parse_obj(
- {
- "task_id": obj.get("task_id"),
- "step_id": obj.get("step_id"),
- "name": obj.get("name"),
- "status": obj.get("status"),
- "output": obj.get("output"),
- "additional_output": obj.get("additional_output"),
- "artifacts": [
- Artifact.from_dict(_item) for _item in obj.get("artifacts")
- ]
- if obj.get("artifacts") is not None
- else None,
- "is_last": obj.get("is_last")
- if obj.get("is_last") is not None
- else False,
- }
- )
- return _obj
diff --git a/benchmark/agbenchmark/agent_protocol_client/models/step_request_body.py b/benchmark/agbenchmark/agent_protocol_client/models/step_request_body.py
deleted file mode 100644
index 47d642cfb..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/models/step_request_body.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-from __future__ import annotations
-
-import json
-import pprint
-import re # noqa: F401
-from typing import Any, Optional
-
-from pydantic import BaseModel, Field, StrictStr
-
-
-class StepRequestBody(BaseModel):
- """
- Body of the task request.
- """
-
- input: Optional[StrictStr] = Field(None, description="Input prompt for the step.")
- additional_input: Optional[Any] = Field(
- None, description="Input parameters for the task step. Any value is allowed."
- )
- __properties = ["input", "additional_input"]
-
- class Config:
- """Pydantic configuration"""
-
- allow_population_by_field_name = True
- validate_assignment = True
-
- def to_str(self) -> str:
- """Returns the string representation of the model using alias"""
- return pprint.pformat(self.dict(by_alias=True))
-
- def to_json(self) -> str:
- """Returns the JSON representation of the model using alias"""
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_json(cls, json_str: str) -> StepRequestBody:
- """Create an instance of StepRequestBody from a JSON string"""
- return cls.from_dict(json.loads(json_str))
-
- def to_dict(self):
- """Returns the dictionary representation of the model using alias"""
- _dict = self.dict(by_alias=True, exclude={}, exclude_none=True)
- # set to None if additional_input (nullable) is None
- # and __fields_set__ contains the field
- if self.additional_input is None and "additional_input" in self.__fields_set__:
- _dict["additional_input"] = None
-
- return _dict
-
- @classmethod
- def from_dict(cls, obj: dict) -> StepRequestBody:
- """Create an instance of StepRequestBody from a dict"""
- if obj is None:
- return None
-
- if not isinstance(obj, dict):
- return StepRequestBody.parse_obj(obj)
-
- _obj = StepRequestBody.parse_obj(
- {"input": obj.get("input"), "additional_input": obj.get("additional_input")}
- )
- return _obj
diff --git a/benchmark/agbenchmark/agent_protocol_client/models/step_result.py b/benchmark/agbenchmark/agent_protocol_client/models/step_result.py
deleted file mode 100644
index 99bf8f820..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/models/step_result.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v1
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-from __future__ import annotations
-
-import json
-import pprint
-import re # noqa: F401
-from typing import Any, Optional
-
-from pydantic import BaseModel, Field, StrictBool, conlist
-
-
-class StepResult(BaseModel):
- """
- Result of the task step.
- """
-
- output: Optional[Any] = Field(
- None,
- description="Output that the task step has produced. Any value is allowed.",
- )
- artifacts: conlist(Any) = Field(
- ..., description="A list of artifacts that the step has produced."
- )
- is_last: Optional[StrictBool] = Field(
- False, description="Whether this is the last step in the task."
- )
- __properties = ["output", "artifacts", "is_last"]
-
- class Config:
- """Pydantic configuration"""
-
- allow_population_by_field_name = True
- validate_assignment = True
-
- def to_str(self) -> str:
- """Returns the string representation of the model using alias"""
- return pprint.pformat(self.dict(by_alias=True))
-
- def to_json(self) -> str:
- """Returns the JSON representation of the model using alias"""
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_json(cls, json_str: str) -> StepResult:
- """Create an instance of StepResult from a JSON string"""
- return cls.from_dict(json.loads(json_str))
-
- def to_dict(self):
- """Returns the dictionary representation of the model using alias"""
- _dict = self.dict(by_alias=True, exclude={}, exclude_none=True)
- # set to None if output (nullable) is None
- # and __fields_set__ contains the field
- if self.output is None and "output" in self.__fields_set__:
- _dict["output"] = None
-
- return _dict
-
- @classmethod
- def from_dict(cls, obj: dict) -> StepResult:
- """Create an instance of StepResult from a dict"""
- if obj is None:
- return None
-
- if not isinstance(obj, dict):
- return StepResult.parse_obj(obj)
-
- _obj = StepResult.parse_obj(
- {
- "output": obj.get("output"),
- "artifacts": obj.get("artifacts"),
- "is_last": obj.get("is_last")
- if obj.get("is_last") is not None
- else False,
- }
- )
- return _obj
diff --git a/benchmark/agbenchmark/agent_protocol_client/models/task.py b/benchmark/agbenchmark/agent_protocol_client/models/task.py
deleted file mode 100644
index 90329f25f..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/models/task.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-from __future__ import annotations
-
-import json
-import pprint
-import re # noqa: F401
-from typing import Any, Optional
-
-from pydantic import BaseModel, Field, StrictStr, conlist
-
-from agbenchmark.agent_protocol_client.models.artifact import Artifact
-
-
-class Task(BaseModel):
- """
- Task
- """
-
- input: Optional[StrictStr] = Field(None, description="Input prompt for the task.")
- additional_input: Optional[Any] = Field(
- None, description="Input parameters for the task. Any value is allowed."
- )
- task_id: StrictStr = Field(..., description="The ID of the task.")
- artifacts: conlist(Artifact) = Field(
- ..., description="A list of artifacts that the task has produced."
- )
- __properties = ["input", "additional_input", "task_id", "artifacts"]
-
- class Config:
- """Pydantic configuration"""
-
- allow_population_by_field_name = True
- validate_assignment = True
-
- def to_str(self) -> str:
- """Returns the string representation of the model using alias"""
- return pprint.pformat(self.dict(by_alias=True))
-
- def to_json(self) -> str:
- """Returns the JSON representation of the model using alias"""
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_json(cls, json_str: str) -> Task:
- """Create an instance of Task from a JSON string"""
- return cls.from_dict(json.loads(json_str))
-
- def to_dict(self):
- """Returns the dictionary representation of the model using alias"""
- _dict = self.dict(by_alias=True, exclude={}, exclude_none=True)
- # override the default output from pydantic by calling `to_dict()` of each item in artifacts (list)
- _items = []
- if self.artifacts:
- for _item in self.artifacts:
- if _item:
- _items.append(_item.to_dict())
- _dict["artifacts"] = _items
- # set to None if additional_input (nullable) is None
- # and __fields_set__ contains the field
- if self.additional_input is None and "additional_input" in self.__fields_set__:
- _dict["additional_input"] = None
-
- return _dict
-
- @classmethod
- def from_dict(cls, obj: dict) -> Task:
- """Create an instance of Task from a dict"""
- if obj is None:
- return None
-
- if not isinstance(obj, dict):
- return Task.parse_obj(obj)
-
- _obj = Task.parse_obj(
- {
- "input": obj.get("input"),
- "additional_input": obj.get("additional_input"),
- "task_id": obj.get("task_id"),
- "artifacts": [
- Artifact.from_dict(_item) for _item in obj.get("artifacts")
- ]
- if obj.get("artifacts") is not None
- else None,
- }
- )
- return _obj
diff --git a/benchmark/agbenchmark/agent_protocol_client/models/task_all_of.py b/benchmark/agbenchmark/agent_protocol_client/models/task_all_of.py
deleted file mode 100644
index 710377de6..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/models/task_all_of.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-from __future__ import annotations
-
-import json
-import pprint
-import re # noqa: F401
-
-from pydantic import BaseModel, Field, StrictStr, conlist
-
-from agbenchmark.agent_protocol_client.models.artifact import Artifact
-
-
-class TaskAllOf(BaseModel):
- """
- Definition of an agent task.
- """
-
- task_id: StrictStr = Field(..., description="The ID of the task.")
- artifacts: conlist(Artifact) = Field(
- ..., description="A list of artifacts that the task has produced."
- )
- __properties = ["task_id", "artifacts"]
-
- class Config:
- """Pydantic configuration"""
-
- allow_population_by_field_name = True
- validate_assignment = True
-
- def to_str(self) -> str:
- """Returns the string representation of the model using alias"""
- return pprint.pformat(self.dict(by_alias=True))
-
- def to_json(self) -> str:
- """Returns the JSON representation of the model using alias"""
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_json(cls, json_str: str) -> TaskAllOf:
- """Create an instance of TaskAllOf from a JSON string"""
- return cls.from_dict(json.loads(json_str))
-
- def to_dict(self):
- """Returns the dictionary representation of the model using alias"""
- _dict = self.dict(by_alias=True, exclude={}, exclude_none=True)
- # override the default output from pydantic by calling `to_dict()` of each item in artifacts (list)
- _items = []
- if self.artifacts:
- for _item in self.artifacts:
- if _item:
- _items.append(_item.to_dict())
- _dict["artifacts"] = _items
- return _dict
-
- @classmethod
- def from_dict(cls, obj: dict) -> TaskAllOf:
- """Create an instance of TaskAllOf from a dict"""
- if obj is None:
- return None
-
- if not isinstance(obj, dict):
- return TaskAllOf.parse_obj(obj)
-
- _obj = TaskAllOf.parse_obj(
- {
- "task_id": obj.get("task_id"),
- "artifacts": [
- Artifact.from_dict(_item) for _item in obj.get("artifacts")
- ]
- if obj.get("artifacts") is not None
- else None,
- }
- )
- return _obj
diff --git a/benchmark/agbenchmark/agent_protocol_client/models/task_request_body.py b/benchmark/agbenchmark/agent_protocol_client/models/task_request_body.py
deleted file mode 100644
index 40a5d4ecb..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/models/task_request_body.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-from __future__ import annotations
-
-import json
-import pprint
-import re # noqa: F401
-from typing import Any, Optional
-
-from pydantic import BaseModel, Field, StrictStr
-
-
-class TaskRequestBody(BaseModel):
- """
- Body of the task request.
- """
-
- input: Optional[StrictStr] = Field(None, description="Input prompt for the task.")
- additional_input: Optional[Any] = Field(
- None, description="Input parameters for the task. Any value is allowed."
- )
- __properties = ["input", "additional_input"]
-
- class Config:
- """Pydantic configuration"""
-
- allow_population_by_field_name = True
- validate_assignment = True
-
- def to_str(self) -> str:
- """Returns the string representation of the model using alias"""
- return pprint.pformat(self.dict(by_alias=True))
-
- def to_json(self) -> str:
- """Returns the JSON representation of the model using alias"""
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_json(cls, json_str: str) -> TaskRequestBody:
- """Create an instance of TaskRequestBody from a JSON string"""
- return cls.from_dict(json.loads(json_str))
-
- def to_dict(self):
- """Returns the dictionary representation of the model using alias"""
- _dict = self.dict(by_alias=True, exclude={}, exclude_none=True)
- # set to None if additional_input (nullable) is None
- # and __fields_set__ contains the field
- if self.additional_input is None and "additional_input" in self.__fields_set__:
- _dict["additional_input"] = None
-
- return _dict
-
- @classmethod
- def from_dict(cls, obj: dict) -> TaskRequestBody:
- """Create an instance of TaskRequestBody from a dict"""
- if obj is None:
- return None
-
- if not isinstance(obj, dict):
- return TaskRequestBody.parse_obj(obj)
-
- _obj = TaskRequestBody.parse_obj(
- {"input": obj.get("input"), "additional_input": obj.get("additional_input")}
- )
- return _obj
diff --git a/benchmark/agbenchmark/agent_protocol_client/rest.py b/benchmark/agbenchmark/agent_protocol_client/rest.py
deleted file mode 100644
index 7c29a9598..000000000
--- a/benchmark/agbenchmark/agent_protocol_client/rest.py
+++ /dev/null
@@ -1,311 +0,0 @@
-# coding: utf-8
-
-"""
- Agent Communication Protocol
-
- Specification of the API protocol for communication with an agent. # noqa: E501
-
- The version of the OpenAPI document: v0.2
- Generated by OpenAPI Generator (https://openapi-generator.tech)
-
- Do not edit the class manually.
-"""
-
-
-import io
-import json
-import logging
-import re
-import ssl
-from urllib.parse import urlencode
-
-import aiohttp
-
-from agbenchmark.agent_protocol_client.exceptions import ApiException, ApiValueError
-
-logger = logging.getLogger(__name__)
-
-
-class RESTResponse(io.IOBase):
- def __init__(self, resp, data):
- self.aiohttp_response = resp
- self.status = resp.status
- self.reason = resp.reason
- self.data = data
-
- def getheaders(self):
- """Returns a CIMultiDictProxy of the response headers."""
- return self.aiohttp_response.headers
-
- def getheader(self, name, default=None):
- """Returns a given response header."""
- return self.aiohttp_response.headers.get(name, default)
-
-
-class RESTClientObject(object):
- def __init__(self, configuration, pools_size=4, maxsize=None):
- # maxsize is number of requests to host that are allowed in parallel
- if maxsize is None:
- maxsize = configuration.connection_pool_maxsize
-
- ssl_context = ssl.create_default_context(cafile=configuration.ssl_ca_cert)
- if configuration.cert_file:
- ssl_context.load_cert_chain(
- configuration.cert_file, keyfile=configuration.key_file
- )
-
- if not configuration.verify_ssl:
- ssl_context.check_hostname = False
- ssl_context.verify_mode = ssl.CERT_NONE
-
- connector = aiohttp.TCPConnector(limit=maxsize, ssl=ssl_context)
-
- self.proxy = configuration.proxy
- self.proxy_headers = configuration.proxy_headers
-
- # https pool manager
- self.pool_manager = aiohttp.ClientSession(connector=connector, trust_env=True)
-
- async def close(self):
- await self.pool_manager.close()
-
- async def request(
- self,
- method,
- url,
- query_params=None,
- headers=None,
- body=None,
- post_params=None,
- _preload_content=True,
- _request_timeout=None,
- ):
- """Execute request
-
- :param method: http request method
- :param url: http request url
- :param query_params: query parameters in the url
- :param headers: http request headers
- :param body: request json body, for `application/json`
- :param post_params: request post parameters,
- `application/x-www-form-urlencoded`
- and `multipart/form-data`
- :param _preload_content: this is a non-applicable field for
- the AiohttpClient.
- :param _request_timeout: timeout setting for this request. If one
- number provided, it will be total request
- timeout. It can also be a pair (tuple) of
- (connection, read) timeouts.
- """
- method = method.upper()
- assert method in ["GET", "HEAD", "DELETE", "POST", "PUT", "PATCH", "OPTIONS"]
-
- if post_params and body:
- raise ApiValueError(
- "body parameter cannot be used with post_params parameter."
- )
-
- post_params = post_params or {}
- headers = headers or {}
- # url already contains the URL query string
- # so reset query_params to empty dict
- query_params = {}
- timeout = _request_timeout or 5 * 60
-
- if "Content-Type" not in headers:
- headers["Content-Type"] = "application/json"
-
- args = {"method": method, "url": url, "timeout": timeout, "headers": headers}
-
- if self.proxy:
- args["proxy"] = self.proxy
- if self.proxy_headers:
- args["proxy_headers"] = self.proxy_headers
-
- if query_params:
- args["url"] += "?" + urlencode(query_params)
-
- # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
- if method in ["POST", "PUT", "PATCH", "OPTIONS", "DELETE"]:
- if re.search("json", headers["Content-Type"], re.IGNORECASE):
- if body is not None:
- body = json.dumps(body)
- args["data"] = body
- elif (
- headers["Content-Type"] == "application/x-www-form-urlencoded"
- ): # noqa: E501
- args["data"] = aiohttp.FormData(post_params)
- elif headers["Content-Type"] == "multipart/form-data":
- # must del headers['Content-Type'], or the correct
- # Content-Type which generated by aiohttp
- del headers["Content-Type"]
- data = aiohttp.FormData()
- for param in post_params:
- k, v = param
- if isinstance(v, tuple) and len(v) == 3:
- data.add_field(k, value=v[1], filename=v[0], content_type=v[2])
- else:
- data.add_field(k, v)
- args["data"] = data
-
- # Pass a `bytes` parameter directly in the body to support
- # other content types than Json when `body` argument is provided
- # in serialized form
- elif isinstance(body, bytes):
- args["data"] = body
- else:
- # Cannot generate the request from given parameters
- msg = """Cannot prepare a request message for provided
- arguments. Please check that your arguments match
- declared content type."""
- raise ApiException(status=0, reason=msg)
-
- r = await self.pool_manager.request(**args)
- if _preload_content:
- data = await r.read()
- r = RESTResponse(r, data)
-
- # log response body
- logger.debug("response body: %s", r.data)
-
- if not 200 <= r.status <= 299:
- raise ApiException(http_resp=r)
-
- return r
-
- async def get_request(
- self,
- url,
- headers=None,
- query_params=None,
- _preload_content=True,
- _request_timeout=None,
- ):
- return await self.request(
- "GET",
- url,
- headers=headers,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- query_params=query_params,
- )
-
- async def head_request(
- self,
- url,
- headers=None,
- query_params=None,
- _preload_content=True,
- _request_timeout=None,
- ):
- return await self.request(
- "HEAD",
- url,
- headers=headers,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- query_params=query_params,
- )
-
- async def options_request(
- self,
- url,
- headers=None,
- query_params=None,
- post_params=None,
- body=None,
- _preload_content=True,
- _request_timeout=None,
- ):
- return await self.request(
- "OPTIONS",
- url,
- headers=headers,
- query_params=query_params,
- post_params=post_params,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- body=body,
- )
-
- async def delete_request(
- self,
- url,
- headers=None,
- query_params=None,
- body=None,
- _preload_content=True,
- _request_timeout=None,
- ):
- return await self.request(
- "DELETE",
- url,
- headers=headers,
- query_params=query_params,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- body=body,
- )
-
- async def post_request(
- self,
- url,
- headers=None,
- query_params=None,
- post_params=None,
- body=None,
- _preload_content=True,
- _request_timeout=None,
- ):
- return await self.request(
- "POST",
- url,
- headers=headers,
- query_params=query_params,
- post_params=post_params,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- body=body,
- )
-
- async def put_request(
- self,
- url,
- headers=None,
- query_params=None,
- post_params=None,
- body=None,
- _preload_content=True,
- _request_timeout=None,
- ):
- return await self.request(
- "PUT",
- url,
- headers=headers,
- query_params=query_params,
- post_params=post_params,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- body=body,
- )
-
- async def patch_request(
- self,
- url,
- headers=None,
- query_params=None,
- post_params=None,
- body=None,
- _preload_content=True,
- _request_timeout=None,
- ):
- return await self.request(
- "PATCH",
- url,
- headers=headers,
- query_params=query_params,
- post_params=post_params,
- _preload_content=_preload_content,
- _request_timeout=_request_timeout,
- body=body,
- )
diff --git a/benchmark/agbenchmark/app.py b/benchmark/agbenchmark/app.py
index ad14cb692..40fee14b6 100644
--- a/benchmark/agbenchmark/app.py
+++ b/benchmark/agbenchmark/app.py
@@ -1,78 +1,81 @@
import datetime
+import glob
+import json
+import logging
+import sys
+import time
import uuid
-from collections import defaultdict, deque
+from collections import deque
+from multiprocessing import Process
from pathlib import Path
+from typing import Optional
import httpx
-
-from agbenchmark.agent_protocol_client import (
- AgentApi,
- ApiClient,
- ApiException,
- Configuration,
+import psutil
+from agent_protocol_client import AgentApi, ApiClient, ApiException, Configuration
+from agent_protocol_client.models import Task, TaskRequestBody
+from fastapi import APIRouter, FastAPI, HTTPException, Request, Response
+from fastapi.middleware.cors import CORSMiddleware
+from pydantic import BaseModel, Extra, ValidationError
+
+from agbenchmark.challenges import ChallengeInfo
+from agbenchmark.config import AgentBenchmarkConfig
+from agbenchmark.reports.processing.report_types_v2 import (
+ BenchmarkRun,
+ Metrics,
+ RepositoryInfo,
+ RunDetails,
+ TaskInfo,
)
-from agbenchmark.reports.processing.report_types_v2 import BenchmarkRun
from agbenchmark.schema import TaskEvalRequestBody
from agbenchmark.utils.utils import write_pretty_json
-configuration = Configuration(host="http://localhost:8000" + "/ap/v1")
-
-import json
-import os
-import sys
-from typing import Any, Optional
-
-import psutil
-from fastapi import APIRouter, FastAPI
-from fastapi import (
- HTTPException as FastAPIHTTPException, # Import HTTPException from FastAPI
-)
-from fastapi import Request, Response
-from fastapi.middleware.cors import CORSMiddleware
-
-from agbenchmark.execute_sub_process import execute_subprocess
-from agbenchmark.schema import Task, TaskRequestBody
-
-sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-from fastapi import FastAPI
-from pydantic import BaseModel, Extra
-
-router = APIRouter()
-import glob
-
-# Change the current working directory to the benchmark path
-# home_path = find_absolute_benchmark_path()
-# os.chdir(home_path)
+sys.path.append(str(Path(__file__).parent.parent))
-general_command = ["poetry", "run", "agbenchmark", "start", "--backend"]
+logger = logging.getLogger(__name__)
-import psutil
-
-challenges_path = os.path.join(os.path.dirname(__file__), "challenges")
-
-json_files = deque(
+CHALLENGES: dict[str, ChallengeInfo] = {}
+challenges_path = Path(__file__).parent / "challenges"
+challenge_spec_files = deque(
glob.glob(
f"{challenges_path}/**/data.json",
recursive=True,
)
)
-CHALLENGES = {}
-task_informations = defaultdict(dict)
+logger.debug("Loading challenges...")
+while challenge_spec_files:
+ challenge_spec_file = Path(challenge_spec_files.popleft())
+ challenge_relpath = challenge_spec_file.relative_to(challenges_path.parent)
+ if challenge_relpath.is_relative_to("challenges/deprecated"):
+ continue
+
+ logger.debug(f"Loading {challenge_relpath}...")
+ try:
+ challenge_info = ChallengeInfo.parse_file(challenge_spec_file)
+ except ValidationError as e:
+ if logging.getLogger().level == logging.DEBUG:
+ logger.warning(f"Spec file {challenge_relpath} failed to load:\n{e}")
+ logger.debug(f"Invalid challenge spec: {challenge_spec_file.read_text()}")
+ continue
+ challenge_info.spec_file = challenge_spec_file
-while json_files:
- json_file = json_files.popleft()
+ if not challenge_info.eval_id:
+ challenge_info.eval_id = str(uuid.uuid4())
+ # this will sort all the keys of the JSON systematically
+ # so that the order is always the same
+ write_pretty_json(challenge_info.dict(), challenge_spec_file)
- with open(json_file, "r") as file:
- data = json.load(file)
+ CHALLENGES[challenge_info.eval_id] = challenge_info
- if "eval_id" not in data:
- data["eval_id"] = str(uuid.uuid4())
- # this will sort all the keys of the JSON systematically so that the order is always the same
- write_pretty_json(data, json_file)
- # ok
- CHALLENGES[data["eval_id"]] = data
- CHALLENGES[data["eval_id"]]["path"] = json_file
+
+class BenchmarkTaskInfo(BaseModel):
+ task_id: str
+ start_time: datetime.datetime
+ challenge_info: ChallengeInfo
+
+
+task_informations: dict[str, BenchmarkTaskInfo] = {}
def find_agbenchmark_without_uvicorn():
@@ -93,10 +96,10 @@ def find_agbenchmark_without_uvicorn():
):
try:
# Convert the process.info dictionary values to strings and concatenate them
- full_info = " ".join([str(v) for k, v in process.info.items()])
+ full_info = " ".join([str(v) for k, v in process.as_dict().items()])
if "agbenchmark" in full_info and "uvicorn" not in full_info:
- pids.append(process.info["pid"])
+ pids.append(process.pid)
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return pids
@@ -114,24 +117,12 @@ class CreateReportRequest(BaseModel):
updates_list = []
-updates_list = []
-
-import json
-
origins = [
"http://localhost:8000",
"http://localhost:8080",
"http://127.0.0.1:5000",
"http://localhost:5000",
]
-app = FastAPI()
-app.add_middleware(
- CORSMiddleware,
- allow_origins=origins,
- allow_credentials=True,
- allow_methods=["*"],
- allow_headers=["*"],
-)
def stream_output(pipe):
@@ -139,275 +130,205 @@ def stream_output(pipe):
print(line, end="")
-@router.post("/reports")
-def run_single_test(body: CreateReportRequest) -> Any:
- pids = find_agbenchmark_without_uvicorn()
- print(f"pids already running with agbenchmark: {pids}")
- print(body.dict())
- # it's a hack because other parts of the code are using sys.argv
- print(os.getcwd())
- command_options = ["agbenchmark"]
- # if body.category:
- # sys.argv.append(f"--category={body.category}")
- command_options.append(f"--test={body.test}")
- if body.mock:
- command_options.append("--mock")
-
- execute_subprocess(command_options, 200)
- import json
- from pathlib import Path
-
- print("finished running")
- # List all folders in the current working directory
- path_reports = Path.cwd() / "agbenchmark_config" / "reports"
- folders = [folder for folder in path_reports.iterdir() if folder.is_dir()]
-
- # Sort the folders based on their names
- sorted_folders = sorted(folders, key=lambda x: x.name)
-
- # Get the last folder
- last_folder = sorted_folders[-1] if sorted_folders else None
-
- # Read report.json from this folder
- if last_folder:
- report_path = last_folder / "report.json"
- print(report_path)
- if report_path.exists():
- with report_path.open() as file:
- data = json.load(file)
- print(data)
- else:
- print(f"'report.json' does not exist in '{last_folder}'")
- else:
- print("No folders found.")
-
- return Response(
- content=json.dumps(data),
- status_code=200,
- media_type="application/json",
- )
-
-
-import json
-from typing import Any
+def setup_fastapi_app(agbenchmark_config: AgentBenchmarkConfig) -> FastAPI:
+ from agbenchmark.agent_api_interface import upload_artifacts
+ from agbenchmark.challenges import get_challenge_from_source_uri
+ from agbenchmark.main import run_benchmark
-from fastapi import FastAPI, Request, Response
+ configuration = Configuration(
+ host=agbenchmark_config.host or "http://localhost:8000"
+ )
+ app = FastAPI()
+ app.add_middleware(
+ CORSMiddleware,
+ allow_origins=origins,
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+ )
+ router = APIRouter()
+ @router.post("/reports")
+ def run_single_test(body: CreateReportRequest) -> dict:
+ pids = find_agbenchmark_without_uvicorn()
+ logger.info(f"pids already running with agbenchmark: {pids}")
-@router.get("/updates")
-def get_updates(request: Request) -> Any:
- from agbenchmark.__main__ import UPDATES_JSON_PATH
+ logger.debug(f"Request to /reports: {body.dict()}")
- try:
- # Read data from the "update.json" file (provide the correct file path)
- with open(UPDATES_JSON_PATH, "r") as file:
- data = json.load(file)
-
- # Get the last_update_time from the query parameter
- query_param = request.query_params.get("last_update_time")
-
- if query_param is None:
- # Handle the case when last_update_time is not provided
- print("ERROR: last_update_time parameter is missing")
- return Response(
- content=json.dumps({"error": "last_update_time parameter is missing"}),
- status_code=400,
- media_type="application/json",
- headers={"Content-Type": "application/json"},
+ # Start the benchmark in a separate thread
+ benchmark_process = Process(
+ target=lambda: run_benchmark(
+ config=agbenchmark_config,
+ tests=(body.test,),
+ mock=body.mock or False,
)
-
- # Convert query_param to a Unix timestamp (assuming it's in seconds as a string)
- query_timestamp = int(query_param)
-
- # Filter the data based on the timestamp (keep timestamps before query_timestamp)
- filtered_data = [item for item in data if item["timestamp"] > query_timestamp]
-
- # Extract only the "content" field from each item
- filtered_data = [item["content"] for item in filtered_data]
-
- # Convert the filtered data to JSON
- filtered_json = json.dumps(filtered_data, indent=2)
-
- print("INFO: Returning filtered data to the client")
- return Response(
- content=filtered_json,
- status_code=200,
- media_type="application/json",
- headers={"Content-Type": "application/json"},
- )
- except FileNotFoundError:
- print("ERROR: File not found: updates.json")
- return Response(
- content=json.dumps({"error": "File not found"}),
- status_code=404,
- media_type="application/json",
- headers={"Content-Type": "application/json"},
)
-
-
-@router.post("/agent/tasks", tags=["agent"], response_model=Task)
-async def create_agent_task(task_eval_request: TaskEvalRequestBody) -> Task:
- """
- Creates a new task using the provided TaskRequestBody and returns a Task.
-
- Args:
- request (Request): FastAPI request object.
- task (TaskRequestBody): The task request containing input and additional input data.
-
- Returns:
- Task: A new task with task_id, input, additional_input, and empty lists for artifacts and steps.
-
- Example:
- Request (TaskRequestBody defined in schema.py):
- {
- "input": "Write the words you receive to the file 'output.txt'.",
- "additional_input": "python/code"
- }
-
- Response (Task defined in schema.py):
- {
- "task_id": "50da533e-3904-4401-8a07-c49adf88b5eb",
- "input": "Write the word 'Washington' to a .txt file",
- "additional_input": "python/code",
- "artifacts": [],
- }
- """
- from agbenchmark.agent_api_interface import upload_artifacts
-
- try:
- async with ApiClient(configuration) as api_client:
- api_instance = AgentApi(api_client)
- task_input = CHALLENGES[task_eval_request.eval_id]["task"]
-
- task_request_body = TaskRequestBody(input=task_input)
- task_response = await api_instance.create_agent_task(
- task_request_body=task_request_body
- )
- task_informations[task_response.task_id][
- "benchmark_start_time"
- ] = datetime.datetime.now(datetime.timezone.utc).strftime(
- "%Y-%m-%dT%H:%M:%S+00:00"
+ benchmark_process.start()
+
+ # Wait for the benchmark to finish, with a timeout of 200 seconds
+ timeout = 200
+ start_time = time.time()
+ while benchmark_process.is_alive():
+ if time.time() - start_time > timeout:
+ logger.warning(f"Benchmark run timed out after {timeout} seconds")
+ benchmark_process.terminate()
+ break
+ time.sleep(1)
+ else:
+ logger.debug(f"Benchmark finished running in {time.time() - start_time} s")
+
+ # List all folders in the current working directory
+ path_reports = agbenchmark_config.reports_folder
+ folders = [folder for folder in path_reports.iterdir() if folder.is_dir()]
+
+ # Sort the folders based on their names
+ sorted_folders = sorted(folders, key=lambda x: x.name)
+
+ # Get the last folder
+ latest_folder = sorted_folders[-1] if sorted_folders else None
+
+ # Read report.json from this folder
+ if latest_folder:
+ report_path = latest_folder / "report.json"
+ logger.debug(f"Getting latest report from {report_path}")
+ if report_path.exists():
+ with report_path.open() as file:
+ data = json.load(file)
+ logger.debug(f"Report data: {data}")
+ else:
+ logger.error(
+ "Could not get result after running benchmark: "
+ f"'report.json' does not exist in '{latest_folder}'"
+ )
+ else:
+ logger.error(
+ "Could not get result after running benchmark: no reports found"
)
- task_informations[task_response.task_id][
- "eval_id"
- ] = task_eval_request.eval_id
- await upload_artifacts(
- api_instance,
- str(Path(CHALLENGES[task_eval_request.eval_id]["path"]).parent),
- task_response.task_id,
- "artifacts_in",
+
+ return data
+
+ @router.post("/agent/tasks", tags=["agent"])
+ async def create_agent_task(task_eval_request: TaskEvalRequestBody) -> Task:
+ """
+ Creates a new task using the provided TaskEvalRequestBody and returns a Task.
+
+ Args:
+ task_eval_request: `TaskRequestBody` including an eval_id.
+
+ Returns:
+ Task: A new task with task_id, input, additional_input,
+ and empty lists for artifacts and steps.
+
+ Example:
+ Request (TaskEvalRequestBody defined in schema.py):
+ {
+ ...,
+ "eval_id": "50da533e-3904-4401-8a07-c49adf88b5eb"
+ }
+
+ Response (Task defined in `agent_protocol_client.models`):
+ {
+ "task_id": "50da533e-3904-4401-8a07-c49adf88b5eb",
+ "input": "Write the word 'Washington' to a .txt file",
+ "artifacts": []
+ }
+ """
+ try:
+ challenge_info = CHALLENGES[task_eval_request.eval_id]
+ async with ApiClient(configuration) as api_client:
+ api_instance = AgentApi(api_client)
+ task_input = challenge_info.task
+
+ task_request_body = TaskRequestBody(input=task_input)
+ task_response = await api_instance.create_agent_task(
+ task_request_body=task_request_body
+ )
+ task_info = BenchmarkTaskInfo(
+ task_id=task_response.task_id,
+ start_time=datetime.datetime.now(datetime.timezone.utc),
+ challenge_info=challenge_info,
+ )
+ task_informations[task_info.task_id] = task_info
+
+ if input_artifacts_dir := challenge_info.task_artifacts_dir:
+ await upload_artifacts(
+ api_instance,
+ input_artifacts_dir,
+ task_response.task_id,
+ "artifacts_in",
+ )
+ return task_response
+ except ApiException as e:
+ logger.error(f"Error whilst trying to create a task:\n{e}")
+ logger.error(
+ "The above error was caused while processing request: "
+ f"{task_eval_request}"
)
- return Response(
- content=task_response.json(),
- status_code=200,
- media_type="application/json",
+ raise HTTPException(500)
+
+ @router.post("/agent/tasks/{task_id}/steps")
+ async def proxy(request: Request, task_id: str):
+ timeout = httpx.Timeout(300.0, read=300.0) # 5 minutes
+ async with httpx.AsyncClient(timeout=timeout) as client:
+ # Construct the new URL
+ new_url = f"{configuration.host}/ap/v1/agent/tasks/{task_id}/steps"
+
+ # Forward the request
+ response = await client.post(
+ new_url,
+ data=await request.body(),
+ headers=dict(request.headers),
)
- except ApiException as e:
- print(f"Error whilst trying to create a task: {task_eval_request}")
- return Response(
- content=json.dumps({"error": "Internal server error"}),
- status_code=500,
- media_type="application/json",
- )
-
-@router.post("/agent/tasks/{task_id}/steps")
-async def proxy(request: Request, task_id: str):
- timeout = httpx.Timeout(300.0, read=300.0) # 5 minutes
- async with httpx.AsyncClient(timeout=timeout) as client:
- # Construct the new URL
- new_url = f"http://localhost:8000/ap/v1/agent/tasks/{task_id}/steps"
-
- # Forward the request
- response = await client.post(
- new_url,
- data=await request.body(),
- headers=dict(request.headers),
- )
+ # Return the response from the forwarded request
+ return Response(content=response.content, status_code=response.status_code)
- # Return the response from the forwarded request
- return Response(content=response.content, status_code=response.status_code)
-
-
-@router.post("/agent/tasks/{task_id}/evaluations")
-async def create_evaluation(task_id: str) -> deque:
- from agbenchmark.__main__ import TEMP_FOLDER_ABS_PATH
- from agbenchmark.agent_api_interface import copy_agent_artifacts_into_temp_folder
- from agbenchmark.agent_interface import copy_artifacts_into_temp_folder
- from agbenchmark.generate_test import create_challenge
+ @router.post("/agent/tasks/{task_id}/evaluations")
+ async def create_evaluation(task_id: str) -> BenchmarkRun:
+ task_info = task_informations[task_id]
+ challenge = get_challenge_from_source_uri(task_info.challenge_info.source_uri)
+ try:
+ async with ApiClient(configuration) as api_client:
+ api_instance = AgentApi(api_client)
+ eval_results = await challenge.evaluate_task_state(
+ api_instance, task_id
+ )
+
+ eval_info = BenchmarkRun(
+ repository_info=RepositoryInfo(),
+ run_details=RunDetails(
+ command=f"agbenchmark --test={challenge.info.name}",
+ benchmark_start_time=(
+ task_info.start_time.strftime("%Y-%m-%dT%H:%M:%S+00:00")
+ ),
+ test_name=challenge.info.name,
+ ),
+ task_info=TaskInfo(
+ data_path=challenge.info.source_uri,
+ is_regression=None,
+ category=[c.value for c in challenge.info.category],
+ task=challenge.info.task,
+ answer=challenge.info.reference_answer or "",
+ description=challenge.info.description or "",
+ ),
+ metrics=Metrics(
+ success=all(e.passed for e in eval_results),
+ success_percentage=(
+ 100 * sum(e.score for e in eval_results) / len(eval_results)
+ if eval_results # avoid division by 0
+ else 0
+ ),
+ attempted=True,
+ ),
+ config={},
+ )
- try:
- async with ApiClient(configuration) as api_client:
- api_instance = AgentApi(api_client)
- await copy_agent_artifacts_into_temp_folder(api_instance, task_id)
- # add custom python
- data = CHALLENGES[task_informations[task_id]["eval_id"]]
-
- artifact_path = str(Path(data["path"]).parent)
- copy_artifacts_into_temp_folder(
- TEMP_FOLDER_ABS_PATH, "custom_python", artifact_path
- )
- json_file = CHALLENGES[task_informations[task_id]["eval_id"]]["path"]
- json_files = deque()
-
- _, challenge_class = create_challenge(data, json_file, json_files)
- challenge_instance = challenge_class()
- scores = challenge_instance.get_scores(config={})
- test_name = "Test" + data["name"]
- is_score_100 = 1 in scores["values"]
-
- info_details = {
- "repository_info": {
- "repo_url": None,
- "team_name": None,
- "benchmark_git_commit_sha": None,
- "agent_git_commit_sha": None,
- },
- "run_details": {
- "run_id": None,
- "command": "agbenchmark" + " --test=" + test_name,
- "completion_time": None,
- "benchmark_start_time": task_informations[task_id][
- "benchmark_start_time"
- ],
- "test_name": data["name"],
- },
- "task_info": {
- "data_path": data["path"].split("benchmark/", 1)[-1],
- "is_regression": None,
- "category": data["category"],
- "task": data["task"],
- "answer": data["ground"]["answer"],
- "description": data["info"]["description"],
- },
- "metrics": {
- "difficulty": None,
- "success": is_score_100,
- "attempted": True,
- "success_percentage": None,
- "cost": None,
- "run_time": None,
- },
- "reached_cutoff": None,
- "config": {},
- }
-
- BenchmarkRun.parse_obj(info_details)
-
- print(json.dumps(info_details, indent=4))
- return Response(
- content=json.dumps(info_details),
- status_code=200,
- media_type="application/json",
- )
- except ApiException as e:
- print(f"Error whilst trying to evaluate the task: {task_id}")
- return Response(
- content=json.dumps({"error": "Internal server error"}),
- status_code=500,
- media_type="application/json",
- )
- # path = Path(json_file).resolve()
+ logger.debug(f"Returning evaluation data:\n{eval_info.json(indent=4)}")
+ return eval_info
+ except ApiException as e:
+ logger.error(f"Error {e} whilst trying to evaluate task: {task_id}")
+ raise HTTPException(500)
+ app.include_router(router, prefix="/ap/v1")
-app.include_router(router, prefix="/ap/v1")
+ return app
diff --git a/benchmark/agbenchmark/challenges/__init__.py b/benchmark/agbenchmark/challenges/__init__.py
index e69de29bb..68105d854 100644
--- a/benchmark/agbenchmark/challenges/__init__.py
+++ b/benchmark/agbenchmark/challenges/__init__.py
@@ -0,0 +1,56 @@
+import glob
+import json
+import logging
+from pathlib import Path
+
+from .base import BaseChallenge, ChallengeInfo
+from .builtin import OPTIONAL_CATEGORIES
+
+logger = logging.getLogger(__name__)
+
+
+def get_challenge_from_source_uri(source_uri: str) -> type[BaseChallenge]:
+ from .builtin import BuiltinChallenge
+ from .webarena import WebArenaChallenge
+
+ provider_prefix = source_uri.split("/", 1)[0]
+
+ if provider_prefix == BuiltinChallenge.SOURCE_URI_PREFIX:
+ return BuiltinChallenge.from_source_uri(source_uri)
+
+ if provider_prefix == WebArenaChallenge.SOURCE_URI_PREFIX:
+ return WebArenaChallenge.from_source_uri(source_uri)
+
+ raise ValueError(f"Cannot resolve source_uri '{source_uri}'")
+
+
+def get_unique_categories() -> set[str]:
+ """
+ Reads all challenge spec files and returns a set of all their categories.
+ """
+ categories = set()
+
+ challenges_dir = Path(__file__).parent
+ glob_path = f"{challenges_dir}/**/data.json"
+
+ for data_file in glob.glob(glob_path, recursive=True):
+ with open(data_file, "r") as f:
+ try:
+ challenge_data = json.load(f)
+ categories.update(challenge_data.get("category", []))
+ except json.JSONDecodeError:
+ logger.error(f"Error: {data_file} is not a valid JSON file.")
+ continue
+ except IOError:
+ logger.error(f"IOError: file could not be read: {data_file}")
+ continue
+
+ return categories
+
+
+__all__ = [
+ "BaseChallenge",
+ "ChallengeInfo",
+ "get_unique_categories",
+ "OPTIONAL_CATEGORIES",
+]
diff --git a/benchmark/agbenchmark/challenges/base.py b/benchmark/agbenchmark/challenges/base.py
new file mode 100644
index 000000000..f77a08c65
--- /dev/null
+++ b/benchmark/agbenchmark/challenges/base.py
@@ -0,0 +1,107 @@
+import logging
+from abc import ABC, abstractmethod
+from pathlib import Path
+from typing import AsyncIterator, ClassVar, Optional
+
+import pytest
+from agent_protocol_client import AgentApi, Step
+from colorama import Fore, Style
+from pydantic import BaseModel, Field
+
+from agbenchmark.config import AgentBenchmarkConfig
+from agbenchmark.utils.data_types import Category, DifficultyLevel, EvalResult
+
+logger = logging.getLogger(__name__)
+
+
+class ChallengeInfo(BaseModel):
+ eval_id: str = ""
+ name: str
+ task: str
+ task_artifacts_dir: Optional[Path] = None
+ category: list[Category]
+ difficulty: Optional[DifficultyLevel] = None
+ description: Optional[str] = None
+ dependencies: list[str] = Field(default_factory=list)
+ reference_answer: Optional[str]
+
+ source_uri: str
+ """Internal reference indicating the source of the challenge specification"""
+
+ available: bool = True
+ unavailable_reason: str = ""
+
+
+class BaseChallenge(ABC):
+ """
+ The base class and shared interface for all specific challenge implementations.
+ """
+
+ info: ClassVar[ChallengeInfo]
+
+ @classmethod
+ @abstractmethod
+ def from_source_uri(cls, source_uri: str) -> type["BaseChallenge"]:
+ """
+ Construct an individual challenge subclass from a suitable `source_uri` (as in
+ `ChallengeInfo.source_uri`).
+ """
+ ...
+
+ @abstractmethod
+ def test_method(
+ self,
+ config: AgentBenchmarkConfig,
+ request: pytest.FixtureRequest,
+ i_attempt: int,
+ ) -> None:
+ """
+ Test method for use by Pytest-based benchmark sessions. Should return normally
+ if the challenge passes, and raise a (preferably descriptive) error otherwise.
+ """
+ ...
+
+ @classmethod
+ async def run_challenge(
+ cls, config: AgentBenchmarkConfig, timeout: int, *, mock: bool = False
+ ) -> AsyncIterator[Step]:
+ """
+ Runs the challenge on the subject agent with the specified timeout.
+ Also prints basic challenge and status info to STDOUT.
+
+ Params:
+ config: The subject agent's benchmark config.
+ timeout: Timeout (seconds) after which to stop the run if not finished.
+
+ Yields:
+ Step: The steps generated by the agent for the challenge task.
+ """
+ # avoid circular import
+ from agbenchmark.agent_api_interface import run_api_agent
+
+ print()
+ print(
+ f"{Fore.MAGENTA + Style.BRIGHT}{'='*24} "
+ f"Starting {cls.info.name} challenge"
+ f" {'='*24}{Style.RESET_ALL}"
+ )
+ print(f"{Fore.CYAN}Timeout:{Fore.RESET} {timeout} seconds")
+ print(f"{Fore.CYAN}Task:{Fore.RESET} {cls.info.task}")
+
+ print()
+ logger.debug(f"Starting {cls.info.name} challenge run")
+ i = 0
+ async for step in run_api_agent(
+ cls.info.task, config, timeout, cls.info.task_artifacts_dir, mock=mock
+ ):
+ i += 1
+ print(f"[{cls.info.name}] - step {step.name} ({i}. request)")
+ yield step
+ logger.debug(f"Finished {cls.info.name} challenge run")
+
+ @classmethod
+ @abstractmethod
+ async def evaluate_task_state(
+ cls, agent: AgentApi, task_id: str
+ ) -> list[EvalResult]:
+ ...
diff --git a/benchmark/agbenchmark/challenges/builtin.py b/benchmark/agbenchmark/challenges/builtin.py
new file mode 100644
index 000000000..71e61bad4
--- /dev/null
+++ b/benchmark/agbenchmark/challenges/builtin.py
@@ -0,0 +1,449 @@
+from collections import deque
+import glob
+import json
+import logging
+import os
+import subprocess
+import sys
+import tempfile
+from pathlib import Path
+from typing import Any, ClassVar, Iterator, Literal, Optional
+
+import pytest
+from agent_protocol_client import (
+ AgentApi,
+ ApiClient,
+ Configuration as ClientConfig,
+ Step,
+)
+from colorama import Fore, Style
+from openai import _load_client as get_openai_client
+from pydantic import BaseModel, constr, Field, validator
+
+from agbenchmark.agent_api_interface import download_agent_artifacts_into_folder
+from agbenchmark.agent_interface import copy_challenge_artifacts_into_workspace
+from agbenchmark.config import AgentBenchmarkConfig
+from agbenchmark.utils.data_types import Category, DifficultyLevel, EvalResult
+from agbenchmark.utils.prompts import (
+ END_PROMPT,
+ FEW_SHOT_EXAMPLES,
+ PROMPT_MAP,
+ SCORING_MAP,
+)
+
+from .base import BaseChallenge, ChallengeInfo
+
+logger = logging.getLogger(__name__)
+
+with open(Path(__file__).parent / "optional_categories.json") as f:
+ OPTIONAL_CATEGORIES: list[str] = json.load(f)["optional_categories"]
+
+
+class BuiltinChallengeSpec(BaseModel):
+ eval_id: str = ""
+ name: str
+ task: str
+ category: list[Category]
+ dependencies: list[str]
+ cutoff: int
+
+ class Info(BaseModel):
+ difficulty: DifficultyLevel
+ description: constr(regex=r"^Tests if the agent can.*")
+ side_effects: list[str] = Field(default_factory=list)
+
+ info: Info
+
+ class Ground(BaseModel):
+ answer: str
+ should_contain: Optional[list[str]] = None
+ should_not_contain: Optional[list[str]] = None
+ files: list[str]
+ case_sensitive: Optional[bool] = True
+
+ class Eval(BaseModel):
+ type: str
+ scoring: Optional[Literal["percentage", "scale", "binary"]]
+ template: Optional[Literal["rubric", "reference", "question", "custom"]]
+ examples: Optional[str]
+
+ @validator("scoring", "template", always=True)
+ def validate_eval_fields(cls, v, values, field):
+ if "type" in values and values["type"] == "llm":
+ if v is None:
+ raise ValueError(
+ f"{field.name} must be provided when eval type is 'llm'"
+ )
+ else:
+ if v is not None:
+ raise ValueError(
+ f"{field.name} should only exist when eval type is 'llm'"
+ )
+ return v
+
+ eval: Eval
+
+ ground: Ground
+
+ metadata: Optional[dict[str, Any]] = None
+ spec_file: Path | None = Field(None, exclude=True)
+
+
+class BuiltinChallenge(BaseChallenge):
+ """
+ Base class for AGBenchmark's built-in challenges (challenges/**/*.json).
+
+ All of the logic is present in this class. Individual challenges are created as
+ subclasses of `BuiltinChallenge` with challenge-specific values assigned to the
+ ClassVars `_spec` etc.
+
+ Dynamically constructing subclasses rather than class instances for the individual
+ challenges makes them suitable for collection by Pytest, which will run their
+ `test_method` like any regular test item.
+ """
+
+ _spec: ClassVar[BuiltinChallengeSpec]
+ CHALLENGE_LOCATION: ClassVar[str]
+ ARTIFACTS_LOCATION: ClassVar[str]
+
+ SOURCE_URI_PREFIX = "__BUILTIN__"
+
+ @classmethod
+ def from_challenge_spec(
+ cls, spec: BuiltinChallengeSpec
+ ) -> type["BuiltinChallenge"]:
+ if not spec.spec_file:
+ raise ValueError("spec.spec_file not defined")
+
+ challenge_info = ChallengeInfo(
+ eval_id=spec.eval_id,
+ name=spec.name,
+ task=spec.task,
+ task_artifacts_dir=spec.spec_file.parent,
+ category=spec.category,
+ difficulty=spec.info.difficulty,
+ description=spec.info.description,
+ dependencies=spec.dependencies,
+ reference_answer=spec.ground.answer,
+ source_uri=(
+ f"__BUILTIN__/{spec.spec_file.relative_to(Path(__file__).parent)}"
+ ),
+ )
+
+ challenge_class_name = f"Test{challenge_info.name}"
+ logger.debug(f"Creating {challenge_class_name} from spec: {spec.spec_file}")
+ return type(
+ challenge_class_name,
+ (BuiltinChallenge,),
+ {
+ "info": challenge_info,
+ "_spec": spec,
+ "CHALLENGE_LOCATION": str(spec.spec_file),
+ "ARTIFACTS_LOCATION": str(spec.spec_file.resolve().parent),
+ },
+ )
+
+ @classmethod
+ def from_challenge_spec_file(cls, spec_file: Path) -> type["BuiltinChallenge"]:
+ challenge_spec = BuiltinChallengeSpec.parse_file(spec_file)
+ challenge_spec.spec_file = spec_file
+ return cls.from_challenge_spec(challenge_spec)
+
+ @classmethod
+ def from_source_uri(cls, source_uri: str) -> type["BuiltinChallenge"]:
+ if not source_uri.startswith(cls.SOURCE_URI_PREFIX):
+ raise ValueError(f"Invalid source_uri for BuiltinChallenge: {source_uri}")
+
+ path = source_uri.split("/", 1)[1]
+ spec_file = Path(__file__).parent / path
+ return cls.from_challenge_spec_file(spec_file)
+
+ @pytest.mark.asyncio
+ async def test_method(
+ self,
+ config: AgentBenchmarkConfig,
+ request: pytest.FixtureRequest,
+ i_attempt: int,
+ ) -> None:
+ # if os.environ.get("HELICONE_API_KEY"):
+ # from helicone.lock import HeliconeLockManager
+
+ # HeliconeLockManager.write_custom_property("challenge", self.info.name)
+
+ timeout = self._spec.cutoff or 60
+
+ if request.config.getoption("--nc"):
+ timeout = 100000
+ elif cutoff := request.config.getoption("--cutoff"):
+ timeout = int(cutoff) # type: ignore
+
+ task_id = ""
+ n_steps = 0
+ timed_out = None
+ agent_task_cost = None
+ steps: list[Step] = []
+ try:
+ async for step in self.run_challenge(
+ config, timeout, mock=request.config.getoption("--mock")
+ ):
+ if not task_id:
+ task_id = step.task_id
+
+ n_steps += 1
+ steps.append(step.copy())
+ if step.additional_output:
+ agent_task_cost = step.additional_output.get(
+ "task_total_cost",
+ step.additional_output.get("task_cumulative_cost"),
+ )
+ timed_out = False
+ except TimeoutError:
+ timed_out = True
+ request.node.user_properties.append(("steps", steps))
+ request.node.user_properties.append(("n_steps", n_steps))
+ request.node.user_properties.append(("timed_out", timed_out))
+ request.node.user_properties.append(("agent_task_cost", agent_task_cost))
+
+ agent_client_config = ClientConfig(host=config.host)
+ async with ApiClient(agent_client_config) as api_client:
+ api_instance = AgentApi(api_client)
+ eval_results = await self.evaluate_task_state(api_instance, task_id)
+
+ if not eval_results:
+ if timed_out:
+ raise TimeoutError("Timed out, no results to evaluate")
+ else:
+ raise ValueError("No results to evaluate")
+
+ request.node.user_properties.append(
+ (
+ "answers",
+ [r.result for r in eval_results]
+ if request.config.getoption("--keep-answers")
+ else None,
+ )
+ )
+ request.node.user_properties.append(("scores", [r.score for r in eval_results]))
+
+ # FIXME: this allows partial failure
+ assert any(r.passed for r in eval_results), (
+ f"No passed evals: {eval_results}"
+ if not timed_out
+ else f"Timed out; no passed evals: {eval_results}"
+ )
+
+ @classmethod
+ async def evaluate_task_state(
+ cls, agent: AgentApi, task_id: str
+ ) -> list[EvalResult]:
+ with tempfile.TemporaryDirectory() as workspace:
+ workspace = Path(workspace)
+ await download_agent_artifacts_into_folder(agent, task_id, workspace)
+ if cls.info.task_artifacts_dir:
+ copy_challenge_artifacts_into_workspace(
+ cls.info.task_artifacts_dir, "custom_python", workspace
+ )
+
+ return list(cls.evaluate_workspace_content(workspace))
+
+ @classmethod
+ def evaluate_workspace_content(cls, workspace: Path) -> Iterator[EvalResult]:
+ result_ground = cls._spec.ground
+ outputs_for_eval = cls.get_outputs_for_eval(workspace, result_ground)
+
+ if result_ground.should_contain or result_ground.should_not_contain:
+ for source, content in outputs_for_eval:
+ score = cls.score_result(content, result_ground)
+ if score is not None:
+ print(f"{Fore.GREEN}Your score is:{Style.RESET_ALL}", score)
+ yield EvalResult(
+ result=content,
+ result_source=str(source),
+ score=score,
+ passed=score > 0.9, # FIXME: arbitrary threshold
+ )
+
+ if result_ground.eval.type in ("python", "pytest"):
+ for py_file, output in outputs_for_eval:
+ yield EvalResult(
+ result=output,
+ result_source=str(py_file),
+ score=float(not output.startswith("Error:")),
+ passed=not output.startswith("Error:"),
+ )
+
+ if result_ground.eval.type == "llm":
+ combined_results = "\n".join(output[1] for output in outputs_for_eval)
+ llm_eval = cls.score_result_with_llm(combined_results, result_ground)
+ print(f"{Fore.GREEN}Your score is:{Style.RESET_ALL}", llm_eval)
+ if result_ground.eval.scoring == "percentage":
+ score = llm_eval / 100
+ elif result_ground.eval.scoring == "scale":
+ score = llm_eval / 10
+ else:
+ score = llm_eval
+
+ yield EvalResult(
+ result=combined_results,
+ result_source=", ".join(str(res[0]) for res in outputs_for_eval),
+ score=score,
+ passed=score > 0.9, # FIXME: arbitrary threshold
+ )
+
+ @staticmethod
+ def get_outputs_for_eval(
+ workspace: str | Path | dict[str, str], ground: BuiltinChallengeSpec.Ground
+ ) -> Iterator[tuple[str | Path, str]]:
+ if isinstance(workspace, dict):
+ workspace = workspace["output"]
+
+ script_dir = workspace
+
+ for file_pattern in ground.files:
+ # Check if it is a file extension
+ if file_pattern.startswith("."):
+ # Find all files with the given extension in the workspace
+ matching_files = glob.glob(os.path.join(script_dir, "*" + file_pattern))
+ else:
+ # Otherwise, it is a specific file
+ matching_files = [os.path.join(script_dir, file_pattern)]
+
+ logger.debug(
+ f"Files to evaluate for pattern `{file_pattern}`: {matching_files}"
+ )
+
+ for file_path in matching_files:
+ relative_file_path = Path(file_path).relative_to(workspace)
+ logger.debug(
+ f"Evaluating {relative_file_path} "
+ f"(eval type: {ground.eval.type})..."
+ )
+ if ground.eval.type == "python":
+ result = subprocess.run(
+ [sys.executable, file_path],
+ cwd=os.path.abspath(workspace),
+ capture_output=True,
+ text=True,
+ )
+ if "error" in result.stderr or result.returncode != 0:
+ yield relative_file_path, f"Error: {result.stderr}\n"
+ else:
+ yield relative_file_path, f"Output: {result.stdout}\n"
+ else:
+ with open(file_path, "r") as f:
+ yield relative_file_path, f.read()
+ else:
+ if ground.eval.type == "pytest":
+ result = subprocess.run(
+ [sys.executable, "-m", "pytest"],
+ cwd=os.path.abspath(workspace),
+ capture_output=True,
+ text=True,
+ )
+ if "error" in result.stderr or result.returncode != 0:
+ yield "pytest", f"Error: {result.stderr}\n"
+ else:
+ yield "pytest", f"Output: {result.stdout}\n"
+
+ @staticmethod
+ def score_result(content: str, ground: BuiltinChallengeSpec.Ground) -> float | None:
+ print(f"{Fore.BLUE}Scoring content:{Style.RESET_ALL}", content)
+ if ground.should_contain:
+ for should_contain_word in ground.should_contain:
+ if not ground.case_sensitive:
+ should_contain_word = should_contain_word.lower()
+ content = content.lower()
+ print_content = (
+ f"{Fore.BLUE}Word that should exist{Style.RESET_ALL}"
+ f" - {should_contain_word}:"
+ )
+ if should_contain_word not in content:
+ print(print_content, "False")
+ return 0.0
+ else:
+ print(print_content, "True")
+ return 1.0
+
+ if ground.should_not_contain:
+ for should_not_contain_word in ground.should_not_contain:
+ if not ground.case_sensitive:
+ should_not_contain_word = should_not_contain_word.lower()
+ content = content.lower()
+ print_content = (
+ f"{Fore.BLUE}Word that should not exist{Style.RESET_ALL}"
+ f" - {should_not_contain_word}:"
+ )
+ if should_not_contain_word in content:
+ print(print_content, "False")
+ return 0.0
+ else:
+ print(print_content, "True")
+ return 1.0
+
+ @classmethod
+ def score_result_with_llm(
+ cls, content: str, ground: BuiltinChallengeSpec.Ground, *, mock: bool = False
+ ) -> float:
+ if mock:
+ return 1.0
+
+ # the validation for this is done in the Eval BaseModel
+ scoring = SCORING_MAP[ground.eval.scoring] # type: ignore
+ prompt = PROMPT_MAP[ground.eval.template].format( # type: ignore
+ task=cls._spec.task, scoring=scoring, answer=ground.answer, response=content
+ )
+
+ if ground.eval.examples:
+ prompt += FEW_SHOT_EXAMPLES.format(examples=ground.eval.examples)
+
+ prompt += END_PROMPT
+
+ answer = get_openai_client().chat.completions.create(
+ model="gpt-4",
+ messages=[
+ {"role": "system", "content": prompt},
+ ],
+ )
+
+ return float(answer.choices[0].message.content) # type: ignore
+
+
+def load_builtin_challenges() -> Iterator[type[BuiltinChallenge]]:
+ logger.info("Loading built-in challenges...")
+
+ challenges_path = os.path.dirname(__file__)
+ logger.debug(f"Looking for challenge spec files in {challenges_path}...")
+
+ json_files = deque(
+ glob.glob(
+ f"{challenges_path}/**/data.json",
+ recursive=True,
+ )
+ )
+
+ logger.debug(f"Found {len(json_files)} built-in challenges.")
+
+ loaded, ignored = 0, 0
+ while json_files:
+ # Take and remove the first element from json_files
+ json_file = json_files.popleft()
+ if _challenge_should_be_ignored(json_file):
+ ignored += 1
+ continue
+
+ challenge = BuiltinChallenge.from_challenge_spec_file(Path(json_file))
+ logger.debug(f"Generated test for {challenge.info.name}")
+ yield challenge
+
+ loaded += 1
+
+ logger.info(
+ f"Loading built-in challenges complete: loaded {loaded}, ignored {ignored}."
+ )
+
+
+def _challenge_should_be_ignored(json_file_path: str):
+ return (
+ "challenges/deprecated" in json_file_path
+ or "challenges/library" in json_file_path
+ )
diff --git a/benchmark/agbenchmark/challenges/verticals/code/5_tic_tac_toe/custom_python/test.py b/benchmark/agbenchmark/challenges/verticals/code/5_tic_tac_toe/custom_python/test.py
index 94b778208..01180015b 100644
--- a/benchmark/agbenchmark/challenges/verticals/code/5_tic_tac_toe/custom_python/test.py
+++ b/benchmark/agbenchmark/challenges/verticals/code/5_tic_tac_toe/custom_python/test.py
@@ -38,4 +38,4 @@ def test_game(inputs, expected_output):
if __name__ == "__main__":
- pytest.main()
+ pytest.main([__file__])
diff --git a/benchmark/agbenchmark/challenges/verticals/code/5_tic_tac_toe/data.json b/benchmark/agbenchmark/challenges/verticals/code/5_tic_tac_toe/data.json
index 63f19ce6f..e46c51bd3 100644
--- a/benchmark/agbenchmark/challenges/verticals/code/5_tic_tac_toe/data.json
+++ b/benchmark/agbenchmark/challenges/verticals/code/5_tic_tac_toe/data.json
@@ -25,5 +25,5 @@
"side_effects": []
},
"name": "TicTacToe",
- "task": "Build a Tic-Tac-Toe game using a python CLI. Here are the specifications.\n\nThe Grid: The game board is a 3x3 grid, consisting of 3 rows and 3 columns, creating a total of 9 squares.\n\nPlayers: There are two players. One player uses the number \"1\", and the other player uses the number \"2\".\n\nTaking Turns: Players take turns to put their respective numbers (\"1\" or \"2\") in an empty square of the grid. Once a player has placed their number in a square, it cannot be changed or removed.\n\nObjective: The goal is to get three of your numbers in a row, either horizontally, vertically, or diagonally.\n\nEnd of the Game: The game concludes in one of two ways: One player gets three of their numbers in a row (horizontally, vertically, or diagonally) and is declared the winner.\nAll squares on the grid are filled, and no player has three in a row. This situation is a \"draw\" or a \"tie\".\n\nTechnical specifications:\nBuild a file called tic_tac_toe.py. This file will be called through command lines. You will have to prompt users for their move. Player 1 will always start.\nPlayers will input their move in the following format: \"x,y\" where x and y represent the location in the grid (0,0 is top left, 2,2 is bottom right).\n\nYour primary requirement is to halt the game when appropriate and to print only one of these three exact sentences:\n\n\"Player 1 won!\"\n\"Player 2 won!\"\n\"Draw\"\n\nEdge cases: A player can send an incorrect location. Either the location is incorrect or the square is already filled. In this case, this counts as doing nothing, and the player gets prompted for new locations again.\n\n\nYou will be expected to create a python file called tic_tac_toe.py that will run through command lines by using ```python tic_tac_toe.py```.\n\nHere is an example of how your tic_tac_toe.py game will be tested.\n```\nprocess = subprocess.Popen(\n ['python', 'tic_tac_toe.py'],\n stdout=subprocess.PIPE,\n text=True\n)\n\noutput, _ = process.communicate('\\n'.join([\"0,0\", \"1,0\", \"0,1\", \"1,1\", \"0,2\"]))\n\nassert \"Player 1 won!\" in output\n```"
+ "task": "Build a Tic-Tac-Toe game using a python CLI. Here are the specifications.\n\nThe Grid: The game board is a 3x3 grid, consisting of 3 rows and 3 columns, creating a total of 9 squares.\n\nPlayers: There are two players. One player uses the number \"1\", and the other player uses the number \"2\".\n\nTaking Turns: Players take turns to put their respective numbers (\"1\" or \"2\") in an empty square of the grid. Once a player has placed their number in a square, it cannot be changed or removed.\n\nObjective: The goal is to get three of your numbers in a row, either horizontally, vertically, or diagonally.\n\nEnd of the Game: The game concludes in one of two ways: One player gets three of their numbers in a row (horizontally, vertically, or diagonally) and is declared the winner.\nAll squares on the grid are filled, and no player has three in a row. This situation is a \"draw\" or a \"tie\".\n\nTechnical specifications:\nBuild a file called tic_tac_toe.py. This file will be called through command lines. You will have to prompt users for their move. Player 1 will always start.\nPlayers will input their move in the following format: \"x,y\" where x and y represent the location in the grid (0,0 is top left, 2,2 is bottom right).\n\nYour primary requirement is to halt the game when appropriate and to print only one of these three exact sentences:\n\n\"Player 1 won!\"\n\"Player 2 won!\"\n\"Draw\"\n\nEdge cases: A player can send an incorrect location. Either the location is incorrect or the square is already filled. In this case, this counts as doing nothing, and the player gets prompted for new locations again.\n\n\nYou will be expected to create a python file called tic_tac_toe.py that will run through command lines by using ```python tic_tac_toe.py```.\n\nHere is an example of how your tic_tac_toe.py game will be tested.\n```\nprocess = subprocess.Popen(\n ['python', 'tic_tac_toe.py'],\n stdin=subprocess.PIPE,\n stdout=subprocess.PIPE,\n stderr=subprocess.PIPE,\n text=True\n)\n\noutput, _ = process.communicate('\\n'.join([\"0,0\", \"1,0\", \"0,1\", \"1,1\", \"0,2\"]))\n\nassert \"Player 1 won!\" in output\n```"
}
diff --git a/benchmark/agbenchmark/challenges/verticals/scrape/4_revenue_retrieval_2/data.json b/benchmark/agbenchmark/challenges/verticals/scrape/4_revenue_retrieval_2/data.json
index 8ca61b9e7..ea1230326 100644
--- a/benchmark/agbenchmark/challenges/verticals/scrape/4_revenue_retrieval_2/data.json
+++ b/benchmark/agbenchmark/challenges/verticals/scrape/4_revenue_retrieval_2/data.json
@@ -16,21 +16,21 @@
".txt"
],
"should_contain": [
- "15",
- "112",
- "117",
- "204",
- "413",
- "2,0",
- "3,198",
- "4,046",
- "7,000",
- "11,759",
- "21,461",
- "24,578",
- "31,536",
- "53,823",
- "81,462"
+ "15",
+ "112",
+ "117",
+ "204",
+ "413",
+ "2,0",
+ "3,198",
+ "4,046",
+ "7,000",
+ "11,759",
+ "21,461",
+ "24,578",
+ "31,536",
+ "53,823",
+ "81,462"
],
"should_not_contain": []
},
diff --git a/benchmark/agbenchmark/challenges/verticals/synthesize/1_basic_content_gen/data.json b/benchmark/agbenchmark/challenges/verticals/synthesize/1_basic_content_gen/data.json
index 68ae89288..6993c4adc 100644
--- a/benchmark/agbenchmark/challenges/verticals/synthesize/1_basic_content_gen/data.json
+++ b/benchmark/agbenchmark/challenges/verticals/synthesize/1_basic_content_gen/data.json
@@ -18,9 +18,7 @@
"files": [
"output.txt"
],
- "should_contain": [
- ""
- ],
+ "should_contain": [],
"should_not_contain": []
},
"info": {
diff --git a/benchmark/agbenchmark/challenges/webarena.py b/benchmark/agbenchmark/challenges/webarena.py
new file mode 100644
index 000000000..9f44ac8f4
--- /dev/null
+++ b/benchmark/agbenchmark/challenges/webarena.py
@@ -0,0 +1,531 @@
+import logging
+import os
+from abc import ABC, abstractmethod
+from typing import ClassVar, Iterator, Literal
+
+import pytest
+import requests
+from agent_protocol_client import AgentApi, Step
+from pydantic import BaseModel, validator, ValidationError
+
+from agbenchmark.config import AgentBenchmarkConfig
+from agbenchmark.utils.data_types import Category, EvalResult
+
+from .base import BaseChallenge, ChallengeInfo
+
+logger = logging.getLogger(__name__)
+
+
+EvalType = Literal["string_match", "url_match", "program_html"]
+WebArenaSite = Literal[
+ "gitlab", "map", "reddit", "shopping", "shopping_admin", "wikipedia"
+]
+ReferenceAnswerType = Literal["exact_match", "fuzzy_match", "must_include"]
+
+
+class WebArenaSiteInfo(BaseModel):
+ base_url: str
+ available: bool = True
+ additional_info: str = ""
+ unavailable_reason: str = ""
+
+
+_git_user, _git_password = os.getenv("WEBARENA_GIT_CREDENTIALS", ":").split(":")
+
+site_info_map: dict[WebArenaSite, WebArenaSiteInfo] = {
+ "gitlab": WebArenaSiteInfo(
+ base_url="http://git.junglegym.ai",
+ available=bool(_git_user and _git_password),
+ additional_info=(
+ f"To log in to {{url}}, use the username '{_git_user}' "
+ f"and password '{_git_password}'."
+ ),
+ unavailable_reason=(
+ "WEBARENA_GIT_CREDENTIALS not set (correctly): "
+ f"'{os.getenv('WEBARENA_GIT_CREDENTIALS', '')}', "
+ "should be USERNAME:PASSWORD."
+ ),
+ ),
+ "map": WebArenaSiteInfo(
+ base_url="http://ec2-3-131-244-37.us-east-2.compute.amazonaws.com:3000/"
+ ),
+ "reddit": WebArenaSiteInfo(base_url="http://forum.junglegym.ai"),
+ "shopping": WebArenaSiteInfo(base_url="http://shop.junglegym.ai"),
+ "shopping_admin": WebArenaSiteInfo(
+ base_url="http://cms.junglegym.ai/admin",
+ additional_info=(
+ "To log in to {url}, use the username 'admin' and password 'admin1234'."
+ ),
+ ),
+ "wikipedia": WebArenaSiteInfo(base_url="http://wiki.junglegym.ai"),
+}
+
+
+def get_site_info(site: WebArenaSite) -> WebArenaSiteInfo:
+ if site not in site_info_map:
+ raise ValueError(f"JungleGym site '{site}' unknown, cannot resolve URL")
+ return site_info_map[site]
+
+
+def get_site_url(site: WebArenaSite) -> str:
+ return get_site_info(site).base_url
+
+
+def resolve_uri(uri: str) -> str:
+ """
+ Resolves URIs with mock hosts, like `__WIKI__/wiki/Octopus`, with the corresponding
+ JungleGym site mirror host.
+ """
+ segments = uri.split("__")
+ if len(segments) > 2 and (site := segments[1]).lower() in site_info_map:
+ return uri.replace(f"__{site}__", get_site_url(site.lower())) # type: ignore
+ return uri
+
+
+class Eval(ABC):
+ @abstractmethod
+ def evaluate(self, string: str) -> bool:
+ ...
+
+ @property
+ @abstractmethod
+ def description(self) -> str:
+ ...
+
+
+class StringEval(BaseModel, Eval):
+ type: ReferenceAnswerType
+
+
+class ExactStringMatchEval(StringEval):
+ type: Literal["exact_match"] = "exact_match"
+ reference_answer: str
+
+ @property
+ def description(self) -> str:
+ return f"Answer must be '{self.reference_answer}'"
+
+ def evaluate(self, string: str) -> bool:
+ return string == self.reference_answer
+
+
+class FuzzyStringMatchEval(StringEval):
+ type: Literal["fuzzy_match"] = "fuzzy_match"
+ reference_answer: str
+
+ @property
+ def description(self) -> str:
+ return f"Answer must contain something like '{self.reference_answer}'"
+
+ def evaluate(self, string: str) -> bool:
+ # TODO: use LLM for matching (or something else that's flexible/robust)
+ return self.reference_answer.lower() in string.lower()
+
+
+class MustIncludeStringEval(StringEval):
+ type: Literal["must_include"] = "must_include"
+ reference_answer: str
+
+ @property
+ def description(self) -> str:
+ return f"Answer must include '{self.reference_answer}'"
+
+ def evaluate(self, string: str) -> bool:
+ return self.reference_answer.lower() in string.lower()
+
+
+class UrlMatchEval(BaseModel, Eval):
+ url: str
+ """Example: `"__WIKI__/wiki/Octopus"`"""
+
+ @property
+ def description(self) -> str:
+ return f"Agent must navigate to '{self.url}'"
+
+ def evaluate(self, url: str) -> bool:
+ return url == resolve_uri(self.url)
+
+
+class ProgramHtmlEval(BaseModel):
+ url: str
+ locator: str
+ """JavaScript code that returns the value to check"""
+ required_contents: str
+
+ @property
+ def description(self) -> str:
+ return (
+ f"On the webpage {self.url}, "
+ f"`{self.locator}` should contain '{self.required_contents}'"
+ )
+
+ def evaluate(self, selenium_instance) -> bool:
+ result = selenium_instance.execute_script(
+ self.locator or "return document.body.innerHTML;"
+ )
+ return self.required_contents in result
+
+
+_Eval = StringEval | UrlMatchEval | ProgramHtmlEval
+
+
+class WebArenaChallengeSpec(BaseModel):
+ task_id: int
+ sites: list[WebArenaSite]
+ """The sites needed to complete the task"""
+ start_url: str
+ """The full URL at which to start"""
+ start_url_junglegym: str
+ """The JungleGym site (base URL) at which to start"""
+ require_login: bool
+ require_reset: bool
+ storage_state: str | None
+
+ intent: str
+ intent_template: str
+ intent_template_id: int
+ instantiation_dict: dict[str, str | list[str]]
+
+ available: bool = True
+ unavailable_reason: str = ""
+
+ class EvalSet(BaseModel):
+ class StringMatchEvalSet(BaseModel):
+ exact_match: str | None
+ fuzzy_match: list[str] | None
+ must_include: list[str] | None
+
+ reference_answers: StringMatchEvalSet | None
+ """For string_match eval, a set of criteria to judge the final answer"""
+ reference_answer_raw_annotation: str | None
+ string_note: str | None
+ annotation_note: str | None
+
+ reference_url: str | None
+ """For url_match eval, the last URL that should be visited"""
+ url_note: str | None
+
+ program_html: list[ProgramHtmlEval]
+ """For program_html eval, a list of criteria to judge the site state by"""
+
+ eval_types: list[EvalType]
+
+ @validator("eval_types")
+ def check_eval_parameters(cls, v: list[EvalType], values):
+ if "string_match" in v and not values.get("reference_answers"):
+ raise ValueError("'string_match' eval_type requires reference_answers")
+ if "url_match" in v and not values.get("reference_url"):
+ raise ValueError("'url_match' eval_type requires reference_url")
+ if "program_html" in v and not values.get("program_html"):
+ raise ValueError(
+ "'program_html' eval_type requires at least one program_html eval"
+ )
+ return v
+
+ @property
+ def evaluators(self) -> list[_Eval]:
+ evaluators: list[_Eval] = []
+ if self.reference_answers:
+ if self.reference_answers.exact_match:
+ evaluators.append(
+ ExactStringMatchEval(
+ reference_answer=self.reference_answers.exact_match
+ )
+ )
+ if self.reference_answers.fuzzy_match:
+ evaluators.extend(
+ FuzzyStringMatchEval(reference_answer=a)
+ for a in self.reference_answers.fuzzy_match
+ )
+ if self.reference_answers.must_include:
+ evaluators.extend(
+ MustIncludeStringEval(reference_answer=a)
+ for a in self.reference_answers.must_include
+ )
+ if self.reference_url:
+ evaluators.append(UrlMatchEval(url=self.reference_url))
+ evaluators.extend(self.program_html)
+ return evaluators
+
+ eval: EvalSet
+ """Evaluation criteria by which to judge the agent's performance"""
+
+ @property
+ def assignment_for_agent(self):
+ sites = [get_site_info(s) for s in self.sites]
+ nav_constraint = (
+ "You are ONLY allowed to access URLs in "
+ f"{' and '.join(s.base_url for s in sites)}.\n\n"
+ + "\n".join(
+ s.additional_info.format(url=s.base_url)
+ for s in sites if s.additional_info
+ )
+ ).strip()
+
+ return (
+ f"First of all, go to {self.start_url}. "
+ f"{self.intent.rstrip('.')}.\n"
+ f"{nav_constraint}"
+ )
+
+
+class WebArenaChallenge(BaseChallenge):
+ _spec: ClassVar[WebArenaChallengeSpec]
+
+ SOURCE_URI_PREFIX = "__JUNGLEGYM__/webarena/tasks/"
+ SOURCE_URI_TEMPLATE = f"{SOURCE_URI_PREFIX}{{task_id}}"
+
+ @classmethod
+ def from_source_uri(cls, source_uri: str) -> type["WebArenaChallenge"]:
+ if not source_uri.startswith(cls.SOURCE_URI_PREFIX):
+ raise ValueError(f"Invalid source_uri for WebArenaChallenge: {source_uri}")
+
+ source_url = source_uri.replace(
+ cls.SOURCE_URI_PREFIX,
+ "https://api.junglegym.ai/get_webarena_by_task_id?task_id=",
+ )
+ results = requests.get(source_url).json()["data"]
+ if not results:
+ raise ValueError(f"Could not fetch challenge {source_uri}")
+ return cls.from_challenge_spec(WebArenaChallengeSpec.parse_obj(results[0]))
+
+ @classmethod
+ def from_challenge_spec(
+ cls, spec: WebArenaChallengeSpec
+ ) -> type["WebArenaChallenge"]:
+ challenge_info = ChallengeInfo(
+ eval_id=f"junglegym-webarena-{spec.task_id}",
+ name=f"WebArenaTask_{spec.task_id}",
+ task=spec.assignment_for_agent,
+ category=[
+ Category.GENERALIST,
+ Category.WEB,
+ ], # TODO: make categories more specific
+ reference_answer=spec.eval.reference_answer_raw_annotation,
+ source_uri=cls.SOURCE_URI_TEMPLATE.format(task_id=spec.task_id),
+ available=spec.available,
+ unavailable_reason=spec.unavailable_reason,
+ )
+ return type(
+ f"Test{challenge_info.name}",
+ (WebArenaChallenge,),
+ {
+ "info": challenge_info,
+ "_spec": spec,
+ },
+ )
+
+ @classmethod
+ def evaluate_answer(cls, answer: str) -> list[tuple[_Eval, EvalResult]]:
+ results: list[tuple[_Eval, EvalResult]] = []
+ for evaluator in cls._spec.eval.evaluators:
+ if isinstance(evaluator, StringEval): # string_match
+ results.append(
+ (
+ evaluator,
+ EvalResult(
+ result=answer,
+ result_source="step_output",
+ score=evaluator.evaluate(answer),
+ passed=evaluator.evaluate(answer),
+ ),
+ )
+ )
+ return results
+
+ @classmethod
+ def evaluate_step_result(
+ cls, step: Step, *, mock: bool = False
+ ) -> list[tuple[_Eval, EvalResult]]:
+ if mock:
+ step.output = cls.info.reference_answer
+ assert step.output
+ eval_results = cls.evaluate_answer(step.output)
+ for eval in cls._spec.eval.evaluators:
+ if isinstance(eval, UrlMatchEval):
+ passed = resolve_uri(eval.url) in step.output # HACK: url_match bodge
+ eval_results.append(
+ (
+ eval,
+ EvalResult(
+ result=step.output,
+ result_source="step_output",
+ score=1.0 if passed else 0.0,
+ passed=passed,
+ ),
+ )
+ )
+ # TODO: add support for program_html evals
+ return eval_results
+
+ @classmethod
+ async def evaluate_task_state(
+ cls, agent: AgentApi, task_id: str
+ ) -> list[EvalResult]:
+ steps: list[Step] = (await agent.list_agent_task_steps(task_id)).steps
+
+ eval_results_per_step = [cls.evaluate_step_result(step) for step in steps]
+ # Get the column aggregate (highest scored EvalResult for each Eval)
+ # from the matrix of EvalResults per step.
+ return [
+ max(step_results_for_eval, key=lambda r: r[1].score)[1]
+ for step_results_for_eval in zip(*eval_results_per_step)
+ ]
+
+ @pytest.mark.asyncio
+ async def test_method(
+ self,
+ config: AgentBenchmarkConfig,
+ request: pytest.FixtureRequest,
+ i_attempt: int,
+ ) -> None:
+ if not self._spec.available:
+ pytest.skip(self._spec.unavailable_reason)
+
+ # if os.environ.get("HELICONE_API_KEY"):
+ # from helicone.lock import HeliconeLockManager
+
+ # HeliconeLockManager.write_custom_property("challenge", self.info.name)
+
+ timeout = 120
+ if request.config.getoption("--nc"):
+ timeout = 100000
+ elif cutoff := request.config.getoption("--cutoff"):
+ timeout = int(cutoff)
+
+ n_steps = 0
+ timed_out = None
+ agent_task_cost = None
+ steps: list[Step] = []
+ eval_results_per_step: list[list[tuple[_Eval, EvalResult]]] = []
+ try:
+ async for step in self.run_challenge(
+ config, timeout, mock=request.config.getoption("--mock")
+ ):
+ if not step.output:
+ logger.warn(f"Step has no output: {step}")
+ continue
+
+ n_steps += 1
+ steps.append(step)
+ if step.additional_output:
+ agent_task_cost = step.additional_output.get(
+ "task_total_cost",
+ step.additional_output.get("task_cumulative_cost"),
+ )
+
+ step_eval_results = self.evaluate_step_result(
+ step, mock=request.config.getoption("--mock")
+ )
+ logger.debug(f"Intermediary results: {step_eval_results}")
+ eval_results_per_step.append(step_eval_results)
+ if step.is_last:
+ request.node.user_properties.append(
+ (
+ "answers",
+ step.output
+ if request.config.getoption("--keep-answers")
+ else None,
+ )
+ )
+ timed_out = False
+ except TimeoutError:
+ timed_out = True
+ request.node.user_properties.append(("steps", steps))
+ request.node.user_properties.append(("n_steps", n_steps))
+ request.node.user_properties.append(("timed_out", timed_out))
+ request.node.user_properties.append(("agent_task_cost", agent_task_cost))
+
+ # Get the column aggregate (highest score for each Eval)
+ # from the matrix of EvalResults per step.
+ evals_results = [
+ max(step_results_for_eval, key=lambda r: r[1].score)
+ for step_results_for_eval in zip(*eval_results_per_step)
+ ]
+
+ if not evals_results:
+ if timed_out:
+ raise TimeoutError("Timed out, no results to evaluate")
+ else:
+ raise ValueError("No results to evaluate")
+
+ request.node.user_properties.append(
+ ("scores", [r[1].score for r in evals_results])
+ )
+
+ # FIXME: arbitrary threshold
+ assert all(r[1].score > 0.9 for r in evals_results), (
+ "Scores insufficient:\n\n"
+ if not timed_out
+ else "Timed out; scores insufficient:\n\n"
+ ) + "\n".join(f"{repr(r[0])}\n -> {repr(r[1])}" for r in evals_results)
+
+
+def load_webarena_challenges(
+ skip_unavailable: bool = True
+) -> Iterator[type[WebArenaChallenge]]:
+ logger.info("Loading WebArena challenges...")
+
+ for site, info in site_info_map.items():
+ if not info.available and skip_unavailable:
+ logger.warning(
+ f"JungleGym site '{site}' is not available: {info.unavailable_reason} "
+ "Skipping all challenges which use this site."
+ )
+
+ # response = requests.get("https://api.junglegym.ai/get_full_webarena_dataset")
+ # challenge_dicts = response.json()["data"]
+
+ # Until the full WebArena challenge set is supported, use a hand-picked selection
+ import json
+ from pathlib import Path
+
+ challenge_dicts = json.loads(
+ (Path(__file__).parent / "webarena_selection.json").read_bytes()
+ )
+
+ logger.debug(
+ "Fetched WebArena dataset. "
+ f"Constructing {len(challenge_dicts)} WebArenaChallenges..."
+ )
+ loaded = 0
+ failed = 0
+ skipped = 0
+ for entry in challenge_dicts:
+ try:
+ challenge_spec = WebArenaChallengeSpec.parse_obj(entry)
+ except ValidationError as e:
+ failed += 1
+ logger.warning(f"Error validating WebArena challenge entry: {entry}")
+ logger.warning(f"Error details: {e}")
+ continue
+
+ # Check all required sites for availability
+ for site in challenge_spec.sites:
+ site_info = site_info_map.get(site)
+ if site_info is None:
+ challenge_spec.available = False
+ challenge_spec.unavailable_reason = (
+ f"WebArena task {challenge_spec.task_id} requires unknown site "
+ f"'{site}'"
+ )
+ elif not site_info.available:
+ challenge_spec.available = False
+ challenge_spec.unavailable_reason = (
+ f"WebArena task {challenge_spec.task_id} requires unavailable "
+ f"site '{site}'"
+ )
+
+ if not challenge_spec.available and skip_unavailable:
+ logger.debug(f"{challenge_spec.unavailable_reason}; skipping...")
+ skipped += 1
+ continue
+
+ yield WebArenaChallenge.from_challenge_spec(challenge_spec)
+ loaded += 1
+
+ logger.info(
+ "Loading WebArena challenges complete: "
+ f"loaded {loaded}, skipped {skipped}."
+ + (f" {failed} challenges failed to load." if failed else "")
+ )
diff --git a/benchmark/agbenchmark/challenges/webarena_selection.json b/benchmark/agbenchmark/challenges/webarena_selection.json
new file mode 100644
index 000000000..af06c7133
--- /dev/null
+++ b/benchmark/agbenchmark/challenges/webarena_selection.json
@@ -0,0 +1,523 @@
+[
+ {
+ "sites": [
+ "shopping_admin"
+ ],
+ "task_id": 0,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_admin_state.json",
+ "start_url": "http://cms.junglegym.ai/admin",
+ "geolocation": "NaN",
+ "intent_template": "What is the top-{{n}} best-selling product in {{year}}",
+ "instantiation_dict": {
+ "n": 1,
+ "year": 2022
+ },
+ "intent": "What is the top-1 best-selling product in 2022",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "exact_match": "Quest Lumaflex™ Band"
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "Quest Lumaflex™ Band"
+ },
+ "intent_template_id": 279,
+ "string_note": null,
+ "start_url_junglegym": "http://cms.junglegym.ai/admin"
+ },
+ {
+ "sites": [
+ "shopping_admin"
+ ],
+ "task_id": 4,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_admin_state.json",
+ "start_url": "http://cms.junglegym.ai/admin",
+ "geolocation": "NaN",
+ "intent_template": "What are the top-{{n}} best-selling product in {{period}}",
+ "instantiation_dict": {
+ "n": 3,
+ "period": "Jan 2023"
+ },
+ "intent": "What are the top-3 best-selling product in Jan 2023",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "Impulse Duffle",
+ "Overnight Duffle",
+ "Hawkeye Yoga Short-32-Blue"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "Impulse Duffle, Overnight Duffle, Hawkeye Yoga Short-32-Blue"
+ },
+ "intent_template_id": 279,
+ "string_note": null,
+ "start_url_junglegym": "http://cms.junglegym.ai/admin"
+ },
+ {
+ "sites": [
+ "shopping_admin"
+ ],
+ "task_id": 6,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_admin_state.json",
+ "start_url": "http://cms.junglegym.ai/admin",
+ "geolocation": "NaN",
+ "intent_template": "What are the top-{{n}} best-selling product in {{year}}",
+ "instantiation_dict": {
+ "n": 5,
+ "year": 2023
+ },
+ "intent": "What are the top-5 best-selling product in 2023",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "Sprite Yoga Strap 6 foot",
+ "Overnight Duffle",
+ "Ida Workout Parachute Pant-29-Purple",
+ "Hawkeye Yoga Short-32-Blue",
+ "Sprite Stasis Ball 65 cm"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "Sprite Yoga Strap 6 foot, Overnight Duffle, Ida Workout Parachute Pant-29-Purple, Hawkeye Yoga Short-32-Blue, Sprite Stasis Ball 65 cm"
+ },
+ "intent_template_id": 279,
+ "string_note": null,
+ "start_url_junglegym": "http://cms.junglegym.ai/admin"
+ },
+ {
+ "sites": [
+ "shopping_admin"
+ ],
+ "task_id": 11,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_admin_state.json",
+ "start_url": "http://cms.junglegym.ai/admin",
+ "geolocation": "NaN",
+ "intent_template": "Tell me the the number of reviews that our store received by far that mention term \"{{term}}\"",
+ "instantiation_dict": {
+ "term": "disappointed"
+ },
+ "intent": "Tell me the the number of reviews that our store received by far that mention term \"disappointed\"",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "6"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "6"
+ },
+ "intent_template_id": 288,
+ "string_note": null,
+ "start_url_junglegym": "http://cms.junglegym.ai/admin"
+ },
+ {
+ "sites": [
+ "shopping"
+ ],
+ "task_id": 21,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_state.json",
+ "start_url": "http://shop.junglegym.ai/6s-wireless-headphones-over-ear-noise-canceling-hi-fi-bass-foldable-stereo-wireless-kid-headsets-earbuds-with-built-in-mic-micro-sd-tf-fm-for-iphone-samsung-ipad-pc-black-gold.html",
+ "geolocation": "NaN",
+ "intent_template": "List out reviewers, if exist, who mention about {{description}}",
+ "instantiation_dict": {
+ "description": "ear cups being small"
+ },
+ "intent": "List out reviewers, if exist, who mention about ear cups being small",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "Joseph Brzezinski",
+ "Catso",
+ "Dibbins",
+ "Anglebert Dinkherhump",
+ "Michelle Davis"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "Joseph Brzezinski, Catso, Dibbins, Anglebert Dinkherhump, Michelle Davis"
+ },
+ "intent_template_id": 222,
+ "string_note": null,
+ "start_url_junglegym": "http://shop.junglegym.ai"
+ },
+ {
+ "sites": [
+ "reddit"
+ ],
+ "task_id": 27,
+ "require_login": true,
+ "storage_state": "./.auth/reddit_state.json",
+ "start_url": "http://forum.junglegym.ai",
+ "geolocation": "NaN",
+ "intent_template": "Tell me the count of comments that have received more downvotes than upvotes for the user who made the latest post on the {{forum}} forum.",
+ "instantiation_dict": {
+ "forum": "Showerthoughts"
+ },
+ "intent": "Tell me the count of comments that have received more downvotes than upvotes for the user who made the latest post on the Showerthoughts forum.",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "0"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "0"
+ },
+ "intent_template_id": 33,
+ "string_note": null,
+ "start_url_junglegym": "http://forum.junglegym.ai"
+ },
+ {
+ "sites": [
+ "shopping_admin"
+ ],
+ "task_id": 43,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_admin_state.json",
+ "start_url": "http://cms.junglegym.ai/admin",
+ "geolocation": "NaN",
+ "intent_template": "List the top {{n}} search terms in my store",
+ "instantiation_dict": {
+ "n": "3"
+ },
+ "intent": "List the top 3 search terms in my store",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "hollister",
+ "Joust Bag",
+ "Antonia Race Tank"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "hollister, Joust Bag, Antonia Race Tank"
+ },
+ "intent_template_id": 285,
+ "string_note": null,
+ "start_url_junglegym": "http://cms.junglegym.ai/admin"
+ },
+ {
+ "sites": [
+ "shopping_admin"
+ ],
+ "task_id": 77,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_admin_state.json",
+ "start_url": "http://cms.junglegym.ai/admin",
+ "geolocation": "NaN",
+ "intent_template": "What is the total count of {{status}} reviews amongst all the reviews?",
+ "instantiation_dict": {
+ "status": "Pending"
+ },
+ "intent": "What is the total count of Pending reviews amongst all the reviews?",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "5"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "5"
+ },
+ "intent_template_id": 277,
+ "string_note": null,
+ "start_url_junglegym": "http://cms.junglegym.ai/admin"
+ },
+ {
+ "sites": [
+ "shopping_admin"
+ ],
+ "task_id": 95,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_admin_state.json",
+ "start_url": "http://cms.junglegym.ai/admin",
+ "geolocation": "NaN",
+ "intent_template": "Telll me the grand total of invoice {{id}}.",
+ "instantiation_dict": {
+ "id": "000000002"
+ },
+ "intent": "Telll me the grand total of invoice 000000002.",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "39.64"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "$39.64"
+ },
+ "intent_template_id": 274,
+ "string_note": null,
+ "start_url_junglegym": "http://cms.junglegym.ai/admin"
+ },
+ {
+ "sites": [
+ "shopping_admin"
+ ],
+ "task_id": 107,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_admin_state.json",
+ "start_url": "http://cms.junglegym.ai/admin",
+ "geolocation": "NaN",
+ "intent_template": "Presents the monthly count of successful orders {{period}} in MM:COUNT format",
+ "instantiation_dict": {
+ "period": "from May to December 2022"
+ },
+ "intent": "Presents the monthly count of successful orders from May to December 2022 in MM:COUNT format",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "fuzzy_match": [
+ "May: 8 orders",
+ "June: 13 orders",
+ "July: 9 orders",
+ "August: 8 orders",
+ "September: 10 orders",
+ "October: 4 orders",
+ "November: 5 orders",
+ "December: 10 orders"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "May: 8 orders; June: 13 orders; July: 9 orders; August: 8 orders; September: 10 orders; October: 4 orders; November: 5 orders; December: 10 orders"
+ },
+ "intent_template_id": 270,
+ "string_note": null,
+ "start_url_junglegym": "http://cms.junglegym.ai/admin"
+ },
+ {
+ "sites": [
+ "shopping_admin"
+ ],
+ "task_id": 112,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_admin_state.json",
+ "start_url": "http://cms.junglegym.ai/admin",
+ "geolocation": "NaN",
+ "intent_template": "Show me the customers who have expressed dissatisfaction with {{product}}?",
+ "instantiation_dict": {
+ "product": "Circe fleece"
+ },
+ "intent": "Show me the customers who have expressed dissatisfaction with Circe fleece?",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "exact_match": "Hannah Lim"
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "Hannah Lim"
+ },
+ "intent_template_id": 245,
+ "string_note": null,
+ "start_url_junglegym": "http://cms.junglegym.ai/admin"
+ },
+ {
+ "sites": [
+ "shopping"
+ ],
+ "task_id": 124,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_state.json",
+ "start_url": "http://shop.junglegym.ai",
+ "geolocation": "NaN",
+ "intent_template": "What is the price range of {{product}} in the One Stop Market?",
+ "instantiation_dict": {
+ "product": "wireless earphone"
+ },
+ "intent": "What is the price range of wireless earphone in the One Stop Market?",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "0.14",
+ "745.00"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "$0.14 - $745.00"
+ },
+ "intent_template_id": 159,
+ "string_note": null,
+ "start_url_junglegym": "http://shop.junglegym.ai"
+ },
+ {
+ "sites": [
+ "gitlab"
+ ],
+ "task_id": 134,
+ "require_login": true,
+ "storage_state": "./.auth/gitlab_state.json",
+ "start_url": "http://git.junglegym.ai",
+ "geolocation": "NaN",
+ "intent_template": "How many commits did {{user}} make to {{repo}} on {{date}}?",
+ "instantiation_dict": {
+ "user": "kilian",
+ "repo": "a11yproject",
+ "date": "3/1/2023"
+ },
+ "intent": "How many commits did kilian make to a11yproject on 3/1/2023?",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "0"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "0"
+ },
+ "intent_template_id": 322,
+ "string_note": null,
+ "start_url_junglegym": "http://git.junglegym.ai"
+ },
+ {
+ "sites": [
+ "gitlab"
+ ],
+ "task_id": 136,
+ "require_login": true,
+ "storage_state": "./.auth/gitlab_state.json",
+ "start_url": "http://git.junglegym.ai",
+ "geolocation": "NaN",
+ "intent_template": "How many commits did {{user}} make to {{repo}} on {{date}}?",
+ "instantiation_dict": {
+ "user": "Steven Woodson",
+ "repo": "a11y-webring.club",
+ "date": "2/6/2023"
+ },
+ "intent": "How many commits did Steven Woodson make to a11y-webring.club on 2/6/2023?",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "5"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "5"
+ },
+ "intent_template_id": 322,
+ "string_note": null,
+ "start_url_junglegym": "http://git.junglegym.ai"
+ },
+ {
+ "sites": [
+ "shopping"
+ ],
+ "task_id": 163,
+ "require_login": true,
+ "storage_state": "./.auth/shopping_state.json",
+ "start_url": "http://shop.junglegym.ai/ostent-16gb-memory-card-stick-storage-for-sony-ps-vita-psv1000-2000-pch-z081-z161-z321-z641.html",
+ "geolocation": "NaN",
+ "intent_template": "What are the main criticisms of this product? Please extract the relevant sentences.",
+ "instantiation_dict": {},
+ "intent": "What are the main criticisms of this product? Please extract the relevant sentences.",
+ "require_reset": false,
+ "eval": {
+ "eval_types": [
+ "string_match"
+ ],
+ "reference_answers": {
+ "must_include": [
+ "I ordered the 16gb but I only got 14 gigs even though I formatted the card",
+ "The memory card is kind of slow on games and downloads",
+ "No original packaging It's used and the previous owners data has not been erased",
+ "The product is a legit sony hardware that have been owned by someone else before",
+ "The media could not be loaded",
+ "I could not format the card so I wasn’t able to use it for my VITA"
+ ]
+ },
+ "reference_url": "",
+ "program_html": [],
+ "string_note": "",
+ "reference_answer_raw_annotation": "I ordered the 16gb but I only got 14 gigs even though I formatted the card. The memory card is kind of slow on games and downloads. No original packaging It's used and the previous owners data has not been erased. The product is a legit sony hardware that have been owned by someone else before The media could not be loaded. I could not format the card so I wasn’t able to use it for my VITA"
+ },
+ "intent_template_id": 136,
+ "string_note": null,
+ "start_url_junglegym": "http://shop.junglegym.ai"
+ }
+]
diff --git a/benchmark/agbenchmark/config.py b/benchmark/agbenchmark/config.py
new file mode 100644
index 000000000..ec8974bea
--- /dev/null
+++ b/benchmark/agbenchmark/config.py
@@ -0,0 +1,127 @@
+import json
+import sys
+from datetime import datetime
+from pathlib import Path
+from typing import Optional
+
+from pydantic import BaseSettings, Field, validator
+
+
+def _calculate_info_test_path(base_path: Path, benchmark_start_time: datetime) -> Path:
+ """
+ Calculates the path to the directory where the test report will be saved.
+ """
+ # Ensure the reports path exists
+ base_path.mkdir(parents=True, exist_ok=True)
+
+ # Get current UTC date-time stamp
+ date_stamp = benchmark_start_time.strftime("%Y%m%dT%H%M%S")
+
+ # Default run name
+ run_name = "full_run"
+
+ # Map command-line arguments to their respective labels
+ arg_labels = {
+ "--test": None,
+ "--category": None,
+ "--maintain": "maintain",
+ "--improve": "improve",
+ "--explore": "explore",
+ }
+
+ # Identify the relevant command-line argument
+ for arg, label in arg_labels.items():
+ if arg in sys.argv:
+ test_arg = sys.argv[sys.argv.index(arg) + 1] if label is None else None
+ run_name = arg.strip("--")
+ if test_arg:
+ run_name = f"{run_name}_{test_arg}"
+ break
+
+ # Create the full new directory path with ISO standard UTC date-time stamp
+ report_path = base_path / f"{date_stamp}_{run_name}"
+
+ # Ensure the new directory is created
+ # FIXME: this is not a desirable side-effect of loading the config
+ report_path.mkdir(exist_ok=True)
+
+ return report_path
+
+
+class AgentBenchmarkConfig(BaseSettings, extra="allow"):
+ """
+ Configuration model and loader for the AGBenchmark.
+
+ Projects that want to use AGBenchmark should contain an agbenchmark_config folder
+ with a config.json file that - at minimum - specifies the `host` at which the
+ subject application exposes an Agent Protocol compliant API.
+ """
+
+ agbenchmark_config_dir: Path = Field(..., exclude=True)
+ """Path to the agbenchmark_config folder of the subject agent application."""
+
+ categories: list[str] | None = None
+ """Categories to benchmark the agent for. If omitted, all categories are assumed."""
+
+ host: str
+ """Host (scheme://address:port) of the subject agent application."""
+
+ reports_folder: Path = Field(None)
+ """
+ Path to the folder where new reports should be stored.
+ Defaults to {agbenchmark_config_dir}/reports.
+ """
+
+ @classmethod
+ def load(cls, config_dir: Optional[Path] = None) -> "AgentBenchmarkConfig":
+ config_dir = config_dir or cls.find_config_folder()
+ with (config_dir / "config.json").open("r") as f:
+ return cls(
+ agbenchmark_config_dir=config_dir,
+ **json.load(f),
+ )
+
+ @staticmethod
+ def find_config_folder(for_dir: Path = Path.cwd()) -> Path:
+ """
+ Find the closest ancestor folder containing an agbenchmark_config folder,
+ and returns the path of that agbenchmark_config folder.
+ """
+ current_directory = for_dir
+ while current_directory != Path("/"):
+ if (path := current_directory / "agbenchmark_config").exists():
+ if (path / "config.json").is_file():
+ return path
+ current_directory = current_directory.parent
+ raise FileNotFoundError(
+ "No 'agbenchmark_config' directory found in the path hierarchy."
+ )
+
+ @property
+ def config_file(self) -> Path:
+ return self.agbenchmark_config_dir / "config.json"
+
+ @validator("reports_folder", pre=True, always=True)
+ def set_reports_folder(cls, v, values):
+ if not v:
+ return values["agbenchmark_config_dir"] / "reports"
+ return v
+
+ def get_report_dir(self, benchmark_start_time: datetime) -> Path:
+ return _calculate_info_test_path(self.reports_folder, benchmark_start_time)
+
+ @property
+ def regression_tests_file(self) -> Path:
+ return self.reports_folder / "regression_tests.json"
+
+ @property
+ def success_rate_file(self) -> Path:
+ return self.reports_folder / "success_rate.json"
+
+ @property
+ def challenges_already_beaten_file(self) -> Path:
+ return self.agbenchmark_config_dir / "challenges_already_beaten.json"
+
+ @property
+ def temp_folder(self) -> Path:
+ return self.agbenchmark_config_dir / "temp_folder"
diff --git a/benchmark/agbenchmark/conftest.py b/benchmark/agbenchmark/conftest.py
index 71db82e01..cf40493b5 100644
--- a/benchmark/agbenchmark/conftest.py
+++ b/benchmark/agbenchmark/conftest.py
@@ -1,277 +1,189 @@
import contextlib
import json
+import logging
import os
import shutil
-import sys
import threading
import time
-from pathlib import Path # noqa
-from typing import Any, Generator
+from pathlib import Path
+from typing import Generator
import pytest
-from agbenchmark.__main__ import TEMP_FOLDER_ABS_PATH
+from agbenchmark.challenges import OPTIONAL_CATEGORIES, BaseChallenge
+from agbenchmark.config import AgentBenchmarkConfig
+from agbenchmark.reports.processing.report_types import Test
+from agbenchmark.reports.ReportManager import RegressionTestsTracker
from agbenchmark.reports.reports import (
- finalize_reports,
- generate_single_call_report,
+ add_test_result_to_report,
+ make_empty_test_report,
session_finish,
)
-from agbenchmark.utils.data_types import AgentBenchmarkConfig
+from agbenchmark.utils.data_types import Category
GLOBAL_TIMEOUT = (
1500 # The tests will stop after 25 minutes so we can send the reports.
)
+agbenchmark_config = AgentBenchmarkConfig.load()
+logger = logging.getLogger(__name__)
+
pytest_plugins = ["agbenchmark.utils.dependencies"]
collect_ignore = ["challenges"]
-suite_reports: dict[str, list] = {}
-
-
-def load_config_from_request(request: Any) -> AgentBenchmarkConfig:
- """
- This function loads the configuration for the agent benchmark from a given request.
-
- Args:
- request (Any): The request object from which the agent benchmark configuration is to be loaded.
-
- Returns:
- AgentBenchmarkConfig: The loaded agent benchmark configuration.
-
- Raises:
- json.JSONDecodeError: If the benchmark configuration file is not a valid JSON file.
- """
- agent_benchmark_config_path = Path.cwd() / "agbenchmark_config" / "config.json"
- try:
- with open(agent_benchmark_config_path, "r") as f:
- agent_benchmark_config = AgentBenchmarkConfig(**json.load(f))
- agent_benchmark_config.agent_benchmark_config_path = (
- agent_benchmark_config_path
- )
- return agent_benchmark_config
- except json.JSONDecodeError:
- print("Error: benchmark_config.json is not a valid JSON file.")
- raise
@pytest.fixture(scope="module")
-def config(request: Any) -> Any:
- """
- This pytest fixture is responsible for loading the agent benchmark configuration from a given request.
- This fixture is scoped to the module level, meaning it's invoked once per test module.
-
- Args:
- request (Any): The request object from which the agent benchmark configuration is to be loaded.
-
- Returns:
- Any: The loaded configuration dictionary.
-
- Raises:
- json.JSONDecodeError: If the benchmark configuration file is not a valid JSON file.
- """
- config = {}
- agent_benchmark_config_path = Path.cwd() / "agbenchmark_config" / "config.json"
- try:
- with open(agent_benchmark_config_path, "r") as f:
- agent_benchmark_config = AgentBenchmarkConfig(**json.load(f))
- agent_benchmark_config.agent_benchmark_config_path = (
- agent_benchmark_config_path
- )
- except json.JSONDecodeError:
- print("Error: benchmark_config.json is not a valid JSON file.")
- raise
-
- config["AgentBenchmarkConfig"] = agent_benchmark_config
-
- return config
+def config() -> AgentBenchmarkConfig:
+ return agbenchmark_config
@pytest.fixture(autouse=True)
-def temp_folder() -> Generator[str, None, None]:
+def temp_folder() -> Generator[Path, None, None]:
"""
- This pytest fixture is responsible for setting up and tearing down the temporary folder for each test.
+ Pytest fixture that sets up and tears down the temporary folder for each test.
It is automatically used in every test due to the 'autouse=True' parameter.
- It is used in order to let agbenchmark store files so they can then be evaluated.
"""
# create output directory if it doesn't exist
- if not os.path.exists(TEMP_FOLDER_ABS_PATH):
- os.makedirs(TEMP_FOLDER_ABS_PATH, exist_ok=True)
+ if not os.path.exists(agbenchmark_config.temp_folder):
+ os.makedirs(agbenchmark_config.temp_folder, exist_ok=True)
- yield
+ yield agbenchmark_config.temp_folder
# teardown after test function completes
if not os.getenv("KEEP_TEMP_FOLDER_FILES"):
- for filename in os.listdir(TEMP_FOLDER_ABS_PATH):
- file_path = os.path.join(TEMP_FOLDER_ABS_PATH, filename)
+ for filename in os.listdir(agbenchmark_config.temp_folder):
+ file_path = os.path.join(agbenchmark_config.temp_folder, filename)
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
except Exception as e:
- print(f"Failed to delete {file_path}. Reason: {e}")
+ logger.warning(f"Failed to delete {file_path}. Reason: {e}")
-def pytest_addoption(parser: Any) -> None:
+def pytest_addoption(parser: pytest.Parser) -> None:
"""
- This function is a pytest hook that is called to add command-line options.
- It is used to add custom command-line options that are specific to the agent benchmark tests.
- These options can be used to control the behavior of the tests.
- The "--mock" option is used to run the tests in mock mode.
- The "--host" option is used to specify the host for the tests.
- The "--category" option is used to run only tests of a specific category.
- The "--nc" option is used to run the tests without caching.
- The "--cutoff" option is used to specify a cutoff time for the tests.
- The "--improve" option is used to run only the tests that are marked for improvement.
- The "--maintain" option is used to run only the tests that are marked for maintenance.
- The "--explore" option is used to run the tests in exploration mode.
- The "--test" option is used to run a specific test.
- The "--no_dep" option is used to run the tests without dependencies.
- The "--keep_answers" option is used to keep the answers of the tests.
+ Pytest hook that adds command-line options to the `pytest` command.
+ The added options are specific to agbenchmark and control its behavior:
+ * `--mock` is used to run the tests in mock mode.
+ * `--host` is used to specify the host for the tests.
+ * `--category` is used to run only tests of a specific category.
+ * `--nc` is used to run the tests without caching.
+ * `--cutoff` is used to specify a cutoff time for the tests.
+ * `--improve` is used to run only the tests that are marked for improvement.
+ * `--maintain` is used to run only the tests that are marked for maintenance.
+ * `--explore` is used to run the tests in exploration mode.
+ * `--test` is used to run a specific test.
+ * `--no-dep` is used to run the tests without dependencies.
+ * `--keep-answers` is used to keep the answers of the tests.
Args:
- parser (Any): The parser object to which the command-line options are added.
+ parser: The Pytest CLI parser to which the command-line options are added.
"""
- parser.addoption("--no_dep", action="store_true", default=False)
- parser.addoption("--mock", action="store_true", default=False)
- parser.addoption("--host", action="store_true", default=None)
- parser.addoption("--nc", action="store_true", default=False)
- parser.addoption("--cutoff", action="store_true", default=False)
- parser.addoption("--category", action="store_true", default=False)
- parser.addoption("--test", action="store_true", default=None)
- parser.addoption("--improve", action="store_true", default=False)
- parser.addoption("--maintain", action="store_true", default=False)
- parser.addoption("--explore", action="store_true", default=False)
- parser.addoption("--keep-answers", action="store_true", default=False)
+ parser.addoption("-N", "--attempts", action="store")
+ parser.addoption("--no-dep", action="store_true")
+ parser.addoption("--mock", action="store_true")
+ parser.addoption("--host", default=None)
+ parser.addoption("--nc", action="store_true")
+ parser.addoption("--cutoff", action="store")
+ parser.addoption("--category", action="append")
+ parser.addoption("--test", action="append")
+ parser.addoption("--improve", action="store_true")
+ parser.addoption("--maintain", action="store_true")
+ parser.addoption("--explore", action="store_true")
+ parser.addoption("--keep-answers", action="store_true")
+
+
+def pytest_configure(config: pytest.Config) -> None:
+ # Register category markers to prevent "unknown marker" warnings
+ for category in Category:
+ config.addinivalue_line("markers", f"{category.value}: {category}")
@pytest.fixture(autouse=True)
-def check_regression(request: Any) -> None:
+def check_regression(request: pytest.FixtureRequest) -> None:
"""
- This pytest fixture is responsible for checking if a test is a regression test.
- It is automatically used in every test due to the 'autouse=True' parameter.
- The test name and the agent benchmark configuration are retrieved from the request object.
- The regression reports are loaded from the path specified in the agent benchmark configuration.
- If the "--improve" option is used and the test name exists in the regression tests, the test is skipped.
- If the "--maintain" option is used and the test name does not exist in the regression tests, the test is also skipped.
+ Fixture that checks for every test if it should be treated as a regression test,
+ and whether to skip it based on that.
+
+ The test name is retrieved from the `request` object. Regression reports are loaded
+ from the path specified in the benchmark configuration.
+
+ Effect:
+ * If the `--improve` option is used and the current test is considered a regression
+ test, it is skipped.
+ * If the `--maintain` option is used and the current test is not considered a
+ regression test, it is also skipped.
Args:
- request (Any): The request object from which the test name and the agent benchmark configuration are retrieved.
+ request: The request object from which the test name and the benchmark
+ configuration are retrieved.
"""
- test_name = request.node.parent.name
- agent_benchmark_config = load_config_from_request(request)
- with contextlib.suppress(Exception):
- test = agent_benchmark_config.get_regression_reports_path()
- data = json.loads(test)
- challenge_location = getattr(request.node.parent.cls, "CHALLENGE_LOCATION", "")
+ with contextlib.suppress(FileNotFoundError):
+ rt_tracker = RegressionTestsTracker(agbenchmark_config.regression_tests_file)
+ test_name = request.node.parent.name
+ challenge_location = getattr(request.node.parent.cls, "CHALLENGE_LOCATION", "")
skip_string = f"Skipping {test_name} at {challenge_location}"
# Check if the test name exists in the regression tests
- if request.config.getoption("--improve") and data.get(test_name, None):
+ is_regression_test = rt_tracker.has_regression_test(test_name)
+ if request.config.getoption("--improve") and is_regression_test:
pytest.skip(f"{skip_string} because it's a regression test")
- elif request.config.getoption("--maintain") and not data.get(test_name, None):
+ elif request.config.getoption("--maintain") and not is_regression_test:
pytest.skip(f"{skip_string} because it's not a regression test")
-# this is to get the challenge_data from every test
-@pytest.fixture(autouse=True)
-def challenge_data(request: Any) -> None:
- """
- This pytest fixture is responsible for providing the challenge data for each test.
- It is automatically used in every test due to the 'autouse=True' parameter.
- The challenge data is retrieved from the request object's parameters.
- This fixture is essential for the pytest system as it provides the necessary data for each test.
-
- Args:
- request (Any): The request object from which the challenge data is retrieved.
-
- Returns:
- None: The challenge data is directly passed to the test function and does not need to be returned.
- """
- return request.param
-
-
@pytest.fixture(autouse=True, scope="session")
-def mock(request: Any) -> None:
+def mock(request: pytest.FixtureRequest) -> bool:
"""
- This pytest fixture is responsible for retrieving the value of the "--mock" command-line option.
- It is automatically used in every test session due to the 'autouse=True' parameter and 'session' scope.
- The "--mock" option is used to run the tests in mock mode.
- This fixture is essential for the pytest system as it provides the necessary command-line option value for each test session.
+ Pytest fixture that retrieves the value of the `--mock` command-line option.
+ The `--mock` option is used to run the tests in mock mode.
Args:
- request (Any): The request object from which the "--mock" option value is retrieved.
+ request: The `pytest.FixtureRequest` from which the `--mock` option value
+ is retrieved.
Returns:
- None: The "--mock" option value is directly passed to the test session and does not need to be returned.
+ bool: Whether `--mock` is set for this session.
"""
return request.config.getoption("--mock")
-@pytest.fixture(autouse=True, scope="function")
-def timer(request: Any) -> Any:
- """
- This pytest fixture is responsible for timing the execution of each test.
- It is automatically used in every test due to the 'autouse=True' parameter and 'function' scope.
- At the start of each test, it records the current time.
- After the test function completes, it calculates the run time and appends it to the test node's user properties.
- This allows the run time of each test to be accessed later for reporting or analysis.
-
- Args:
- request (Any): The request object from which the test node is retrieved.
-
- Yields:
- None: Control is yielded back to the test function.
- """
- start_time = time.time()
- yield
- run_time = time.time() - start_time
- request.node.user_properties.append(("run_time", run_time))
+test_reports: dict[str, Test] = {}
-def pytest_runtest_makereport(item: Any, call: Any) -> None:
+def pytest_runtest_makereport(item: pytest.Item, call: pytest.CallInfo) -> None:
"""
- This function is a pytest hook that is called when a test report is being generated.
+ Pytest hook that is called when a test report is being generated.
It is used to generate and finalize reports for each test.
Args:
- item (Any): The test item for which the report is being generated.
- call (Any): The call object from which the test result is retrieved.
+ item: The test item for which the report is being generated.
+ call: The call object from which the test result is retrieved.
"""
- challenge_data = item.funcargs.get("challenge_data", None)
+ challenge: type[BaseChallenge] = item.cls # type: ignore
+ challenge_id = challenge.info.eval_id
- if not challenge_data:
- # this will only happen for dummy dependency setup tests
- return
+ if challenge_id not in test_reports:
+ test_reports[challenge_id] = make_empty_test_report(challenge.info)
- challenge_location: str = getattr(item.cls, "CHALLENGE_LOCATION", "")
-
- flags = (
- "--test" in sys.argv
- or "--maintain" in sys.argv
- or "--improve" in sys.argv
- or "--explore" in sys.argv
- )
-
- if call.when == "call":
- answers = getattr(item, "answers", None)
- challenge_location: str = getattr(item.cls, "CHALLENGE_LOCATION", "")
+ if call.when == "setup":
test_name = item.nodeid.split("::")[1]
- item.test_name = test_name
+ item.user_properties.append(("test_name", test_name))
- generate_single_call_report(
- item, call, challenge_data, answers, challenge_location, test_name
+ if call.when == "call":
+ add_test_result_to_report(
+ test_reports[challenge_id], item, call, agbenchmark_config
)
- if call.when == "teardown":
- finalize_reports(item, challenge_data)
-
def timeout_monitor(start_time: int) -> None:
"""
- This function is responsible for monitoring the total execution time of the test suite.
- It runs in a separate thread and checks every second if the total execution time has exceeded the global timeout.
- If the global timeout is exceeded, it terminates the pytest session with a specific return code.
+ Function that limits the total execution time of the test suite.
+ This function is supposed to be run in a separate thread and calls `pytest.exit`
+ if the total execution time has exceeded the global timeout.
Args:
start_time (int): The start time of the test suite.
@@ -282,14 +194,11 @@ def timeout_monitor(start_time: int) -> None:
pytest.exit("Test suite exceeded the global timeout", returncode=1)
-def pytest_sessionstart(session: Any) -> None:
+def pytest_sessionstart(session: pytest.Session) -> None:
"""
- This function is a pytest hook that is called at the start of the test session.
- It starts the timeout monitor in a separate thread.
- The timeout monitor checks if the total execution time of the test suite has exceeded the global timeout.
+ Pytest hook that is called at the start of a test session.
- Args:
- session (Any): The pytest session object.
+ Sets up and runs a `timeout_monitor` in a separate thread.
"""
start_time = time.time()
t = threading.Thread(target=timeout_monitor, args=(start_time,))
@@ -297,94 +206,129 @@ def pytest_sessionstart(session: Any) -> None:
t.start()
-def pytest_sessionfinish(session: Any) -> None:
- """
- This function is a pytest hook that is called at the end of the test session.
- It is used to finalize and save the test reports.
- The reports are saved in a specific location defined in the suite reports.
-
- Args:
- session (Any): The pytest session object.
+def pytest_sessionfinish(session: pytest.Session) -> None:
"""
- session_finish(suite_reports)
-
+ Pytest hook that is called at the end of a test session.
-@pytest.fixture
-def scores(request: Any) -> None:
+ Finalizes and saves the test reports.
"""
- This pytest fixture is responsible for retrieving the scores of the test class.
- The scores are retrieved from the test class's 'scores' attribute using the test class name.
- This fixture is essential for the pytest system as it provides the necessary scores for each test.
+ session_finish(agbenchmark_config)
- Args:
- request (Any): The request object from which the test class is retrieved.
- Returns:
- None: The scores are directly passed to the test function and do not need to be returned.
- """
- test_class_name = request.node.cls.__name__
- return request.node.cls.scores.get(test_class_name)
+def pytest_generate_tests(metafunc: pytest.Metafunc):
+ n = metafunc.config.getoption("-N")
+ metafunc.parametrize("i_attempt", range(int(n)) if type(n) is str else [0])
-# this is adding the dependency marker and category markers automatically from the json
-def pytest_collection_modifyitems(items: Any, config: Any) -> None:
+def pytest_collection_modifyitems(
+ items: list[pytest.Item], config: pytest.Config
+) -> None:
"""
- This function is a pytest hook that is called after the test collection has been performed.
- It is used to modify the collected test items based on the agent benchmark configuration.
- The function loads the agent benchmark configuration from the specified path and retrieves the regression reports.
- For each test item, it checks if the test method exists and retrieves the dependencies and categories from the test class instance.
- If the "--improve" or "--category" options are used, the dependencies are filtered based on the regression data.
- If the "--test", "--no_dep", or "--maintain" options are used, the dependencies are cleared.
- The function then dynamically adds the 'depends' and 'category' markers to the test item.
- This function is essential for the pytest system as it provides the necessary modification of the test items based on the agent benchmark configuration.
+ Pytest hook that is called after initial test collection has been performed.
+ Modifies the collected test items based on the agent benchmark configuration,
+ adding the dependency marker and category markers.
Args:
- items (Any): The collected test items to be modified.
- config (Any): The pytest configuration object from which the agent benchmark configuration path is retrieved.
+ items: The collected test items to be modified.
+ config: The active pytest configuration.
"""
- agent_benchmark_config_path = str(Path.cwd() / "agbenchmark_config" / "config.json")
+ rt_tracker = RegressionTestsTracker(agbenchmark_config.regression_tests_file)
+
try:
- with open(agent_benchmark_config_path) as f:
- agent_benchmark_config = AgentBenchmarkConfig(**json.load(f))
- except json.JSONDecodeError:
- print("Error: benchmark_config.json is not a valid JSON file.")
- raise
-
- regression_file = agent_benchmark_config.get_regression_reports_path()
- data = (
- json.loads(open(regression_file, "r").read())
- if os.path.exists(regression_file)
- else {}
- )
-
- for item in items:
- # Assuming item.cls is your test class
- test_class_instance = item.cls()
-
- if "test_method" not in item.name:
+ challenges_beaten_in_the_past = json.loads(
+ agbenchmark_config.challenges_already_beaten_file.read_bytes()
+ )
+ except FileNotFoundError:
+ challenges_beaten_in_the_past = {}
+
+ selected_tests: tuple[str] = config.getoption("--test") # type: ignore
+ selected_categories: tuple[str] = config.getoption("--category") # type: ignore
+
+ # Can't use a for-loop to remove items in-place
+ i = 0
+ while i < len(items):
+ item = items[i]
+ challenge = item.cls
+ challenge_name = item.cls.__name__
+
+ if not issubclass(challenge, BaseChallenge):
+ item.warn(
+ pytest.PytestCollectionWarning(
+ f"Non-challenge item collected: {challenge}"
+ )
+ )
+ i += 1
continue
- # Then you can access your properties
- name = item.parent.cls.__name__
- # dependencies = test_class_instance.data.dependencies
-
- # Filter dependencies if they exist in regression data if its an improvement test
- # if config.getoption("--improve") or config.getoption(
- # "--category"
- # ):
- # dependencies = [dep for dep in dependencies if not data.get(dep, None)]
- # if (
- # config.getoption("--test")
- # or config.getoption("--no_dep")
- # or config.getoption("--maintain")
- # ):
- dependencies = test_class_instance.dependencies
-
- # Add depends marker dynamically
- item.add_marker(pytest.mark.depends(on=dependencies, name=name))
-
- categories = test_class_instance.data.category
-
- # Add category marker dynamically
- for category in categories:
- item.add_marker(getattr(pytest.mark, category))
+ # --test: remove the test from the set if it's not specifically selected
+ if selected_tests and challenge.info.name not in selected_tests:
+ items.remove(item)
+ continue
+
+ # Filter challenges for --maintain, --improve, and --explore:
+ # --maintain -> only challenges expected to be passed (= regression tests)
+ # --improve -> only challenges that so far are not passed (reliably)
+ # --explore -> only challenges that have never been passed
+ is_regression_test = rt_tracker.has_regression_test(challenge.info.name)
+ has_been_passed = challenges_beaten_in_the_past.get(challenge.info.name, False)
+ if (
+ (config.getoption("--maintain") and not is_regression_test)
+ or (config.getoption("--improve") and is_regression_test)
+ or (config.getoption("--explore") and has_been_passed)
+ ):
+ items.remove(item)
+ continue
+
+ dependencies = challenge.info.dependencies
+ if (
+ config.getoption("--test")
+ or config.getoption("--no-dep")
+ or config.getoption("--maintain")
+ ):
+ # Ignore dependencies:
+ # --test -> user selected specific tests to run, don't care about deps
+ # --no-dep -> ignore dependency relations regardless of test selection
+ # --maintain -> all "regression" tests must pass, so run all of them
+ dependencies = []
+ elif config.getoption("--improve"):
+ # Filter dependencies, keep only deps that are not "regression" tests
+ dependencies = [
+ d for d in dependencies if not rt_tracker.has_regression_test(d)
+ ]
+
+ # Set category markers
+ challenge_categories = set(c.value for c in challenge.info.category)
+ for category in challenge_categories:
+ item.add_marker(category)
+
+ # Enforce category selection
+ if selected_categories:
+ if not challenge_categories.intersection(set(selected_categories)):
+ items.remove(item)
+ continue
+ # # Filter dependencies, keep only deps from selected categories
+ # dependencies = [
+ # d for d in dependencies
+ # if not set(d.categories).intersection(set(selected_categories))
+ # ]
+
+ # Skip items in optional categories that are not selected for the subject agent
+ challenge_optional_categories = challenge_categories & set(OPTIONAL_CATEGORIES)
+ if challenge_optional_categories and not (
+ agbenchmark_config.categories
+ and challenge_optional_categories.issubset(
+ set(agbenchmark_config.categories)
+ )
+ ):
+ logger.debug(
+ f"Skipping {challenge_name}: "
+ f"category {' and '.join(challenge_optional_categories)} is optional, "
+ "and not explicitly selected in the benchmark config."
+ )
+ items.remove(item)
+ continue
+
+ # Add marker for the DependencyManager
+ item.add_marker(pytest.mark.depends(on=dependencies, name=challenge_name))
+
+ i += 1
diff --git a/benchmark/agbenchmark/execute_sub_process.py b/benchmark/agbenchmark/execute_sub_process.py
deleted file mode 100644
index b981e6be5..000000000
--- a/benchmark/agbenchmark/execute_sub_process.py
+++ /dev/null
@@ -1,79 +0,0 @@
-import platform
-import queue
-import select
-import subprocess
-import time
-from threading import Thread
-from typing import Any
-
-import psutil
-
-
-def run_linux_env(process: Any, start_time: float, timeout: float) -> None:
- while True:
- try:
- # This checks if there's data to be read from stdout without blocking.
- if process.stdout and select.select([process.stdout], [], [], 0)[0]:
- output = process.stdout.readline()
- print(output.strip())
- except Exception as e:
- continue
-
- # Check if process has ended, has no more output, or exceeded timeout
- if process.poll() is not None or (time.time() - start_time > timeout):
- break
-
- if time.time() - start_time > timeout:
- print("The Python function has exceeded the time limit and was terminated.")
- parent = psutil.Process(process.pid)
- for child in parent.children(recursive=True):
- child.kill()
- parent.kill()
-
- else:
- print("The Python function has finished running.")
-
-
-def enqueue_output(out: Any, my_queue: Any) -> None:
- for line in iter(out.readline, b""):
- my_queue.put(line)
- out.close()
-
-
-def run_windows_env(process: Any, start_time: float, timeout: float) -> None:
- my_queue: Any = queue.Queue()
- thread = Thread(target=enqueue_output, args=(process.stdout, my_queue))
- thread.daemon = True
- thread.start()
-
- while True:
- try:
- output = my_queue.get_nowait().strip()
- print(output)
- except queue.Empty:
- pass
-
- if process.poll() is not None or (time.time() - start_time > timeout):
- break
-
- if time.time() - start_time > timeout:
- print("The Python function has exceeded the time limit and was terminated.")
- process.terminate()
-
-
-def execute_subprocess(command, timeout):
- process = subprocess.Popen(
- command,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT,
- universal_newlines=True,
- bufsize=1,
- )
- start_time = time.time()
- if platform.system() == "Windows":
- run_windows_env(process, start_time, timeout)
- else:
- run_linux_env(process, start_time, timeout)
- process.wait()
- if process.returncode != 0:
- print(f"The agent timed out")
diff --git a/benchmark/agbenchmark/generate_test.py b/benchmark/agbenchmark/generate_test.py
index 363d53697..5bc41971e 100644
--- a/benchmark/agbenchmark/generate_test.py
+++ b/benchmark/agbenchmark/generate_test.py
@@ -1,223 +1,26 @@
-import glob
-import importlib
-import json
-import os
-import sys
-import types
-from collections import deque
-from pathlib import Path
-from typing import Any, Dict, Optional, Union
-
-import pytest
-
-from agbenchmark.__main__ import CHALLENGES_ALREADY_BEATEN
-from agbenchmark.agent_api_interface import append_updates_file
-from agbenchmark.agent_protocol_client.models.step import Step
-from agbenchmark.utils.challenge import Challenge
-from agbenchmark.utils.data_types import AgentBenchmarkConfig, ChallengeData
-
-DATA_CATEGORY = {}
-
-
-def create_single_test(
- data: Dict[str, Any] | ChallengeData,
- challenge_location: str,
- file_datum: Optional[list[dict[str, Any]]] = None,
-) -> None:
- challenge_data = None
- artifacts_location = None
- if isinstance(data, ChallengeData):
- challenge_data = data
- data = data.get_data()
-
- DATA_CATEGORY[data["name"]] = data["category"][0]
-
- # Define test class dynamically
- challenge_class = types.new_class(f"Test{data['name']}", (Challenge,))
- print(challenge_location)
- # clean_challenge_location = get_test_path(challenge_location)
- setattr(challenge_class, "CHALLENGE_LOCATION", challenge_location)
-
- setattr(
- challenge_class,
- "ARTIFACTS_LOCATION",
- artifacts_location or str(Path(challenge_location).resolve().parent),
- )
-
- # Define test method within the dynamically created class
- @pytest.mark.asyncio
- async def test_method(self, config: Dict[str, Any], request) -> None: # type: ignore
- # create a random number between 0 and 1
- test_name = self.data.name
-
- try:
- with open(CHALLENGES_ALREADY_BEATEN, "r") as f:
- challenges_beaten_in_the_past = json.load(f)
- except:
- challenges_beaten_in_the_past = {}
+"""
+AGBenchmark's test discovery endpoint for Pytest.
- if request.config.getoption("--explore") and challenges_beaten_in_the_past.get(
- test_name, False
- ):
- return None
+This module is picked up by Pytest's *_test.py file matching pattern, and all challenge
+classes in the module that conform to the `Test*` pattern are collected.
+"""
- # skip optional categories
- self.skip_optional_categories(config)
-
- from helicone.lock import HeliconeLockManager
-
- if os.environ.get("HELICONE_API_KEY"):
- HeliconeLockManager.write_custom_property("challenge", self.data.name)
-
- cutoff = self.data.cutoff or 60
-
- timeout = cutoff
- if "--nc" in sys.argv:
- timeout = 100000
- if "--cutoff" in sys.argv:
- timeout = int(sys.argv[sys.argv.index("--cutoff") + 1])
-
- await self.setup_challenge(config, timeout)
-
- scores = self.get_scores(config)
- request.node.answers = (
- scores["answers"] if "--keep-answers" in sys.argv else None
- )
- del scores["answers"] # remove answers from scores
- request.node.scores = scores # store scores in request.node
- is_score_100 = 1 in scores["values"]
-
- evaluation = "Correct!" if is_score_100 else "Incorrect."
- eval_step = Step(
- input=evaluation,
- additional_input=None,
- task_id="irrelevant, this step is a hack",
- step_id="irrelevant, this step is a hack",
- name="",
- status="created",
- output=None,
- additional_output=None,
- artifacts=[],
- is_last=True,
- )
- await append_updates_file(eval_step)
+import importlib
+import logging
+from itertools import chain
- assert is_score_100
+from agbenchmark.challenges.builtin import load_builtin_challenges
+from agbenchmark.challenges.webarena import load_webarena_challenges
- # Parametrize the method here
- test_method = pytest.mark.parametrize(
- "challenge_data",
- [data],
- indirect=True,
- )(test_method)
+logger = logging.getLogger(__name__)
- setattr(challenge_class, "test_method", test_method)
+DATA_CATEGORY = {}
- # Attach the new class to a module so it can be discovered by pytest
+# Load challenges and attach them to this module
+for challenge in chain(load_builtin_challenges(), load_webarena_challenges()):
+ # Attach the Challenge class to this module so it can be discovered by pytest
module = importlib.import_module(__name__)
- setattr(module, f"Test{data['name']}", challenge_class)
- return challenge_class
-
-
-def create_single_suite_challenge(challenge_data: ChallengeData, path: Path) -> None:
- create_single_test(challenge_data, str(path))
-
-
-def create_challenge(
- data: Dict[str, Any],
- json_file: str,
- json_files: deque,
-) -> Union[deque, Any]:
- path = Path(json_file).resolve()
- print("Creating challenge for", path)
-
- challenge_class = create_single_test(data, str(path))
- print("Creation complete for", path)
-
- return json_files, challenge_class
-
-
-def generate_tests() -> None: # sourcery skip: invert-any-all
- print("Generating tests...")
-
- challenges_path = os.path.join(os.path.dirname(__file__), "challenges")
- print(f"Looking for challenges in {challenges_path}...")
-
- json_files = deque(
- glob.glob(
- f"{challenges_path}/**/data.json",
- recursive=True,
- )
- )
-
- print(f"Found {len(json_files)} challenges.")
- print(f"Sample path: {json_files[0]}")
-
- agent_benchmark_config_path = str(Path.cwd() / "agbenchmark_config" / "config.json")
- try:
- with open(agent_benchmark_config_path, "r") as f:
- agent_benchmark_config = AgentBenchmarkConfig(**json.load(f))
- agent_benchmark_config.agent_benchmark_config_path = (
- agent_benchmark_config_path
- )
- except json.JSONDecodeError:
- print("Error: benchmark_config.json is not a valid JSON file.")
- raise
-
- regression_reports_path = agent_benchmark_config.get_regression_reports_path()
- if regression_reports_path and os.path.exists(regression_reports_path):
- with open(regression_reports_path, "r") as f:
- regression_tests = json.load(f)
- else:
- regression_tests = {}
-
- while json_files:
- json_file = (
- json_files.popleft()
- ) # Take and remove the first element from json_files
- if challenge_should_be_ignored(json_file):
- continue
-
- data = ChallengeData.get_json_from_path(json_file)
-
- commands = sys.argv
- # --by flag
- if "--category" in commands:
- categories = data.get("category", [])
- commands_set = set(commands)
-
- # Convert the combined list to a set
- categories_set = set(categories)
-
- # If there's no overlap with commands
- if not categories_set.intersection(commands_set):
- continue
-
- # --test flag, only run the test if it's the exact one specified
- tests = []
- for command in commands:
- if command.startswith("--test="):
- tests.append(command.split("=")[1])
-
- if tests and data["name"] not in tests:
- continue
-
- # --maintain and --improve flag
- in_regression = regression_tests.get(data["name"], None)
- improve_flag = in_regression and "--improve" in commands
- maintain_flag = not in_regression and "--maintain" in commands
- if "--maintain" in commands and maintain_flag:
- continue
- elif "--improve" in commands and improve_flag:
- continue
- json_files, challenge_class = create_challenge(data, json_file, json_files)
-
- print(f"Generated test for {data['name']}.")
- print("Test generation complete.")
-
-
-def challenge_should_be_ignored(json_file):
- return "challenges/deprecated" in json_file or "challenges/library" in json_file
-
+ setattr(module, challenge.__name__, challenge)
-generate_tests()
+ # Build a map of challenge names and their primary category
+ DATA_CATEGORY[challenge.info.name] = challenge.info.category[0].value
diff --git a/benchmark/agbenchmark/main.py b/benchmark/agbenchmark/main.py
new file mode 100644
index 000000000..4cd97bd89
--- /dev/null
+++ b/benchmark/agbenchmark/main.py
@@ -0,0 +1,158 @@
+import logging
+import os
+from pathlib import Path
+from typing import Optional, Sequence
+
+from dotenv import load_dotenv
+
+from agbenchmark.challenges import get_unique_categories
+from agbenchmark.config import AgentBenchmarkConfig
+
+load_dotenv()
+
+logger = logging.getLogger(__name__)
+
+
+def run_benchmark(
+ config: AgentBenchmarkConfig,
+ maintain: bool = False,
+ improve: bool = False,
+ explore: bool = False,
+ tests: tuple[str] = tuple(),
+ categories: tuple[str] = tuple(),
+ skip_categories: tuple[str] = tuple(),
+ attempts_per_challenge: int = 1,
+ mock: bool = False,
+ no_dep: bool = False,
+ no_cutoff: bool = False,
+ cutoff: Optional[int] = None,
+ keep_answers: bool = False,
+ server: bool = False,
+) -> int:
+ """
+ Starts the benchmark. If a category flag is provided, only challenges with the
+ corresponding mark will be run.
+ """
+ import pytest
+
+ from agbenchmark.reports.ReportManager import SingletonReportManager
+
+ validate_args(
+ maintain=maintain,
+ improve=improve,
+ explore=explore,
+ tests=tests,
+ categories=categories,
+ skip_categories=skip_categories,
+ no_cutoff=no_cutoff,
+ cutoff=cutoff,
+ )
+
+ SingletonReportManager()
+
+ for key, value in vars(config).items():
+ logger.debug(f"config.{key} = {repr(value)}")
+
+ pytest_args = ["-vs"]
+
+ if tests:
+ logger.info(f"Running specific test(s): {' '.join(tests)}")
+ pytest_args += [f"--test={t}" for t in tests]
+ else:
+ all_categories = get_unique_categories()
+
+ if categories or skip_categories:
+ categories_to_run = set(categories) or all_categories
+ if skip_categories:
+ categories_to_run = categories_to_run.difference(set(skip_categories))
+ assert categories_to_run, "Error: You can't skip all categories"
+ pytest_args += [f"--category={c}" for c in categories_to_run]
+ logger.info(f"Running tests of category: {categories_to_run}")
+ else:
+ logger.info("Running all categories")
+
+ if maintain:
+ logger.info("Running only regression tests")
+ elif improve:
+ logger.info("Running only non-regression tests")
+ elif explore:
+ logger.info("Only attempt challenges that have never been beaten")
+
+ if mock:
+ # TODO: unhack
+ os.environ[
+ "IS_MOCK"
+ ] = "True" # ugly hack to make the mock work when calling from API
+
+ # Pass through flags
+ for flag, active in {
+ "--maintain": maintain,
+ "--improve": improve,
+ "--explore": explore,
+ "--no-dep": no_dep,
+ "--mock": mock,
+ "--nc": no_cutoff,
+ "--keep-answers": keep_answers,
+ }.items():
+ if active:
+ pytest_args.append(flag)
+
+ if attempts_per_challenge > 1:
+ pytest_args.append(f"--attempts={attempts_per_challenge}")
+
+ if cutoff:
+ pytest_args.append(f"--cutoff={cutoff}")
+ logger.debug(f"Setting cuttoff override to {cutoff} seconds.")
+
+ current_dir = Path(__file__).resolve().parent
+ pytest_args.append(str(current_dir / "generate_test.py"))
+
+ pytest_args.append("--cache-clear")
+ logger.debug(f"Running Pytest with args: {pytest_args}")
+ exit_code = pytest.main(pytest_args)
+
+ SingletonReportManager.clear_instance()
+ return exit_code
+
+
+class InvalidInvocationError(ValueError):
+ pass
+
+
+def validate_args(
+ maintain: bool,
+ improve: bool,
+ explore: bool,
+ tests: Sequence[str],
+ categories: Sequence[str],
+ skip_categories: Sequence[str],
+ no_cutoff: bool,
+ cutoff: Optional[int],
+) -> None:
+ if categories:
+ all_categories = get_unique_categories()
+ invalid_categories = set(categories) - all_categories
+ if invalid_categories:
+ raise InvalidInvocationError(
+ "One or more invalid categories were specified: "
+ f"{', '.join(invalid_categories)}.\n"
+ f"Valid categories are: {', '.join(all_categories)}."
+ )
+
+ if (maintain + improve + explore) > 1:
+ raise InvalidInvocationError(
+ "You can't use --maintain, --improve or --explore at the same time. "
+ "Please choose one."
+ )
+
+ if tests and (categories or skip_categories or maintain or improve or explore):
+ raise InvalidInvocationError(
+ "If you're running a specific test make sure no other options are "
+ "selected. Please just pass the --test."
+ )
+
+ if no_cutoff and cutoff:
+ raise InvalidInvocationError(
+ "You can't use both --nc and --cutoff at the same time. "
+ "Please choose one."
+ )
diff --git a/benchmark/agbenchmark/reports/ReportManager.py b/benchmark/agbenchmark/reports/ReportManager.py
index 8e56682e5..24a9893d4 100644
--- a/benchmark/agbenchmark/reports/ReportManager.py
+++ b/benchmark/agbenchmark/reports/ReportManager.py
@@ -1,47 +1,51 @@
import copy
import json
+import logging
import os
import sys
import time
from datetime import datetime, timezone
+from pathlib import Path
+from typing import Any
+from agbenchmark.config import AgentBenchmarkConfig
from agbenchmark.reports.processing.graphs import save_single_radar_chart
-from agbenchmark.reports.processing.process_report import get_agent_category
-from agbenchmark.reports.processing.report_types import Report
-from agbenchmark.utils.data_types import AgentBenchmarkConfig
+from agbenchmark.reports.processing.process_report import (
+ get_highest_achieved_difficulty_per_category,
+)
+from agbenchmark.reports.processing.report_types import MetricsOverall, Report, Test
from agbenchmark.utils.utils import get_highest_success_difficulty
+logger = logging.getLogger(__name__)
+
class SingletonReportManager:
instance = None
- def __new__(cls):
- from agbenchmark.reports.agent_benchmark_config import (
- get_agent_benchmark_config,
- )
+ INFO_MANAGER: "SessionReportManager"
+ REGRESSION_MANAGER: "RegressionTestsTracker"
+ SUCCESS_RATE_TRACKER: "SuccessRatesTracker"
+ def __new__(cls):
if not cls.instance:
cls.instance = super(SingletonReportManager, cls).__new__(cls)
- agent_benchmark_config = get_agent_benchmark_config()
+ agent_benchmark_config = AgentBenchmarkConfig.load()
benchmark_start_time_dt = datetime.now(
timezone.utc
) # or any logic to fetch the datetime
# Make the Managers class attributes
- cls.REGRESSION_MANAGER = ReportManager(
- agent_benchmark_config.get_regression_reports_path(),
+ cls.INFO_MANAGER = SessionReportManager(
+ agent_benchmark_config.get_report_dir(benchmark_start_time_dt)
+ / "report.json",
benchmark_start_time_dt,
)
- cls.INFO_MANAGER = ReportManager(
- str(
- agent_benchmark_config.get_reports_path(benchmark_start_time_dt)
- / "report.json"
- ),
- benchmark_start_time_dt,
+ cls.REGRESSION_MANAGER = RegressionTestsTracker(
+ agent_benchmark_config.regression_tests_file
)
- cls.INTERNAL_INFO_MANAGER = ReportManager(
- agent_benchmark_config.get_success_rate_path(), benchmark_start_time_dt
+ cls.SUCCESS_RATE_TRACKER = SuccessRatesTracker(
+ agent_benchmark_config.success_rate_file
)
return cls.instance
@@ -49,54 +53,39 @@ class SingletonReportManager:
@classmethod
def clear_instance(cls):
cls.instance = None
- cls.REGRESSION_MANAGER = None
cls.INFO_MANAGER = None
- cls.INTERNAL_INFO_MANAGER = None
+ cls.REGRESSION_MANAGER = None
+ cls.SUCCESS_RATE_TRACKER = None
-class ReportManager:
+class BaseReportManager:
"""Abstracts interaction with the regression tests file"""
- def __init__(self, filename: str, benchmark_start_time: str):
- self.filename = filename
- self.start_time = time.time()
- self.benchmark_start_time = benchmark_start_time
+ tests: dict[str, Any]
+
+ def __init__(self, report_file: Path):
+ self.report_file = report_file
self.load()
def load(self) -> None:
- if not os.path.exists(self.filename):
- os.makedirs(os.path.dirname(self.filename), exist_ok=True)
- with open(self.filename, "w") as f:
- pass
+ if not self.report_file.exists():
+ self.report_file.parent.mkdir(exist_ok=True)
try:
- with open(self.filename, "r") as f:
- file_content = (
- f.read().strip()
- ) # read the content and remove any leading/trailing whitespace
- if file_content: # if file is not empty, load the json
- data = json.loads(file_content)
- self.tests = {k: data[k] for k in sorted(data)}
- else: # if file is empty, assign an empty dictionary
- self.tests = {}
+ with self.report_file.open("r") as f:
+ data = json.load(f)
+ self.tests = {k: data[k] for k in sorted(data)}
except FileNotFoundError:
self.tests = {}
- except json.decoder.JSONDecodeError: # If JSON is invalid
+ except json.decoder.JSONDecodeError as e:
+ logger.warning(f"Could not parse {self.report_file}: {e}")
self.tests = {}
- self.save()
def save(self) -> None:
- with open(self.filename, "w") as f:
+ with self.report_file.open("w") as f:
json.dump(self.tests, f, indent=4)
- def add_test(self, test_name: str, test_details: dict | list) -> None:
- if test_name.startswith("Test"):
- test_name = test_name[4:]
- self.tests[test_name] = test_details
-
- self.save()
-
def remove_test(self, test_name: str) -> None:
if test_name in self.tests:
del self.tests[test_name]
@@ -106,49 +95,86 @@ class ReportManager:
self.tests = {}
self.save()
- def end_info_report(self, config: AgentBenchmarkConfig) -> None:
+
+class SessionReportManager(BaseReportManager):
+ """Abstracts interaction with the regression tests file"""
+
+ tests: dict[str, Test] | Report
+
+ def __init__(self, report_file: Path, benchmark_start_time: datetime):
+ super().__init__(report_file)
+
+ self.start_time = time.time()
+ self.benchmark_start_time = benchmark_start_time
+
+ def save(self) -> None:
+ with self.report_file.open("w") as f:
+ if isinstance(self.tests, Report):
+ f.write(self.tests.json(indent=4))
+ else:
+ json.dump({k: v.dict() for k, v in self.tests.items()}, f, indent=4)
+
+ def load(self) -> None:
+ super().load()
+ if "tests" in self.tests: # type: ignore
+ self.tests = Report.parse_obj(self.tests)
+ else:
+ self.tests = {n: Test.parse_obj(d) for n, d in self.tests.items()}
+
+ def add_test_report(self, test_name: str, test_report: Test) -> None:
+ if isinstance(self.tests, Report):
+ raise RuntimeError("Session report already finalized")
+
+ if test_name.startswith("Test"):
+ test_name = test_name[4:]
+ self.tests[test_name] = test_report
+
+ self.save()
+
+ def finalize_session_report(self, config: AgentBenchmarkConfig) -> None:
command = " ".join(sys.argv)
- self.tests = {
- "command": command.split(os.sep)[-1],
- "benchmark_git_commit_sha": "---",
- "agent_git_commit_sha": "---",
- "completion_time": datetime.now(timezone.utc).strftime(
+ if isinstance(self.tests, Report):
+ raise RuntimeError("Session report already finalized")
+
+ self.tests = Report(
+ command=command.split(os.sep)[-1],
+ benchmark_git_commit_sha="---",
+ agent_git_commit_sha="---",
+ completion_time=datetime.now(timezone.utc).strftime(
"%Y-%m-%dT%H:%M:%S+00:00"
),
- "benchmark_start_time": self.benchmark_start_time.strftime(
+ benchmark_start_time=self.benchmark_start_time.strftime(
"%Y-%m-%dT%H:%M:%S+00:00"
),
- "metrics": {
- "run_time": str(round(time.time() - self.start_time, 2)) + " seconds",
- "highest_difficulty": get_highest_success_difficulty(self.tests),
- "total_cost": self.get_total_costs(),
- },
- "tests": copy.copy(self.tests),
- "config": {
- k: v for k, v in json.loads(config.json()).items() if v is not None
- },
- }
- Report.parse_obj(self.tests)
-
- converted_data = Report.parse_obj(self.tests)
-
- agent_categories = get_agent_category(converted_data)
+ metrics=MetricsOverall(
+ run_time=str(round(time.time() - self.start_time, 2)) + " seconds",
+ highest_difficulty=get_highest_success_difficulty(self.tests),
+ total_cost=self.get_total_costs(),
+ ),
+ tests=copy.copy(self.tests),
+ config=config.dict(exclude={"reports_folder"}, exclude_none=True),
+ )
+
+ agent_categories = get_highest_achieved_difficulty_per_category(self.tests)
if len(agent_categories) > 1:
save_single_radar_chart(
agent_categories,
- config.get_reports_path(self.benchmark_start_time) / "radar_chart.png",
+ config.get_report_dir(self.benchmark_start_time) / "radar_chart.png",
)
self.save()
def get_total_costs(self):
+ if isinstance(self.tests, Report):
+ tests = self.tests.tests
+ else:
+ tests = self.tests
+
total_cost = 0
all_costs_none = True
- for test_name, test_data in self.tests.items():
- cost = test_data["metrics"].get(
- "cost", 0
- ) # gets the cost or defaults to 0 if cost is missing
+ for test_data in tests.values():
+ cost = sum(r.cost or 0 for r in test_data.results)
if cost is not None: # check if cost is not None
all_costs_none = False
@@ -156,3 +182,32 @@ class ReportManager:
if all_costs_none:
total_cost = None
return total_cost
+
+
+class RegressionTestsTracker(BaseReportManager):
+ """Abstracts interaction with the regression tests file"""
+
+ tests: dict[str, dict]
+
+ def add_test(self, test_name: str, test_details: dict) -> None:
+ if test_name.startswith("Test"):
+ test_name = test_name[4:]
+
+ self.tests[test_name] = test_details
+ self.save()
+
+ def has_regression_test(self, test_name: str) -> bool:
+ return self.tests.get(test_name) is not None
+
+
+class SuccessRatesTracker(BaseReportManager):
+ """Abstracts interaction with the regression tests file"""
+
+ tests: dict[str, list[bool | None]]
+
+ def update(self, test_name: str, success_history: list[bool | None]) -> None:
+ if test_name.startswith("Test"):
+ test_name = test_name[4:]
+
+ self.tests[test_name] = success_history
+ self.save()
diff --git a/benchmark/agbenchmark/reports/agent_benchmark_config.py b/benchmark/agbenchmark/reports/agent_benchmark_config.py
deleted file mode 100644
index 3b45ed713..000000000
--- a/benchmark/agbenchmark/reports/agent_benchmark_config.py
+++ /dev/null
@@ -1,18 +0,0 @@
-import json
-from pathlib import Path
-
-from agbenchmark.utils.data_types import AgentBenchmarkConfig
-
-
-def get_agent_benchmark_config() -> AgentBenchmarkConfig:
- agent_benchmark_config_path = str(Path.cwd() / "agbenchmark_config" / "config.json")
- try:
- with open(agent_benchmark_config_path, "r") as f:
- agent_benchmark_config = AgentBenchmarkConfig(**json.load(f))
- agent_benchmark_config.agent_benchmark_config_path = (
- agent_benchmark_config_path
- )
- return agent_benchmark_config
- except json.JSONDecodeError:
- print("Error: benchmark_config.json is not a valid JSON file.")
- raise
diff --git a/benchmark/agbenchmark/reports/processing/process_report.py b/benchmark/agbenchmark/reports/processing/process_report.py
index b390ba2f9..993cc4f3c 100644
--- a/benchmark/agbenchmark/reports/processing/process_report.py
+++ b/benchmark/agbenchmark/reports/processing/process_report.py
@@ -1,4 +1,5 @@
import json
+import logging
import os
from pathlib import Path
from typing import Any
@@ -6,9 +7,11 @@ from typing import Any
from agbenchmark.reports.processing.get_files import (
get_latest_report_from_agent_directories,
)
-from agbenchmark.reports.processing.report_types import Report, Test
+from agbenchmark.reports.processing.report_types import Report
from agbenchmark.utils.data_types import STRING_DIFFICULTY_MAP
+logger = logging.getLogger(__name__)
+
def get_reports_data(report_path: str) -> dict[str, Any]:
latest_files = get_latest_report_from_agent_directories(report_path)
@@ -31,26 +34,23 @@ def get_reports_data(report_path: str) -> dict[str, Any]:
return reports_data
-def get_agent_category(report: Report) -> dict[str, Any]:
+def get_highest_achieved_difficulty_per_category(report: Report) -> dict[str, Any]:
categories: dict[str, Any] = {}
- def get_highest_category_difficulty(data: Test) -> None:
- for category in data.category:
- if (
- category == "interface"
- or category == "iterate"
- or category == "product_advisor"
- ):
+ for _, test_data in report.tests.items():
+ for category in test_data.category:
+ if category in ("interface", "iterate", "product_advisor"):
continue
categories.setdefault(category, 0)
- if data.metrics.success:
- num_dif = STRING_DIFFICULTY_MAP[data.metrics.difficulty]
+ if (
+ test_data.results
+ and all(r.success for r in test_data.results)
+ and test_data.difficulty
+ ):
+ num_dif = STRING_DIFFICULTY_MAP[test_data.difficulty]
if num_dif > categories[category]:
categories[category] = num_dif
- for _, test_data in report.tests.items():
- get_highest_category_difficulty(test_data)
-
return categories
@@ -58,9 +58,9 @@ def all_agent_categories(reports_data: dict[str, Any]) -> dict[str, Any]:
all_categories: dict[str, Any] = {}
for name, report in reports_data.items():
- categories = get_agent_category(report)
+ categories = get_highest_achieved_difficulty_per_category(report)
if categories: # only add to all_categories if categories is not empty
- print(f"Adding {name}: {categories}")
+ logger.debug(f"Adding {name}: {categories}")
all_categories[name] = categories
return all_categories
diff --git a/benchmark/agbenchmark/reports/processing/report_types.py b/benchmark/agbenchmark/reports/processing/report_types.py
index 3ba9e6c6b..ea2ad840f 100644
--- a/benchmark/agbenchmark/reports/processing/report_types.py
+++ b/benchmark/agbenchmark/reports/processing/report_types.py
@@ -1,75 +1,100 @@
-from typing import Any, Dict, List, Union
+"""
+Model definitions used internally and for reports generated during command-line runs.
+"""
-from pydantic import BaseModel, Field
-
-datetime_format = r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+00:00$"
-from pydantic import BaseModel, constr
-
-
-class ForbidOptionalMeta(type(BaseModel)): # metaclass to forbid optional fields
- def __new__(cls, name: str, bases: tuple, dct: Dict[str, Any]) -> Any:
- for attr_name, attr_value in dct.items():
- if (
- getattr(attr_value, "__origin__", None) == Union
- and type(None) in attr_value.__args__
- ):
- raise TypeError(
- f"Optional fields are forbidden, but found in {attr_name}"
- )
-
- return super().__new__(cls, name, bases, dct)
+import logging
+from typing import Any, Dict, List
+from agent_protocol_client import Step
+from pydantic import BaseModel, Field, constr, validator
-class BaseModelBenchmark(BaseModel, metaclass=ForbidOptionalMeta):
- class Config:
- extra = "forbid"
-
+datetime_format = r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+00:00$"
+logger = logging.getLogger(__name__)
+
+
+class TestResult(BaseModel):
+ """Result details for a single run of a test/challenge."""
+
+ success: bool | None = None
+ """Whether the run was successful"""
+ run_time: str | None = None
+ """The (formatted) duration of the run"""
+ fail_reason: str | None = None
+ """If applicable, the reason why the run was not successful"""
+ reached_cutoff: bool | None = None # None if in progress
+ """Whether the run had to be stopped due to reaching the timeout"""
+ n_steps: int | None = None
+ """The number of steps executed by the agent"""
+ steps: list[Step] = []
+ """The steps generated by the agent"""
+ cost: float | None = None
+ """The (known) cost incurred by the run, e.g. from using paid LLM APIs"""
+
+ @validator("fail_reason")
+ def success_xor_fail_reason(cls, v: str | None, values: dict[str, Any]):
+ if bool(v) == bool(values["success"]):
+ logger.error(
+ "Error validating `success ^ fail_reason` on TestResult: "
+ f"success = {repr(values['success'])}; "
+ f"fail_reason = {repr(v)}"
+ )
+ if v:
+ success = values["success"]
+ assert not success, "fail_reason must only be specified if success=False"
+ else:
+ assert values["success"], "fail_reason is required if success=False"
+ return v
+
+
+class TestMetrics(BaseModel):
+ """
+ Result metrics for a set of runs for a test/challenge. Should be an aggregate of all
+ results for the same test/challenge within a benchmarking session.
+ """
-class Metrics(BaseModelBenchmark):
- difficulty: str
- success: bool
- success_percentage: float = Field(..., alias="success_%")
- run_time: str
- fail_reason: str | None
attempted: bool
- cost: float | None
+ """Whether the challenge was attempted during this session"""
+ is_regression: bool
+ """Whether the challenge was considered a regression test at the time of running"""
+ success_percentage: float | None = Field(default=None, alias="success_%")
+ """Success rate (0-100) for this challenge within the session"""
-class MetricsOverall(BaseModelBenchmark):
+class MetricsOverall(BaseModel):
+ """Global metrics concerning a benchmarking session"""
+
run_time: str
+ """Duration from beginning to end of the session"""
highest_difficulty: str
- percentage: float | None
- total_cost: float | None
+ """
+ Difficulty of the most difficult challenge that succeeded at least once this session
+ """
+ total_cost: float | None = None
+ """Total known cost of the session"""
-class Test(BaseModelBenchmark):
+class Test(BaseModel):
+ category: List[str]
+ difficulty: str | None
data_path: str
- is_regression: bool
- answer: str
description: str
- metrics: Metrics
- category: List[str]
task: str
- reached_cutoff: bool
- metadata: Any
+ answer: str
+ metrics: TestMetrics
+ results: list[TestResult]
+ metadata: dict[str, Any] | None = Field(default_factory=dict)
-class ReportBase(BaseModelBenchmark):
+class ReportBase(BaseModel):
command: str
- completion_time: str | None
+ completion_time: str | None = None
benchmark_start_time: constr(regex=datetime_format)
metrics: MetricsOverall
config: Dict[str, str | dict[str, str]]
- agent_git_commit_sha: str | None
- benchmark_git_commit_sha: str | None
- repo_url: str | None
+ agent_git_commit_sha: str | None = None
+ benchmark_git_commit_sha: str | None = None
+ repo_url: str | None = None
class Report(ReportBase):
tests: Dict[str, Test]
-
-
-class ReportV2(Test, ReportBase):
- test_name: str
- run_id: str | None
- team_name: str | None
diff --git a/benchmark/agbenchmark/reports/processing/report_types_v2.py b/benchmark/agbenchmark/reports/processing/report_types_v2.py
index 94b53ca97..b26adaa6d 100644
--- a/benchmark/agbenchmark/reports/processing/report_types_v2.py
+++ b/benchmark/agbenchmark/reports/processing/report_types_v2.py
@@ -1,52 +1,48 @@
-from typing import Dict, List
+"""Model definitions for use in the API"""
-datetime_format = r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+00:00$"
from pydantic import BaseModel, constr
-
-class BaseModelBenchmark(BaseModel):
- class Config:
- extra = "forbid"
+datetime_format = r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+00:00$"
-class TaskInfo(BaseModelBenchmark):
+class TaskInfo(BaseModel):
data_path: str
is_regression: bool | None
answer: str
description: str
- category: List[str]
+ category: list[str]
task: str
-class RepositoryInfo(BaseModelBenchmark):
- repo_url: str | None
- team_name: str | None
- benchmark_git_commit_sha: str | None
- agent_git_commit_sha: str | None
+class RepositoryInfo(BaseModel):
+ repo_url: str | None = None
+ team_name: str | None = None
+ agent_git_commit_sha: str | None = None
+ benchmark_git_commit_sha: str | None = None
-class Metrics(BaseModelBenchmark):
- difficulty: str | None
+class Metrics(BaseModel):
+ cost: float | None = None
success: bool
- success_percentage: float | None
- run_time: str | None
- fail_reason: str | None
attempted: bool
- cost: float | None
+ difficulty: str | None = None
+ run_time: str | None = None
+ fail_reason: str | None = None
+ success_percentage: float | None = None
-class RunDetails(BaseModelBenchmark):
+class RunDetails(BaseModel):
test_name: str
- run_id: str | None
+ run_id: str | None = None
command: str
- completion_time: str | None
+ completion_time: str | None = None
benchmark_start_time: constr(regex=datetime_format)
-class BenchmarkRun(BaseModelBenchmark):
+class BenchmarkRun(BaseModel):
repository_info: RepositoryInfo
run_details: RunDetails
task_info: TaskInfo
metrics: Metrics
- reached_cutoff: bool | None
- config: Dict[str, str | dict[str, str]]
+ reached_cutoff: bool | None = None
+ config: dict[str, str | dict[str, str]]
diff --git a/benchmark/agbenchmark/reports/reports.py b/benchmark/agbenchmark/reports/reports.py
index a1164bab7..431f4ba6e 100644
--- a/benchmark/agbenchmark/reports/reports.py
+++ b/benchmark/agbenchmark/reports/reports.py
@@ -1,184 +1,157 @@
import json
+import logging
import os
-import sys
-from typing import Any, Dict
+from pathlib import Path
-from agbenchmark.__main__ import CHALLENGES_ALREADY_BEATEN
-from agbenchmark.reports.agent_benchmark_config import get_agent_benchmark_config
+import pytest
+from pydantic import ValidationError
+
+from agbenchmark.challenges import ChallengeInfo
+from agbenchmark.config import AgentBenchmarkConfig
+from agbenchmark.reports.processing.report_types import Test, TestMetrics, TestResult
from agbenchmark.reports.ReportManager import SingletonReportManager
from agbenchmark.utils.data_types import DifficultyLevel
-from agbenchmark.utils.get_data_from_helicone import get_data_from_helicone
-from agbenchmark.utils.utils import calculate_success_percentage
+
+# from agbenchmark.utils.get_data_from_helicone import get_data_from_helicone
+
+logger = logging.getLogger(__name__)
-def get_previous_test_results(
- test_name: str, info_details: dict[str, Any]
-) -> list[bool]:
- agent_tests: dict[str, list[bool]] = {}
+def get_and_update_success_history(
+ test_name: str, success: bool | None
+) -> list[bool | None]:
mock = os.getenv("IS_MOCK") # Check if --mock is in sys.argv
- prev_test_results = SingletonReportManager().INTERNAL_INFO_MANAGER.tests.get(
+ prev_test_results = SingletonReportManager().SUCCESS_RATE_TRACKER.tests.get(
test_name, []
)
if not mock:
# only add if it's an actual test
- prev_test_results.append(info_details["metrics"]["success"])
- SingletonReportManager().INTERNAL_INFO_MANAGER.add_test(
+ prev_test_results.append(success)
+ SingletonReportManager().SUCCESS_RATE_TRACKER.update(
test_name, prev_test_results
)
- # can calculate success rate regardless of mock
- info_details["metrics"]["success_%"] = calculate_success_percentage(
- prev_test_results
- )
-
return prev_test_results
def update_regression_tests(
- prev_test_results: list[bool],
- info_details: dict,
+ prev_test_results: list[bool | None],
+ test_report: Test,
test_name: str,
- test_details: dict,
) -> None:
if len(prev_test_results) >= 3 and prev_test_results[-3:] == [True, True, True]:
# if the last 3 tests were successful, add to the regression tests
- info_details["is_regression"] = True
- SingletonReportManager().REGRESSION_MANAGER.add_test(test_name, test_details)
-
+ test_report.metrics.is_regression = True
+ SingletonReportManager().REGRESSION_MANAGER.add_test(
+ test_name, test_report.dict(include={"difficulty", "data_path"})
+ )
-def generate_single_call_report(
- item: Any,
- call: Any,
- challenge_data: dict[str, Any],
- answers: dict[str, Any],
- challenge_location,
- test_name,
-) -> None:
- try:
- difficulty = challenge_data["info"]["difficulty"]
- except KeyError:
- return None
+def make_empty_test_report(
+ challenge_info: ChallengeInfo,
+) -> Test:
+ difficulty = challenge_info.difficulty
if isinstance(difficulty, DifficultyLevel):
difficulty = difficulty.value
- # Extract the challenge_location from the class
- # challenge_location: str = getattr(item.cls, "CHALLENGE_LOCATION", "")
- # test_name = item.nodeid.split("::")[1]
- # item.test_name = test_name
-
- test_details = {
- "difficulty": difficulty,
- "data_path": challenge_location,
- }
-
- info_details: Any = {
- "data_path": challenge_location,
- "is_regression": False,
- "category": challenge_data["category"],
- "task": challenge_data["task"],
- "answer": challenge_data["ground"]["answer"],
- "description": challenge_data["info"]["description"],
- "metrics": {
- "difficulty": difficulty,
- "success": False,
- "attempted": True,
- },
- # "answers": answers,
- }
- if answers:
- info_details["answers"] = answers
-
- if "metadata" in challenge_data:
- info_details["metadata"] = challenge_data["metadata"]
-
- mock = os.getenv("IS_MOCK") # Check if --mock is in sys.argv
- if call:
- if call.excinfo is None:
- info_details["metrics"]["success"] = True
- else:
- if not mock: # don't remove if it's a mock test
- SingletonReportManager().REGRESSION_MANAGER.remove_test(test_name)
- info_details["metrics"]["fail_reason"] = str(call.excinfo.value)
- if call.excinfo.typename == "Skipped":
- info_details["metrics"]["attempted"] = False
-
- prev_test_results: list[bool] = get_previous_test_results(test_name, info_details)
-
- update_regression_tests(prev_test_results, info_details, test_name, test_details)
-
- # user facing reporting
- if item:
- item.info_details = info_details
-
- return info_details
+ return Test(
+ category=[c.value for c in challenge_info.category],
+ difficulty=difficulty,
+ data_path=challenge_info.source_uri,
+ description=challenge_info.description or "",
+ task=challenge_info.task,
+ answer=challenge_info.reference_answer or "",
+ metrics=TestMetrics(attempted=False, is_regression=False),
+ results=[],
+ )
-def finalize_reports(item: Any, challenge_data: dict[str, Any]) -> None:
- run_time = dict(item.user_properties).get("run_time")
+def add_test_result_to_report(
+ test_report: Test,
+ item: pytest.Item,
+ call: pytest.CallInfo,
+ config: AgentBenchmarkConfig,
+) -> None:
+ user_properties: dict = dict(item.user_properties)
+ test_name: str = user_properties.get("test_name", "")
- info_details = getattr(item, "info_details", {})
- test_name = getattr(item, "test_name", "")
+ mock = os.getenv("IS_MOCK") # Check if --mock is in sys.argv
- if info_details and test_name:
- if run_time is not None:
- cost = None
- if "--mock" not in sys.argv and os.environ.get("HELICONE_API_KEY"):
- print("Getting cost from Helicone")
- cost = get_data_from_helicone(test_name)
+ if call.excinfo:
+ if not mock:
+ SingletonReportManager().REGRESSION_MANAGER.remove_test(test_name)
- info_details["metrics"]["cost"] = cost
+ test_report.metrics.attempted = call.excinfo.typename != "Skipped"
+ else:
+ test_report.metrics.attempted = True
- if info_details["metrics"].get("success", None) is None:
- info_details["metrics"]["attempted"] = False
- info_details["metrics"]["success"] = False
- elif (
- info_details["metrics"].get("success") is False
- and "attempted" not in info_details["metrics"]
- ):
- info_details["metrics"]["attempted"] = False
+ try:
+ test_report.results.append(
+ TestResult(
+ success=call.excinfo is None,
+ run_time=f"{str(round(call.duration, 3))} seconds",
+ fail_reason=(
+ str(call.excinfo.value) if call.excinfo is not None else None
+ ),
+ reached_cutoff=user_properties.get("timed_out", False),
+ n_steps=user_properties.get("n_steps"),
+ steps=user_properties.get("steps", []),
+ cost=user_properties.get("agent_task_cost"),
+ )
+ )
+ test_report.metrics.success_percentage = (
+ sum(r.success or False for r in test_report.results)
+ / len(test_report.results)
+ * 100
+ )
+ except ValidationError:
+ if call.excinfo:
+ logger.error(
+ "Validation failed on TestResult; "
+ f"call.excinfo = {repr(call.excinfo)};\n{call.excinfo.getrepr()})"
+ )
+ raise
+
+ prev_test_results: list[bool | None] = get_and_update_success_history(
+ test_name, test_report.results[-1].success
+ )
- info_details["metrics"]["run_time"] = f"{str(round(run_time, 3))} seconds"
+ update_regression_tests(prev_test_results, test_report, test_name)
- info_details["reached_cutoff"] = float(run_time) > challenge_data["cutoff"]
+ if test_report and test_name:
+ # if "--mock" not in sys.argv and os.environ.get("HELICONE_API_KEY"):
+ # logger.debug("Getting cost from Helicone")
+ # test_report.metrics.cost = get_data_from_helicone(test_name)
+ # logger.debug(f"Cost: {cost}")
- if "--mock" not in sys.argv:
- update_challenges_already_beaten(info_details, test_name)
- if info_details.get("tests") is not None:
- for nested_test_name, nested_test_info in info_details[
- "tests"
- ].items():
- update_challenges_already_beaten(
- nested_test_info, nested_test_name
- )
+ if not mock:
+ update_challenges_already_beaten(
+ config.challenges_already_beaten_file, test_report, test_name
+ )
- SingletonReportManager().INFO_MANAGER.add_test(test_name, info_details)
+ SingletonReportManager().INFO_MANAGER.add_test_report(test_name, test_report)
def update_challenges_already_beaten(
- info_details: Dict[str, Any], test_name: str
+ challenges_already_beaten_file: Path, test_report: Test, test_name: str
) -> None:
- current_run_successful = info_details["metrics"]["success"]
+ current_run_successful = any(r.success for r in test_report.results)
try:
- with open(CHALLENGES_ALREADY_BEATEN, "r") as f:
- challenge_data = json.load(f)
- except:
- challenge_data = {}
- challenge_beaten_in_the_past = challenge_data.get(test_name)
-
- challenge_data[test_name] = True
- if challenge_beaten_in_the_past is None and not current_run_successful:
- challenge_data[test_name] = False
+ with open(challenges_already_beaten_file, "r") as f:
+ challenges_beaten_before = json.load(f)
+ except FileNotFoundError:
+ challenges_beaten_before = {}
- with open(CHALLENGES_ALREADY_BEATEN, "w") as f:
- json.dump(challenge_data, f, indent=4)
+ has_ever_been_beaten = challenges_beaten_before.get(test_name)
+ challenges_beaten_before[test_name] = has_ever_been_beaten or current_run_successful
+ with open(challenges_already_beaten_file, "w") as f:
+ json.dump(challenges_beaten_before, f, indent=4)
-def session_finish(suite_reports: dict) -> None:
- agent_benchmark_config = get_agent_benchmark_config()
- SingletonReportManager().INTERNAL_INFO_MANAGER.save()
- SingletonReportManager().INFO_MANAGER.end_info_report(agent_benchmark_config)
+def session_finish(agbenchmark_config: AgentBenchmarkConfig) -> None:
+ SingletonReportManager().INFO_MANAGER.finalize_session_report(agbenchmark_config)
SingletonReportManager().REGRESSION_MANAGER.save()
+ SingletonReportManager().SUCCESS_RATE_TRACKER.save()
diff --git a/benchmark/agbenchmark/schema.py b/benchmark/agbenchmark/schema.py
index 4849c2ad6..2aed562da 100644
--- a/benchmark/agbenchmark/schema.py
+++ b/benchmark/agbenchmark/schema.py
@@ -1,79 +1,14 @@
-# generated by fastapi-codegen:
-# filename: ../../postman/schemas/openapi.yaml
-# timestamp: 2023-08-25T10:36:11+00:00
-
from __future__ import annotations
-from datetime import datetime
-from enum import Enum
-from typing import List, Optional
+from typing import Optional
from pydantic import BaseModel, Field
-class ArtifactUpload(BaseModel):
- file: str = Field(..., description="File to upload.", format="binary")
- relative_path: str = Field(
- ...,
- description="Relative path of the artifact in the agent's workspace.",
- example="python/code",
- )
-
-
-class Pagination(BaseModel):
- total_items: int = Field(..., description="Total number of items.", example=42)
- total_pages: int = Field(..., description="Total number of pages.", example=97)
- current_page: int = Field(..., description="Current_page page number.", example=1)
- page_size: int = Field(..., description="Number of items per page.", example=25)
-
-
class TaskInput(BaseModel):
pass
-class Artifact(BaseModel):
- created_at: datetime = Field(
- ...,
- description="The creation datetime of the task.",
- example="2023-01-01T00:00:00Z",
- json_encoders={datetime: lambda v: v.isoformat()},
- )
- modified_at: datetime = Field(
- ...,
- description="The modification datetime of the task.",
- example="2023-01-01T00:00:00Z",
- json_encoders={datetime: lambda v: v.isoformat()},
- )
- artifact_id: str = Field(
- ...,
- description="ID of the artifact.",
- example="b225e278-8b4c-4f99-a696-8facf19f0e56",
- )
- agent_created: bool = Field(
- ...,
- description="Whether the artifact has been created by the agent.",
- example=False,
- )
- relative_path: str = Field(
- ...,
- description="Relative path of the artifact in the agents workspace.",
- example="/my_folder/my_other_folder/",
- )
- file_name: str = Field(
- ...,
- description="Filename of the artifact.",
- example="main.py",
- )
-
-
-class StepInput(BaseModel):
- pass
-
-
-class StepOutput(BaseModel):
- pass
-
-
class TaskRequestBody(BaseModel):
input: str = Field(
...,
@@ -86,108 +21,3 @@ class TaskRequestBody(BaseModel):
class TaskEvalRequestBody(TaskRequestBody):
eval_id: str
-
-
-class Task(TaskRequestBody):
- created_at: datetime = Field(
- ...,
- description="The creation datetime of the task.",
- example="2023-01-01T00:00:00Z",
- json_encoders={datetime: lambda v: v.isoformat()},
- )
- modified_at: datetime = Field(
- ...,
- description="The modification datetime of the task.",
- example="2023-01-01T00:00:00Z",
- json_encoders={datetime: lambda v: v.isoformat()},
- )
- task_id: str = Field(
- ...,
- description="The ID of the task.",
- example="50da533e-3904-4401-8a07-c49adf88b5eb",
- )
- artifacts: Optional[List[Artifact]] = Field(
- [],
- description="A list of artifacts that the task has produced.",
- example=[
- "7a49f31c-f9c6-4346-a22c-e32bc5af4d8e",
- "ab7b4091-2560-4692-a4fe-d831ea3ca7d6",
- ],
- )
-
-
-class StepRequestBody(BaseModel):
- name: Optional[str] = Field(
- None, description="The name of the task step.", example="Write to file"
- )
- input: Optional[str] = Field(
- None,
- min_length=1,
- description="Input prompt for the step.",
- example="Washington",
- )
- additional_input: Optional[StepInput] = {}
-
-
-class Status(Enum):
- created = "created"
- running = "running"
- completed = "completed"
-
-
-class Step(StepRequestBody):
- created_at: datetime = Field(
- ...,
- description="The creation datetime of the task.",
- example="2023-01-01T00:00:00Z",
- json_encoders={datetime: lambda v: v.isoformat()},
- )
- modified_at: datetime = Field(
- ...,
- description="The modification datetime of the task.",
- example="2023-01-01T00:00:00Z",
- json_encoders={datetime: lambda v: v.isoformat()},
- )
- task_id: str = Field(
- ...,
- description="The ID of the task this step belongs to.",
- example="50da533e-3904-4401-8a07-c49adf88b5eb",
- )
- step_id: str = Field(
- ...,
- description="The ID of the task step.",
- example="6bb1801a-fd80-45e8-899a-4dd723cc602e",
- )
- name: Optional[str] = Field(
- None, description="The name of the task step.", example="Write to file"
- )
- status: Status = Field(
- ..., description="The status of the task step.", example="created"
- )
- output: Optional[str] = Field(
- None,
- description="Output of the task step.",
- example="I am going to use the write_to_file command and write Washington to a file called output.txt <write_to_file('output.txt', 'Washington')",
- )
- additional_output: Optional[StepOutput] = {}
- artifacts: Optional[List[Artifact]] = Field(
- [], description="A list of artifacts that the step has produced."
- )
- is_last: bool = Field(
- ..., description="Whether this is the last step in the task.", example=True
- )
-
-
-class TaskListResponse(BaseModel):
- tasks: Optional[List[Task]] = None
- pagination: Optional[Pagination] = None
-
-
-class TaskStepsListResponse(BaseModel):
- steps: Optional[List[Step]] = None
- pagination: Optional[Pagination] = None
-
-
-class TaskArtifactsListResponse(BaseModel):
- artifacts: Optional[List[Artifact]] = None
- pagination: Optional[Pagination] = None
diff --git a/benchmark/agbenchmark/utils/challenge.py b/benchmark/agbenchmark/utils/challenge.py
deleted file mode 100644
index a32ab6cf7..000000000
--- a/benchmark/agbenchmark/utils/challenge.py
+++ /dev/null
@@ -1,236 +0,0 @@
-import glob
-import math
-import os
-import subprocess
-import sys
-from abc import ABC
-from pathlib import Path
-from typing import Any, Dict, List
-
-import openai
-import pytest
-
-from agbenchmark.__main__ import OPTIONAL_CATEGORIES, TEMP_FOLDER_ABS_PATH
-from agbenchmark.agent_api_interface import run_api_agent
-from agbenchmark.utils.data_types import ChallengeData, Ground
-from agbenchmark.utils.prompts import (
- END_PROMPT,
- FEW_SHOT_EXAMPLES,
- PROMPT_MAP,
- SCORING_MAP,
-)
-from agbenchmark.utils.utils import agent_eligibible_for_optional_categories
-
-
-class Challenge(ABC):
- """The parent class to all specific challenges classes.
- Defines helper methods for running a challenge"""
-
- _data_cache: Dict[str, ChallengeData] = {}
- CHALLENGE_LOCATION: str = ""
- scores: dict[str, Any] = {} # this is for suites
-
- @property
- def data(self) -> ChallengeData:
- if self.CHALLENGE_LOCATION not in self._data_cache:
- self._data_cache[self.CHALLENGE_LOCATION] = ChallengeData.deserialize(
- self.CHALLENGE_LOCATION
- )
- return self._data_cache[self.CHALLENGE_LOCATION]
-
- @property
- def task(self) -> str:
- return self.data.task
-
- @property
- def dependencies(self) -> list:
- return self.data.dependencies
-
- async def setup_challenge(self, config: Dict[str, Any], cutoff: int) -> None:
- from agbenchmark.agent_interface import copy_artifacts_into_temp_folder
-
- if not self.task:
- return
-
- print(
- f"\033[1;35m============Starting {self.data.name} challenge============\033[0m"
- )
- print(f"\033[1;30mTask: {self.task}\033[0m")
-
- await run_api_agent(self.data, config, self.ARTIFACTS_LOCATION, cutoff)
-
- # hidden files are added after the agent runs. Hidden files can be python test files.
- # We copy them in the temporary folder to make it easy to import the code produced by the agent
- artifact_paths = [
- self.ARTIFACTS_LOCATION,
- str(Path(self.CHALLENGE_LOCATION).parent),
- ]
- for path in artifact_paths:
- copy_artifacts_into_temp_folder(TEMP_FOLDER_ABS_PATH, "custom_python", path)
-
- def test_method(self, config: Dict[str, Any]) -> None:
- raise NotImplementedError
-
- def get_artifacts_out(
- self, workspace: str | dict[str, str], ground: Ground
- ) -> List[str]:
- if isinstance(workspace, dict):
- workspace = workspace["output"]
-
- script_dir = workspace
- files_contents = []
-
- for file_pattern in ground.files:
- # Check if it is a file extension
- if file_pattern.startswith("."):
- # Find all files with the given extension in the workspace
- matching_files = glob.glob(os.path.join(script_dir, "*" + file_pattern))
- else:
- # Otherwise, it is a specific file
- matching_files = [os.path.join(script_dir, file_pattern)]
-
- for file_path in matching_files:
- if ground.eval.type == "python":
- result = subprocess.run(
- [sys.executable, file_path],
- cwd=os.path.abspath(workspace),
- capture_output=True,
- text=True,
- )
- if "error" in result.stderr or result.returncode != 0:
- print(result.stderr)
- assert False, result.stderr
- files_contents.append(f"Output: {result.stdout}\n")
- else:
- with open(file_path, "r") as f:
- files_contents.append(f.read())
- else:
- if ground.eval.type == "pytest":
- result = subprocess.run(
- [sys.executable, "-m", "pytest"],
- cwd=TEMP_FOLDER_ABS_PATH,
- capture_output=True,
- text=True,
- )
- if "error" in result.stderr or result.returncode != 0:
- print(result.stderr)
- assert False, result.stderr
- files_contents.append(f"Output: {result.stdout}\n")
-
- return files_contents
-
- def scoring(self, config: Dict[str, Any], content: str, ground: Ground) -> float:
- print("\033[1;34mScoring content:\033[0m", content)
- if ground.should_contain:
- for should_contain_word in ground.should_contain:
- if not getattr(ground, "case_sensitive", True):
- should_contain_word = should_contain_word.lower()
- content = content.lower()
- print_content = (
- f"\033[1;34mWord that should exist\033[0m - {should_contain_word}:"
- )
- if should_contain_word not in content:
- print(print_content, "False")
- return 0.0
- else:
- print(print_content, "True")
-
- if ground.should_not_contain:
- for should_not_contain_word in ground.should_not_contain:
- if not getattr(ground, "case_sensitive", True):
- should_not_contain_word = should_not_contain_word.lower()
- content = content.lower()
- print_content = f"\033[1;34mWord that should not exist\033[0m - {should_not_contain_word}:"
- if should_not_contain_word in content:
- print(print_content, "False")
- return 0.0
- else:
- print(print_content, "True")
-
- return 1.0
-
- def llm_eval(self, config: Dict[str, Any], content: str, ground: Ground) -> float:
- openai.api_key = os.getenv("OPENAI_API_KEY")
- if os.getenv("IS_MOCK"):
- return 1.0
-
- # the validation for this is done in the Eval BaseModel
- scoring = SCORING_MAP[ground.eval.scoring] # type: ignore
- prompt = PROMPT_MAP[ground.eval.template].format(task=self.data.task, scoring=scoring, answer=ground.answer, response=content) # type: ignore
-
- if ground.eval.examples:
- prompt += FEW_SHOT_EXAMPLES.format(examples=ground.eval.examples)
-
- prompt += END_PROMPT
-
- answer = openai.ChatCompletion.create(
- model="gpt-4",
- messages=[
- {"role": "system", "content": prompt},
- ],
- )
-
- return float(answer["choices"][0]["message"]["content"]) # type: ignore
-
- def get_scores(self, config: Dict[str, Any]) -> dict[str, Any]:
- scores = []
- scores_dict: Any = {}
- percentage = None
- answers = {}
- try:
- if self.data.task == "" and os.getenv("IS_MOCK"):
- scores = [1.0]
- answers = {"mock": "This is a mock answer"}
- elif isinstance(self.data.ground, Ground):
- files_contents = self.get_artifacts_out(
- TEMP_FOLDER_ABS_PATH, self.data.ground
- )
- answers = {"answer": files_contents}
- for file_content in files_contents:
- score = self.scoring(config, file_content, self.data.ground)
- print("\033[1;32mYour score is:\033[0m", score)
- scores.append(score)
-
- if self.data.ground.eval.type == "llm":
- llm_eval = self.llm_eval(
- config, "\n".join(files_contents), self.data.ground
- )
- if self.data.ground.eval.scoring == "percentage":
- scores.append(math.ceil(llm_eval / 100))
- elif self.data.ground.eval.scoring == "scale":
- scores.append(math.ceil(llm_eval / 10))
- print("\033[1;32mYour score is:\033[0m", llm_eval)
-
- scores.append(llm_eval)
- except Exception as e:
- print("Error getting scores", e)
-
- scores_data = {
- "values": scores,
- "scores_obj": scores_dict,
- "percentage": percentage,
- "answers": answers,
- }
-
- self.scores[self.__class__.__name__] = scores_data
-
- return scores_data
-
- def get_dummy_scores(self, test_name: str, scores: dict[str, Any]) -> int | None:
- return 1 # remove this once this works
- if 1 in scores.get("scores_obj", {}).get(test_name, []):
- return 1
-
- return None
-
- def skip_optional_categories(self, config: Dict[str, Any]) -> None:
- challenge_category = self.data.category
- categories = [
- category
- for category in OPTIONAL_CATEGORIES
- if category in challenge_category
- ]
- if not agent_eligibible_for_optional_categories(
- categories, config.get("category", [])
- ):
- pytest.skip("Agent is not eligible for this category")
diff --git a/benchmark/agbenchmark/utils/data_types.py b/benchmark/agbenchmark/utils/data_types.py
index 955b1d6a8..ac7444921 100644
--- a/benchmark/agbenchmark/utils/data_types.py
+++ b/benchmark/agbenchmark/utils/data_types.py
@@ -1,12 +1,7 @@
-import datetime
-import json
-import sys
-from datetime import datetime
from enum import Enum
-from pathlib import Path
-from typing import Any, Dict, List, Optional
+from typing import Literal
-from pydantic import BaseModel, constr, validator
+from pydantic import BaseModel
class DifficultyLevel(Enum):
@@ -33,229 +28,19 @@ DIFFICULTY_MAP = {
STRING_DIFFICULTY_MAP = {e.value: DIFFICULTY_MAP[e] for e in DifficultyLevel}
-def calculate_info_test_path(base_path: Path, benchmark_start_time: datetime) -> Path:
- """
- Calculates the path to the directory where the test report will be saved.
- """
- # Ensure the reports path exists
- base_path.mkdir(parents=True, exist_ok=True)
-
- # Get current UTC date-time stamp
- date_stamp = benchmark_start_time.strftime("%Y%m%dT%H%M%S")
-
- # Default run name
- run_name = "full_run"
-
- # Map command-line arguments to their respective labels
- arg_labels = {
- "--test": None,
- "--category": None,
- "--maintain": "maintain",
- "--improve": "improve",
- "--explore": "explore",
- }
-
- # Identify the relevant command-line argument
- for arg, label in arg_labels.items():
- if arg in sys.argv:
- test_arg = sys.argv[sys.argv.index(arg) + 1] if label is None else None
- run_name = arg.strip("--")
- if test_arg:
- run_name = f"{run_name}_{test_arg}"
- break
-
- # Create the full new directory path with ISO standard UTC date-time stamp
- report_path = base_path / f"{date_stamp}_{run_name}"
-
- # Ensure the new directory is created
- report_path.mkdir(exist_ok=True)
- return report_path
-
-
-class AgentBenchmarkConfig(BaseModel):
- """
- This class represents the configuration for the Agent agbenchmark.
- It includes the following attributes:
- - agent_benchmark_config_path: The path to the agent benchmark config that this object was created from.
- - reports_folder: The path to the folder where the benchmark reports will be stored.
- - host: The host where the benchmark is run.
- """
-
- agent_benchmark_config_path: Path | None = None
- reports_folder: Path | None = None
- host: str | None
-
- def get_reports_location(self) -> Path:
- # if not self.reports_folder:
- # self.reports_folder = (
- # Path(self.agent_benchmark_config_path).parent / "reports"
- # ).resolve()
- return Path.cwd() / "agbenchmark_config" / "reports"
-
- def get_reports_path(self, benchmark_start_time: datetime) -> Path:
- return calculate_info_test_path(
- self.get_reports_location(), benchmark_start_time
- )
-
- def get_regression_reports_path(self) -> Path:
- return self.get_reports_location() / "regression_tests.json"
-
- def get_success_rate_path(self) -> Path:
- return self.get_reports_location() / "success_rate.json"
-
- def get_agent_home_directory(self) -> Path:
- return Path(self.agent_benchmark_config_path).resolve().parent
-
-
-class Info(BaseModel):
- difficulty: DifficultyLevel
- description: constr(regex=r"^Tests if the agent can.*")
- side_effects: List[str]
-
- @validator("difficulty", pre=True)
- def difficulty_to_enum(cls: "Info", v: str | DifficultyLevel) -> DifficultyLevel:
- """Convert a string to an instance of DifficultyLevel."""
- if isinstance(v, DifficultyLevel):
- return v
-
- if isinstance(v, str):
- try:
- return DifficultyLevel(v.lower())
- except ValueError:
- pass
-
- raise ValueError(f"Cannot convert {v} to DifficultyLevel.")
-
-
-class Eval(BaseModel):
- type: str
- scoring: Optional[str]
- template: Optional[str]
- examples: Optional[str]
-
- @validator("scoring", "template", always=True)
- def validate_eval_fields(cls, v, values, field):
- if "type" in values and values["type"] == "llm":
- if v is None:
- raise ValueError(f"{field.name} must be provided when type is 'llm'")
- else:
- if v is not None:
- raise ValueError(f"{field.name} should only exist when type is 'llm'")
- return v
-
- @validator("scoring")
- def validate_scoring(cls, v):
- if v is not None and v not in ["percentage", "scale", "binary"]:
- raise ValueError(
- "scoring must be either 'percentage', 'scale', or 'binary'"
- )
- return v
-
- @validator("template")
- def validate_template(cls, v):
- if v is not None and v not in ["rubric", "reference", "question", "custom"]:
- raise ValueError(
- "template must be either 'rubric', 'reference', 'question', or 'custom'"
- )
- return v
-
-
-class Ground(BaseModel):
- answer: str
- should_contain: Optional[List[str]] = None
- should_not_contain: Optional[List[str]] = None
- files: List[str]
- case_sensitive: Optional[bool] = True
- eval: Eval
-
-
class Category(str, Enum):
- DATA = "data"
GENERALIST = "general"
+ DATA = "data"
CODING = "coding"
SCRAPE_SYNTHESIZE = "scrape_synthesize"
+ WEB = "web"
GAIA_1 = "GAIA_1"
GAIA_2 = "GAIA_2"
GAIA_3 = "GAIA_3"
-class ChallengeData(BaseModel):
- name: str
- category: List[Category]
- task: str
- dependencies: List[str]
- cutoff: int
- ground: Ground | Dict[str, Ground]
- info: Info | Dict[str, Info]
- metadata: Optional[Dict[str, Any]] = None
-
- def serialize(self, path: str) -> None:
- with open(path, "w") as file:
- file.write(self.json())
-
- def get_data(self) -> dict:
- return self.dict()
-
- @staticmethod
- def get_json_from_path(json_path: Path | str) -> dict:
- path = Path(json_path).resolve()
- with open(path, "r") as file:
- data = json.load(file)
- return data
-
- @staticmethod
- def deserialize(path: str) -> "ChallengeData":
- # this script is in root/agbenchmark/utils/define_task_types.py
- script_dir = Path(__file__).resolve().parent.parent.parent
- json_path = script_dir / Path(path)
-
- with open(json_path, "r") as file:
- data = json.load(file)
- try:
- return ChallengeData(**data)
- except:
- test = "ok"
-
- def challenge_from_datum(self, file_datum: list[dict[str, Any]]) -> "ChallengeData":
- same_task_data = {
- "name": self.prefix,
- "dependencies": self.dependencies,
- "category": self.shared_category,
- "task": self.task,
- "cutoff": self.cutoff,
- }
-
- if not self.info:
- same_task_data["info"] = {
- datum["name"]: datum["info"] for datum in file_datum
- }
- else:
- same_task_data["info"] = self.info
-
- if not self.ground:
- same_task_data["ground"] = {
- datum["name"]: datum["ground"] for datum in file_datum
- }
- else:
- same_task_data["ground"] = self.ground
-
- return ChallengeData(**same_task_data)
-
- def challenge_from_test_data(self, data: dict[str, Any]) -> "ChallengeData":
- same_task_data = {
- "name": data["name"],
- "dependencies": data["dependencies"],
- "category": data["category"],
- "info": data["info"],
- "ground": data["ground"],
- }
-
- if self.same_task:
- same_task_data["category"].extend(self.shared_category)
- same_task_data["task"] = self.task
- same_task_data["cutoff"] = self.cutoff
- else:
- same_task_data["task"] = data["task"]
- same_task_data["cutoff"] = data["cutoff"]
-
- return ChallengeData(**same_task_data)
+class EvalResult(BaseModel):
+ result: str
+ result_source: Literal["step_output"] | str
+ score: float
+ passed: bool
diff --git a/benchmark/agbenchmark/utils/dependencies/graphs.py b/benchmark/agbenchmark/utils/dependencies/graphs.py
index 8155e2bfd..47d3d5c09 100644
--- a/benchmark/agbenchmark/utils/dependencies/graphs.py
+++ b/benchmark/agbenchmark/utils/dependencies/graphs.py
@@ -1,3 +1,5 @@
+import json
+import logging
import math
from pathlib import Path
from typing import Any, Dict, List, Tuple
@@ -11,6 +13,8 @@ from pyvis.network import Network
from agbenchmark.generate_test import DATA_CATEGORY
from agbenchmark.utils.utils import write_pretty_json
+logger = logging.getLogger(__name__)
+
def bezier_curve(
src: np.ndarray, ctrl: List[float], dst: np.ndarray
@@ -221,8 +225,8 @@ def graph_interactive_network(
f"{source_id_str}_to_{target_id_str}" # Construct a unique edge id
)
if not (source_id_str in nt.get_nodes() and target_id_str in nt.get_nodes()):
- print(
- f"Skipping edge {source_id_str} -> {target_id_str} due to missing nodes."
+ logger.warning(
+ f"Skipping edge {source_id_str} -> {target_id_str} due to missing nodes"
)
continue
nt.add_edge(source_id_str, target_id_str, id=edge_id_str)
@@ -271,9 +275,12 @@ def graph_interactive_network(
"layout": {"hierarchical": hierarchical_options},
}
- # Serialize the graph to JSON
+ # Serialize the graph to JSON and save in appropriate locations
graph_data = {"nodes": nt.nodes, "edges": nt.edges}
+ logger.debug(f"Generated graph data:\n{json.dumps(graph_data, indent=4)}")
+ # FIXME: use more reliable method to find the right location for these files.
+ # This will fail in all cases except if run from the root of our repo.
home_path = Path.cwd()
write_pretty_json(graph_data, home_path / "frontend" / "public" / "graph.json")
@@ -284,7 +291,6 @@ def graph_interactive_network(
# this literally only works in the AutoGPT repo, but this part of the code is not reached if BUILD_SKILL_TREE is false
write_pretty_json(graph_data, flutter_app_path / "tree_structure.json")
validate_skill_tree(graph_data, "")
- import json
# Extract node IDs with category "coding"
@@ -317,9 +323,6 @@ def graph_interactive_network(
scrape_synthesize_tree,
flutter_app_path / "scrape_synthesize_tree_structure.json",
)
- # If you want to convert back to JSON
- filtered_json = json.dumps(graph_data, indent=4)
- print(filtered_json)
if html_graph_path:
file_path = str(Path(html_graph_path).resolve())
diff --git a/benchmark/agbenchmark/utils/get_data_from_helicone.py b/benchmark/agbenchmark/utils/get_data_from_helicone.py
index 1e2f5fcbd..dabb2c8b0 100644
--- a/benchmark/agbenchmark/utils/get_data_from_helicone.py
+++ b/benchmark/agbenchmark/utils/get_data_from_helicone.py
@@ -1,4 +1,5 @@
import json
+import logging
import os
from typing import Optional
@@ -7,6 +8,8 @@ import requests
from agbenchmark.__main__ import BENCHMARK_START_TIME
from agbenchmark.agent_interface import HELICONE_GRAPHQL_LOGS
+logger = logging.getLogger(__name__)
+
def get_data_from_helicone(challenge: str) -> Optional[float]:
# Define the endpoint of your GraphQL server
@@ -38,8 +41,8 @@ query ExampleQuery($properties: [PropertyFilter!]){
]
}
if HELICONE_GRAPHQL_LOGS:
- print(query)
- print(json.dumps(variables, indent=4))
+ logger.debug(f"Executing Helicone query:\n{query.strip()}")
+ logger.debug(f"Query variables:\n{json.dumps(variables, indent=4)}")
operation_name = "ExampleQuery"
@@ -59,24 +62,22 @@ query ExampleQuery($properties: [PropertyFilter!]){
data = response.json()
except requests.HTTPError as http_err:
- print(f"HTTP error occurred: {http_err}")
- return None # Re-raise the exception to stop execution
+ logger.error(f"Helicone returned an HTTP error: {http_err}")
+ return None
except json.JSONDecodeError:
- print(f"Invalid JSON response: {response.text if response else 'No response'}")
+ raw_response = response.text # type: ignore
+ logger.error(
+ f"Helicone returned an invalid JSON response: '''{raw_response}'''"
+ )
return None
except Exception as err:
- print(f"Other error occurred: {err}")
+ logger.error(f"Error while trying to get data from Helicone: {err}")
return None
- try:
- if data is None or data.get("data") is None:
- print("Invalid response received from server: no data")
- return None
- return (
- data.get("data", {})
- .get("aggregatedHeliconeRequest", {})
- .get("costUSD", None)
- )
- except Exception as err:
- print(f"Error occurred while parsing response: {err}")
+ if data is None or data.get("data") is None:
+ logger.error("Invalid response received from Helicone: no data")
+ logger.error(f"Offending response: {response}")
return None
+ return (
+ data.get("data", {}).get("aggregatedHeliconeRequest", {}).get("costUSD", None)
+ )
diff --git a/benchmark/agbenchmark/utils/logging.py b/benchmark/agbenchmark/utils/logging.py
new file mode 100644
index 000000000..9a8f9f41d
--- /dev/null
+++ b/benchmark/agbenchmark/utils/logging.py
@@ -0,0 +1,74 @@
+from __future__ import annotations
+
+import logging
+
+from colorama import Fore, Style
+
+SIMPLE_LOG_FORMAT = "[%(asctime)s] %(levelname)s %(message)s"
+DEBUG_LOG_FORMAT = "[%(asctime)s] %(levelname)s %(filename)s:%(lineno)03d %(message)s"
+
+
+def configure_logging(
+ level: int = logging.INFO,
+) -> None:
+ """Configure the native logging module."""
+
+ # Auto-adjust default log format based on log level
+ log_format = DEBUG_LOG_FORMAT if level == logging.DEBUG else SIMPLE_LOG_FORMAT
+
+ console_handler = logging.StreamHandler()
+ console_handler.setFormatter(FancyConsoleFormatter(log_format))
+
+ # Configure the root logger
+ logging.basicConfig(
+ level=level,
+ format=log_format,
+ handlers=[console_handler],
+ )
+
+
+class FancyConsoleFormatter(logging.Formatter):
+ """
+ A custom logging formatter designed for console output.
+
+ This formatter enhances the standard logging output with color coding. The color
+ coding is based on the level of the log message, making it easier to distinguish
+ between different types of messages in the console output.
+
+ The color for each level is defined in the LEVEL_COLOR_MAP class attribute.
+ """
+
+ # level -> (level & text color, title color)
+ LEVEL_COLOR_MAP = {
+ logging.DEBUG: Fore.LIGHTBLACK_EX,
+ logging.INFO: Fore.BLUE,
+ logging.WARNING: Fore.YELLOW,
+ logging.ERROR: Fore.RED,
+ logging.CRITICAL: Fore.RED + Style.BRIGHT,
+ }
+
+ def format(self, record: logging.LogRecord) -> str:
+ # Make sure `msg` is a string
+ if not hasattr(record, "msg"):
+ record.msg = ""
+ elif not type(record.msg) is str:
+ record.msg = str(record.msg)
+
+ # Justify the level name to 5 characters minimum
+ record.levelname = record.levelname.ljust(5)
+
+ # Determine default color based on error level
+ level_color = ""
+ if record.levelno in self.LEVEL_COLOR_MAP:
+ level_color = self.LEVEL_COLOR_MAP[record.levelno]
+ record.levelname = f"{level_color}{record.levelname}{Style.RESET_ALL}"
+
+ # Determine color for message
+ color = getattr(record, "color", level_color)
+ color_is_specified = hasattr(record, "color")
+
+ # Don't color INFO messages unless the color is explicitly specified.
+ if color and (record.levelno != logging.INFO or color_is_specified):
+ record.msg = f"{color}{record.msg}{Style.RESET_ALL}"
+
+ return super().format(record)
diff --git a/benchmark/agbenchmark/utils/utils.py b/benchmark/agbenchmark/utils/utils.py
index 2fc51d212..0f0ad56d9 100644
--- a/benchmark/agbenchmark/utils/utils.py
+++ b/benchmark/agbenchmark/utils/utils.py
@@ -1,17 +1,27 @@
# radio charts, logs, helper functions for tests, anything else relevant.
import json
+import logging
import os
import re
+from enum import Enum
from pathlib import Path
-from typing import Any, List, Optional
+from typing import Any, Callable, Iterable, Optional, TypeVar, overload
+import click
from dotenv import load_dotenv
+from pydantic import BaseModel
-load_dotenv()
+from agbenchmark.reports.processing.report_types import Test
from agbenchmark.utils.data_types import DIFFICULTY_MAP, DifficultyLevel
+load_dotenv()
+
AGENT_NAME = os.getenv("AGENT_NAME")
-REPORT_LOCATION = os.getenv("REPORT_LOCATION", None)
+
+logger = logging.getLogger(__name__)
+
+T = TypeVar("T")
+E = TypeVar("E", bound=Enum)
def replace_backslash(value: Any) -> Any:
@@ -27,17 +37,6 @@ def replace_backslash(value: Any) -> Any:
return value
-def calculate_success_percentage(results: list[bool]) -> float:
- # Take the last 10 results or all if less than 10
- last_results = results[-10:] if len(results) > 10 else results
- success_count = last_results.count(True)
- total_count = len(last_results)
- if total_count == 0:
- return 0
- success_percentage = (success_count / total_count) * 100 # as a percentage
- return round(success_percentage, 2)
-
-
def get_test_path(json_file: str | Path) -> str:
if isinstance(json_file, str):
json_file = Path(json_file)
@@ -59,41 +58,41 @@ def get_test_path(json_file: str | Path) -> str:
def get_highest_success_difficulty(
- data: dict, just_string: Optional[bool] = None
+ data: dict[str, Test], just_string: Optional[bool] = None
) -> str:
highest_difficulty = None
highest_difficulty_level = 0
for test_name, test_data in data.items():
try:
- if test_data.get("tests", None):
- highest_difficulty_str = test_data["metrics"]["highest_difficulty"]
+ if any(r.success for r in test_data.results):
+ difficulty_str = test_data.difficulty
+ if not difficulty_str:
+ continue
+
try:
- highest_difficulty = DifficultyLevel[highest_difficulty_str]
- highest_difficulty_level = DIFFICULTY_MAP[highest_difficulty]
+ difficulty_enum = DifficultyLevel[difficulty_str.lower()]
+ difficulty_level = DIFFICULTY_MAP[difficulty_enum]
+
+ if difficulty_level > highest_difficulty_level:
+ highest_difficulty = difficulty_enum
+ highest_difficulty_level = difficulty_level
except KeyError:
- print(
- f"Unexpected difficulty level '{highest_difficulty_str}' in test '{test_name}'"
+ logger.warning(
+ f"Unexpected difficulty level '{difficulty_str}' "
+ f"in test '{test_name}'"
)
continue
- else:
- if test_data["metrics"]["success"]:
- difficulty_str = test_data["metrics"]["difficulty"]
-
- try:
- difficulty_enum = DifficultyLevel[difficulty_str.lower()]
- difficulty_level = DIFFICULTY_MAP[difficulty_enum]
-
- if difficulty_level > highest_difficulty_level:
- highest_difficulty = difficulty_enum
- highest_difficulty_level = difficulty_level
- except KeyError:
- print(
- f"Unexpected difficulty level '{difficulty_str}' in test '{test_name}'"
- )
- continue
- except Exception:
- print(f"Make sure you selected the right test, no reports were generated.")
+ except Exception as e:
+ logger.warning(
+ "An unexpected error [1] occurred while analyzing report [2]."
+ "Please notify a maintainer.\n"
+ f"Report data [1]: {data}\n"
+ f"Error [2]: {e}"
+ )
+ logger.warning(
+ "Make sure you selected the right test, no reports were generated."
+ )
break
if highest_difficulty is not None:
@@ -116,22 +115,13 @@ def get_highest_success_difficulty(
# remote_url = remote_url[:-4]
# git_commit_sha = f"{remote_url}/tree/{repo.head.commit.hexsha}"
-# # print(f"GIT_COMMIT_SHA: {git_commit_sha}")
+# # logger.debug(f"GIT_COMMIT_SHA: {git_commit_sha}")
# return git_commit_sha
# except Exception:
-# # print(f"{directory} is not a git repository!")
+# # logger.error(f"{directory} is not a git repository!")
# return None
-def agent_eligibible_for_optional_categories(
- optional_challenge_categories: List, agent_categories: List
-) -> bool:
- for element in optional_challenge_categories:
- if element not in agent_categories:
- return False
- return True
-
-
def write_pretty_json(data, json_file):
sorted_data = deep_sort(data)
json_graph = json.dumps(sorted_data, indent=4)
@@ -140,6 +130,42 @@ def write_pretty_json(data, json_file):
f.write("\n")
+def pretty_print_model(model: BaseModel, include_header: bool = True) -> None:
+ indent = ""
+ if include_header:
+ # Try to find the ID and/or name attribute of the model
+ id, name = None, None
+ for attr, value in model.dict().items():
+ if attr == "id" or attr.endswith("_id"):
+ id = value
+ if attr.endswith("name"):
+ name = value
+ if id and name:
+ break
+ identifiers = [v for v in [name, id] if v]
+ click.echo(
+ f"{model.__repr_name__()}{repr(identifiers) if identifiers else ''}:"
+ )
+ indent = " " * 2
+
+ k_col_width = max(len(k) for k in model.dict().keys())
+ for k, v in model.dict().items():
+ v_fmt = repr(v)
+ if v is None or v == "":
+ v_fmt = click.style(v_fmt, fg="black")
+ elif type(v) is bool:
+ v_fmt = click.style(v_fmt, fg="green" if v else "red")
+ elif type(v) is str and "\n" in v:
+ v_fmt = f"\n{v}".replace(
+ "\n", f"\n{indent} {click.style('|', fg='black')} "
+ )
+ if isinstance(v, Enum):
+ v_fmt = click.style(v.value, fg="blue")
+ elif type(v) is list and len(v) > 0 and isinstance(v[0], Enum):
+ v_fmt = ", ".join(click.style(lv.value, fg="blue") for lv in v)
+ click.echo(f"{indent}{k: <{k_col_width}} = {v_fmt}")
+
+
def deep_sort(obj):
"""
Recursively sort the keys in JSON object
@@ -149,3 +175,38 @@ def deep_sort(obj):
if isinstance(obj, list):
return [deep_sort(elem) for elem in obj]
return obj
+
+
+@overload
+def sorted_by_enum_index(
+ sortable: Iterable[E],
+ enum: type[E],
+ *,
+ reverse: bool = False,
+) -> list[E]:
+ ...
+
+
+@overload
+def sorted_by_enum_index(
+ sortable: Iterable[T],
+ enum: type[Enum],
+ *,
+ key: Callable[[T], Enum | None],
+ reverse: bool = False,
+) -> list[T]:
+ ...
+
+
+def sorted_by_enum_index(
+ sortable: Iterable[T],
+ enum: type[Enum],
+ *,
+ key: Callable[[T], Enum | None] = lambda x: x, # type: ignore
+ reverse: bool = False,
+) -> list[T]:
+ return sorted(
+ sortable,
+ key=lambda x: enum._member_names_.index(e.name) if (e := key(x)) else 420e3,
+ reverse=reverse,
+ )
diff --git a/benchmark/notebooks/LLM Score Experimentation.ipynb b/benchmark/notebooks/LLM Score Experimentation.ipynb
index b14577fdb..745913971 100644
--- a/benchmark/notebooks/LLM Score Experimentation.ipynb
+++ b/benchmark/notebooks/LLM Score Experimentation.ipynb
@@ -7,23 +7,21 @@
"metadata": {},
"outputs": [],
"source": [
- "import openai\n",
"import os\n",
"from dotenv import load_dotenv\n",
+ "from openai import OpenAI\n",
"\n",
"load_dotenv()\n",
"\n",
- "OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\")\n",
- "\n",
"def llm_eval(evaluation: str) -> float:\n",
- " openai.api_key = OPENAI_API_KEY\n",
- " answer = openai.ChatCompletion.create(\n",
+ " openai_client = OpenAI()\n",
+ " answer = openai_client.chat.completions.create(\n",
" model=\"gpt-4\",\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": evaluation},\n",
" ],\n",
" )\n",
- " return answer[\"choices\"][0][\"message\"][\"content\"]"
+ " return answer.choices[0].message.content"
]
},
{
diff --git a/benchmark/poetry.lock b/benchmark/poetry.lock
index 9a27d456f..70bef01f6 100644
--- a/benchmark/poetry.lock
+++ b/benchmark/poetry.lock
@@ -1,112 +1,117 @@
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
[[package]]
+name = "agent-protocol-client"
+version = "1.1.0"
+description = "Agent Communication Protocol Client"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "agent_protocol_client-1.1.0-py3-none-any.whl", hash = "sha256:0e8c6c97244189666ed18e320410abddce8c9dfb75437da1e590bbef3b6268be"},
+ {file = "agent_protocol_client-1.1.0.tar.gz", hash = "sha256:aa7e1042de1249477fdc29c2df08a44f2233dade9c02c1279e37c98e9d3a0d72"},
+]
+
+[package.dependencies]
+aiohttp = ">=3.8.4,<4.0.0"
+pydantic = ">=1.10.5,<2.0.0"
+python-dateutil = ">=2.8.2,<3.0.0"
+urllib3 = ">=1.25.3,<2.0.0"
+
+[[package]]
name = "aiohttp"
-version = "3.8.5"
+version = "3.9.3"
description = "Async http client/server framework (asyncio)"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
files = [
- {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a94159871304770da4dd371f4291b20cac04e8c94f11bdea1c3478e557fbe0d8"},
- {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:13bf85afc99ce6f9ee3567b04501f18f9f8dbbb2ea11ed1a2e079670403a7c84"},
- {file = "aiohttp-3.8.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ce2ac5708501afc4847221a521f7e4b245abf5178cf5ddae9d5b3856ddb2f3a"},
- {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96943e5dcc37a6529d18766597c491798b7eb7a61d48878611298afc1fca946c"},
- {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ad5c3c4590bb3cc28b4382f031f3783f25ec223557124c68754a2231d989e2b"},
- {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c413c633d0512df4dc7fd2373ec06cc6a815b7b6d6c2f208ada7e9e93a5061d"},
- {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df72ac063b97837a80d80dec8d54c241af059cc9bb42c4de68bd5b61ceb37caa"},
- {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c48c5c0271149cfe467c0ff8eb941279fd6e3f65c9a388c984e0e6cf57538e14"},
- {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:368a42363c4d70ab52c2c6420a57f190ed3dfaca6a1b19afda8165ee16416a82"},
- {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7607ec3ce4993464368505888af5beb446845a014bc676d349efec0e05085905"},
- {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0d21c684808288a98914e5aaf2a7c6a3179d4df11d249799c32d1808e79503b5"},
- {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:312fcfbacc7880a8da0ae8b6abc6cc7d752e9caa0051a53d217a650b25e9a691"},
- {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad093e823df03bb3fd37e7dec9d4670c34f9e24aeace76808fc20a507cace825"},
- {file = "aiohttp-3.8.5-cp310-cp310-win32.whl", hash = "sha256:33279701c04351a2914e1100b62b2a7fdb9a25995c4a104259f9a5ead7ed4802"},
- {file = "aiohttp-3.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:6e4a280e4b975a2e7745573e3fc9c9ba0d1194a3738ce1cbaa80626cc9b4f4df"},
- {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae871a964e1987a943d83d6709d20ec6103ca1eaf52f7e0d36ee1b5bebb8b9b9"},
- {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:461908b2578955045efde733719d62f2b649c404189a09a632d245b445c9c975"},
- {file = "aiohttp-3.8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72a860c215e26192379f57cae5ab12b168b75db8271f111019509a1196dfc780"},
- {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc14be025665dba6202b6a71cfcdb53210cc498e50068bc088076624471f8bb9"},
- {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af740fc2711ad85f1a5c034a435782fbd5b5f8314c9a3ef071424a8158d7f6b"},
- {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:841cd8233cbd2111a0ef0a522ce016357c5e3aff8a8ce92bcfa14cef890d698f"},
- {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed1c46fb119f1b59304b5ec89f834f07124cd23ae5b74288e364477641060ff"},
- {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84f8ae3e09a34f35c18fa57f015cc394bd1389bce02503fb30c394d04ee6b938"},
- {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62360cb771707cb70a6fd114b9871d20d7dd2163a0feafe43fd115cfe4fe845e"},
- {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23fb25a9f0a1ca1f24c0a371523546366bb642397c94ab45ad3aedf2941cec6a"},
- {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0ba0d15164eae3d878260d4c4df859bbdc6466e9e6689c344a13334f988bb53"},
- {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5d20003b635fc6ae3f96d7260281dfaf1894fc3aa24d1888a9b2628e97c241e5"},
- {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0175d745d9e85c40dcc51c8f88c74bfbaef9e7afeeeb9d03c37977270303064c"},
- {file = "aiohttp-3.8.5-cp311-cp311-win32.whl", hash = "sha256:2e1b1e51b0774408f091d268648e3d57f7260c1682e7d3a63cb00d22d71bb945"},
- {file = "aiohttp-3.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:043d2299f6dfdc92f0ac5e995dfc56668e1587cea7f9aa9d8a78a1b6554e5755"},
- {file = "aiohttp-3.8.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cae533195e8122584ec87531d6df000ad07737eaa3c81209e85c928854d2195c"},
- {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f21e83f355643c345177a5d1d8079f9f28b5133bcd154193b799d380331d5d3"},
- {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a75ef35f2df54ad55dbf4b73fe1da96f370e51b10c91f08b19603c64004acc"},
- {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e2e9839e14dd5308ee773c97115f1e0a1cb1d75cbeeee9f33824fa5144c7634"},
- {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44e65da1de4403d0576473e2344828ef9c4c6244d65cf4b75549bb46d40b8dd"},
- {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d847e4cde6ecc19125ccbc9bfac4a7ab37c234dd88fbb3c5c524e8e14da543"},
- {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c7a815258e5895d8900aec4454f38dca9aed71085f227537208057853f9d13f2"},
- {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:8b929b9bd7cd7c3939f8bcfffa92fae7480bd1aa425279d51a89327d600c704d"},
- {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5db3a5b833764280ed7618393832e0853e40f3d3e9aa128ac0ba0f8278d08649"},
- {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:a0215ce6041d501f3155dc219712bc41252d0ab76474615b9700d63d4d9292af"},
- {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:fd1ed388ea7fbed22c4968dd64bab0198de60750a25fe8c0c9d4bef5abe13824"},
- {file = "aiohttp-3.8.5-cp36-cp36m-win32.whl", hash = "sha256:6e6783bcc45f397fdebc118d772103d751b54cddf5b60fbcc958382d7dd64f3e"},
- {file = "aiohttp-3.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:b5411d82cddd212644cf9360879eb5080f0d5f7d809d03262c50dad02f01421a"},
- {file = "aiohttp-3.8.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:01d4c0c874aa4ddfb8098e85d10b5e875a70adc63db91f1ae65a4b04d3344cda"},
- {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5980a746d547a6ba173fd5ee85ce9077e72d118758db05d229044b469d9029a"},
- {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a482e6da906d5e6e653be079b29bc173a48e381600161c9932d89dfae5942ef"},
- {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80bd372b8d0715c66c974cf57fe363621a02f359f1ec81cba97366948c7fc873"},
- {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1161b345c0a444ebcf46bf0a740ba5dcf50612fd3d0528883fdc0eff578006a"},
- {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd56db019015b6acfaaf92e1ac40eb8434847d9bf88b4be4efe5bfd260aee692"},
- {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:153c2549f6c004d2754cc60603d4668899c9895b8a89397444a9c4efa282aaf4"},
- {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4a01951fabc4ce26ab791da5f3f24dca6d9a6f24121746eb19756416ff2d881b"},
- {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bfb9162dcf01f615462b995a516ba03e769de0789de1cadc0f916265c257e5d8"},
- {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7dde0009408969a43b04c16cbbe252c4f5ef4574ac226bc8815cd7342d2028b6"},
- {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4149d34c32f9638f38f544b3977a4c24052042affa895352d3636fa8bffd030a"},
- {file = "aiohttp-3.8.5-cp37-cp37m-win32.whl", hash = "sha256:68c5a82c8779bdfc6367c967a4a1b2aa52cd3595388bf5961a62158ee8a59e22"},
- {file = "aiohttp-3.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2cf57fb50be5f52bda004b8893e63b48530ed9f0d6c96c84620dc92fe3cd9b9d"},
- {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:eca4bf3734c541dc4f374ad6010a68ff6c6748f00451707f39857f429ca36ced"},
- {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1274477e4c71ce8cfe6c1ec2f806d57c015ebf84d83373676036e256bc55d690"},
- {file = "aiohttp-3.8.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28c543e54710d6158fc6f439296c7865b29e0b616629767e685a7185fab4a6b9"},
- {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:910bec0c49637d213f5d9877105d26e0c4a4de2f8b1b29405ff37e9fc0ad52b8"},
- {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5443910d662db951b2e58eb70b0fbe6b6e2ae613477129a5805d0b66c54b6cb7"},
- {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e460be6978fc24e3df83193dc0cc4de46c9909ed92dd47d349a452ef49325b7"},
- {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb1558def481d84f03b45888473fc5a1f35747b5f334ef4e7a571bc0dfcb11f8"},
- {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34dd0c107799dcbbf7d48b53be761a013c0adf5571bf50c4ecad5643fe9cfcd0"},
- {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aa1990247f02a54185dc0dff92a6904521172a22664c863a03ff64c42f9b5410"},
- {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0e584a10f204a617d71d359fe383406305a4b595b333721fa50b867b4a0a1548"},
- {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a3cf433f127efa43fee6b90ea4c6edf6c4a17109d1d037d1a52abec84d8f2e42"},
- {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c11f5b099adafb18e65c2c997d57108b5bbeaa9eeee64a84302c0978b1ec948b"},
- {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:84de26ddf621d7ac4c975dbea4c945860e08cccde492269db4e1538a6a6f3c35"},
- {file = "aiohttp-3.8.5-cp38-cp38-win32.whl", hash = "sha256:ab88bafedc57dd0aab55fa728ea10c1911f7e4d8b43e1d838a1739f33712921c"},
- {file = "aiohttp-3.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:5798a9aad1879f626589f3df0f8b79b3608a92e9beab10e5fda02c8a2c60db2e"},
- {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a6ce61195c6a19c785df04e71a4537e29eaa2c50fe745b732aa937c0c77169f3"},
- {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:773dd01706d4db536335fcfae6ea2440a70ceb03dd3e7378f3e815b03c97ab51"},
- {file = "aiohttp-3.8.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f83a552443a526ea38d064588613aca983d0ee0038801bc93c0c916428310c28"},
- {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f7372f7341fcc16f57b2caded43e81ddd18df53320b6f9f042acad41f8e049a"},
- {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea353162f249c8097ea63c2169dd1aa55de1e8fecbe63412a9bc50816e87b761"},
- {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d47ae48db0b2dcf70bc8a3bc72b3de86e2a590fc299fdbbb15af320d2659de"},
- {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d827176898a2b0b09694fbd1088c7a31836d1a505c243811c87ae53a3f6273c1"},
- {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3562b06567c06439d8b447037bb655ef69786c590b1de86c7ab81efe1c9c15d8"},
- {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e874cbf8caf8959d2adf572a78bba17cb0e9d7e51bb83d86a3697b686a0ab4d"},
- {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6809a00deaf3810e38c628e9a33271892f815b853605a936e2e9e5129762356c"},
- {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:33776e945d89b29251b33a7e7d006ce86447b2cfd66db5e5ded4e5cd0340585c"},
- {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eaeed7abfb5d64c539e2db173f63631455f1196c37d9d8d873fc316470dfbacd"},
- {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e91d635961bec2d8f19dfeb41a539eb94bd073f075ca6dae6c8dc0ee89ad6f91"},
- {file = "aiohttp-3.8.5-cp39-cp39-win32.whl", hash = "sha256:00ad4b6f185ec67f3e6562e8a1d2b69660be43070bd0ef6fcec5211154c7df67"},
- {file = "aiohttp-3.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:c0a9034379a37ae42dea7ac1e048352d96286626251862e448933c0f59cbd79c"},
- {file = "aiohttp-3.8.5.tar.gz", hash = "sha256:b9552ec52cc147dbf1944ac7ac98af7602e51ea2dcd076ed194ca3c0d1c7d0bc"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"},
+ {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"},
+ {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"},
+ {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"},
+ {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"},
+ {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"},
+ {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"},
+ {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"},
+ {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"},
+ {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"},
+ {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"},
+ {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"},
+ {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"},
+ {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"},
+ {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"},
+ {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"},
+ {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"},
+ {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"},
+ {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"},
+ {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"},
+ {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"},
+ {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"},
+ {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"},
+ {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"},
+ {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"},
+ {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"},
+ {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"},
]
[package.dependencies]
aiosignal = ">=1.1.2"
-async-timeout = ">=4.0.0a3,<5.0"
+async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""}
attrs = ">=17.3.0"
-charset-normalizer = ">=2.0,<4.0"
frozenlist = ">=1.1.1"
multidict = ">=4.5,<7.0"
yarl = ">=1.0,<2.0"
[package.extras]
-speedups = ["Brotli", "aiodns", "cchardet"]
+speedups = ["Brotli", "aiodns", "brotlicffi"]
[[package]]
name = "aiosignal"
@@ -124,52 +129,43 @@ frozenlist = ">=1.1.0"
[[package]]
name = "anyio"
-version = "4.0.0"
+version = "4.2.0"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
optional = false
python-versions = ">=3.8"
files = [
- {file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"},
- {file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"},
+ {file = "anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee"},
+ {file = "anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f"},
]
[package.dependencies]
exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""}
idna = ">=2.8"
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)"]
-test = ["anyio[trio]", "coverage[toml] (>=7)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
-trio = ["trio (>=0.22)"]
-
-[[package]]
-name = "appnope"
-version = "0.1.3"
-description = "Disable App Nap on macOS >= 10.9"
-optional = false
-python-versions = "*"
-files = [
- {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"},
- {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"},
-]
+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)"]
[[package]]
name = "asttokens"
-version = "2.4.0"
+version = "2.4.1"
description = "Annotate AST trees with source code positions"
optional = false
python-versions = "*"
files = [
- {file = "asttokens-2.4.0-py2.py3-none-any.whl", hash = "sha256:cf8fc9e61a86461aa9fb161a14a0841a03c405fa829ac6b202670b3495d2ce69"},
- {file = "asttokens-2.4.0.tar.gz", hash = "sha256:2e0171b991b2c959acc6c49318049236844a5da1d65ba2672c4880c1c894834e"},
+ {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"},
+ {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"},
]
[package.dependencies]
six = ">=1.12.0"
[package.extras]
-test = ["astroid", "pytest"]
+astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"]
+test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"]
[[package]]
name = "async-timeout"
@@ -184,21 +180,22 @@ files = [
[[package]]
name = "attrs"
-version = "23.1.0"
+version = "23.2.0"
description = "Classes Without Boilerplate"
optional = false
python-versions = ">=3.7"
files = [
- {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
- {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
+ {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"},
+ {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"},
]
[package.extras]
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
-dev = ["attrs[docs,tests]", "pre-commit"]
+dev = ["attrs[tests]", "pre-commit"]
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
tests = ["attrs[tests-no-zope]", "zope-interface"]
-tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"]
+tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"]
[[package]]
name = "autoflake"
@@ -216,17 +213,6 @@ pyflakes = ">=1.1.0,<3"
tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""}
[[package]]
-name = "backcall"
-version = "0.2.0"
-description = "Specifications for callback functions passed in to an API"
-optional = false
-python-versions = "*"
-files = [
- {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"},
- {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
-]
-
-[[package]]
name = "black"
version = "22.3.0"
description = "The uncompromising code formatter."
@@ -273,24 +259,24 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "cachetools"
-version = "5.3.1"
+version = "5.3.2"
description = "Extensible memoizing collections and decorators"
optional = false
python-versions = ">=3.7"
files = [
- {file = "cachetools-5.3.1-py3-none-any.whl", hash = "sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590"},
- {file = "cachetools-5.3.1.tar.gz", hash = "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b"},
+ {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"},
+ {file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"},
]
[[package]]
name = "certifi"
-version = "2023.7.22"
+version = "2023.11.17"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.6"
files = [
- {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"},
- {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"},
+ {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"},
+ {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"},
]
[[package]]
@@ -370,86 +356,101 @@ files = [
[[package]]
name = "charset-normalizer"
-version = "3.2.0"
+version = "3.3.2"
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.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"},
- {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"},
- {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"},
- {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"},
- {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"},
- {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"},
- {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"},
+ {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"},
]
[[package]]
@@ -467,6 +468,23 @@ files = [
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
+name = "click-default-group"
+version = "1.2.4"
+description = "click_default_group"
+optional = false
+python-versions = ">=2.7"
+files = [
+ {file = "click_default_group-1.2.4-py2.py3-none-any.whl", hash = "sha256:9b60486923720e7fc61731bdb32b617039aba820e22e1c88766b1125592eaa5f"},
+ {file = "click_default_group-1.2.4.tar.gz", hash = "sha256:eb3f3c99ec0d456ca6cd2a7f08f7d4e91771bef51b01bdd9580cc6450fe1251e"},
+]
+
+[package.dependencies]
+click = "*"
+
+[package.extras]
+test = ["pytest"]
+
+[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
@@ -479,142 +497,76 @@ files = [
[[package]]
name = "contourpy"
-version = "1.1.0"
-description = "Python library for calculating contours of 2D quadrilateral grids"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "contourpy-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:89f06eff3ce2f4b3eb24c1055a26981bffe4e7264acd86f15b97e40530b794bc"},
- {file = "contourpy-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dffcc2ddec1782dd2f2ce1ef16f070861af4fb78c69862ce0aab801495dda6a3"},
- {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25ae46595e22f93592d39a7eac3d638cda552c3e1160255258b695f7b58e5655"},
- {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:17cfaf5ec9862bc93af1ec1f302457371c34e688fbd381f4035a06cd47324f48"},
- {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18a64814ae7bce73925131381603fff0116e2df25230dfc80d6d690aa6e20b37"},
- {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90c81f22b4f572f8a2110b0b741bb64e5a6427e0a198b2cdc1fbaf85f352a3aa"},
- {file = "contourpy-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:53cc3a40635abedbec7f1bde60f8c189c49e84ac180c665f2cd7c162cc454baa"},
- {file = "contourpy-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:1f795597073b09d631782e7245016a4323cf1cf0b4e06eef7ea6627e06a37ff2"},
- {file = "contourpy-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0b7b04ed0961647691cfe5d82115dd072af7ce8846d31a5fac6c142dcce8b882"},
- {file = "contourpy-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27bc79200c742f9746d7dd51a734ee326a292d77e7d94c8af6e08d1e6c15d545"},
- {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052cc634bf903c604ef1a00a5aa093c54f81a2612faedaa43295809ffdde885e"},
- {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9382a1c0bc46230fb881c36229bfa23d8c303b889b788b939365578d762b5c18"},
- {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5cec36c5090e75a9ac9dbd0ff4a8cf7cecd60f1b6dc23a374c7d980a1cd710e"},
- {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f0cbd657e9bde94cd0e33aa7df94fb73c1ab7799378d3b3f902eb8eb2e04a3a"},
- {file = "contourpy-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:181cbace49874f4358e2929aaf7ba84006acb76694102e88dd15af861996c16e"},
- {file = "contourpy-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fb3b7d9e6243bfa1efb93ccfe64ec610d85cfe5aec2c25f97fbbd2e58b531256"},
- {file = "contourpy-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bcb41692aa09aeb19c7c213411854402f29f6613845ad2453d30bf421fe68fed"},
- {file = "contourpy-1.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5d123a5bc63cd34c27ff9c7ac1cd978909e9c71da12e05be0231c608048bb2ae"},
- {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62013a2cf68abc80dadfd2307299bfa8f5aa0dcaec5b2954caeb5fa094171103"},
- {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b6616375d7de55797d7a66ee7d087efe27f03d336c27cf1f32c02b8c1a5ac70"},
- {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:317267d915490d1e84577924bd61ba71bf8681a30e0d6c545f577363157e5e94"},
- {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d551f3a442655f3dcc1285723f9acd646ca5858834efeab4598d706206b09c9f"},
- {file = "contourpy-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e7a117ce7df5a938fe035cad481b0189049e8d92433b4b33aa7fc609344aafa1"},
- {file = "contourpy-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:d4f26b25b4f86087e7d75e63212756c38546e70f2a92d2be44f80114826e1cd4"},
- {file = "contourpy-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc00bb4225d57bff7ebb634646c0ee2a1298402ec10a5fe7af79df9a51c1bfd9"},
- {file = "contourpy-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:189ceb1525eb0655ab8487a9a9c41f42a73ba52d6789754788d1883fb06b2d8a"},
- {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f2931ed4741f98f74b410b16e5213f71dcccee67518970c42f64153ea9313b9"},
- {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30f511c05fab7f12e0b1b7730ebdc2ec8deedcfb505bc27eb570ff47c51a8f15"},
- {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:143dde50520a9f90e4a2703f367cf8ec96a73042b72e68fcd184e1279962eb6f"},
- {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e94bef2580e25b5fdb183bf98a2faa2adc5b638736b2c0a4da98691da641316a"},
- {file = "contourpy-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ed614aea8462735e7d70141374bd7650afd1c3f3cb0c2dbbcbe44e14331bf002"},
- {file = "contourpy-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:438ba416d02f82b692e371858143970ed2eb6337d9cdbbede0d8ad9f3d7dd17d"},
- {file = "contourpy-1.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a698c6a7a432789e587168573a864a7ea374c6be8d4f31f9d87c001d5a843493"},
- {file = "contourpy-1.1.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:397b0ac8a12880412da3551a8cb5a187d3298a72802b45a3bd1805e204ad8439"},
- {file = "contourpy-1.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a67259c2b493b00e5a4d0f7bfae51fb4b3371395e47d079a4446e9b0f4d70e76"},
- {file = "contourpy-1.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2b836d22bd2c7bb2700348e4521b25e077255ebb6ab68e351ab5aa91ca27e027"},
- {file = "contourpy-1.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084eaa568400cfaf7179b847ac871582199b1b44d5699198e9602ecbbb5f6104"},
- {file = "contourpy-1.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:911ff4fd53e26b019f898f32db0d4956c9d227d51338fb3b03ec72ff0084ee5f"},
- {file = "contourpy-1.1.0.tar.gz", hash = "sha256:e53046c3863828d21d531cc3b53786e6580eb1ba02477e8681009b6aa0870b21"},
-]
-
-[package.dependencies]
-numpy = ">=1.16"
-
-[package.extras]
-bokeh = ["bokeh", "selenium"]
-docs = ["furo", "sphinx-copybutton"]
-mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.2.0)", "types-Pillow"]
-test = ["Pillow", "contourpy[test-no-images]", "matplotlib"]
-test-no-images = ["pytest", "pytest-cov", "wurlitzer"]
-
-[[package]]
-name = "contourpy"
-version = "1.1.1"
+version = "1.2.0"
description = "Python library for calculating contours of 2D quadrilateral grids"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.9"
files = [
- {file = "contourpy-1.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:46e24f5412c948d81736509377e255f6040e94216bf1a9b5ea1eaa9d29f6ec1b"},
- {file = "contourpy-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e48694d6a9c5a26ee85b10130c77a011a4fedf50a7279fa0bdaf44bafb4299d"},
- {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a66045af6cf00e19d02191ab578a50cb93b2028c3eefed999793698e9ea768ae"},
- {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ebf42695f75ee1a952f98ce9775c873e4971732a87334b099dde90b6af6a916"},
- {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6aec19457617ef468ff091669cca01fa7ea557b12b59a7908b9474bb9674cf0"},
- {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:462c59914dc6d81e0b11f37e560b8a7c2dbab6aca4f38be31519d442d6cde1a1"},
- {file = "contourpy-1.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6d0a8efc258659edc5299f9ef32d8d81de8b53b45d67bf4bfa3067f31366764d"},
- {file = "contourpy-1.1.1-cp310-cp310-win32.whl", hash = "sha256:d6ab42f223e58b7dac1bb0af32194a7b9311065583cc75ff59dcf301afd8a431"},
- {file = "contourpy-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:549174b0713d49871c6dee90a4b499d3f12f5e5f69641cd23c50a4542e2ca1eb"},
- {file = "contourpy-1.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:407d864db716a067cc696d61fa1ef6637fedf03606e8417fe2aeed20a061e6b2"},
- {file = "contourpy-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe80c017973e6a4c367e037cb31601044dd55e6bfacd57370674867d15a899b"},
- {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e30aaf2b8a2bac57eb7e1650df1b3a4130e8d0c66fc2f861039d507a11760e1b"},
- {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3de23ca4f381c3770dee6d10ead6fff524d540c0f662e763ad1530bde5112532"},
- {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:566f0e41df06dfef2431defcfaa155f0acfa1ca4acbf8fd80895b1e7e2ada40e"},
- {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b04c2f0adaf255bf756cf08ebef1be132d3c7a06fe6f9877d55640c5e60c72c5"},
- {file = "contourpy-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d0c188ae66b772d9d61d43c6030500344c13e3f73a00d1dc241da896f379bb62"},
- {file = "contourpy-1.1.1-cp311-cp311-win32.whl", hash = "sha256:0683e1ae20dc038075d92e0e0148f09ffcefab120e57f6b4c9c0f477ec171f33"},
- {file = "contourpy-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:8636cd2fc5da0fb102a2504fa2c4bea3cbc149533b345d72cdf0e7a924decc45"},
- {file = "contourpy-1.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:560f1d68a33e89c62da5da4077ba98137a5e4d3a271b29f2f195d0fba2adcb6a"},
- {file = "contourpy-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:24216552104ae8f3b34120ef84825400b16eb6133af2e27a190fdc13529f023e"},
- {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56de98a2fb23025882a18b60c7f0ea2d2d70bbbcfcf878f9067234b1c4818442"},
- {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:07d6f11dfaf80a84c97f1a5ba50d129d9303c5b4206f776e94037332e298dda8"},
- {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1eaac5257a8f8a047248d60e8f9315c6cff58f7803971170d952555ef6344a7"},
- {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19557fa407e70f20bfaba7d55b4d97b14f9480856c4fb65812e8a05fe1c6f9bf"},
- {file = "contourpy-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:081f3c0880712e40effc5f4c3b08feca6d064cb8cfbb372ca548105b86fd6c3d"},
- {file = "contourpy-1.1.1-cp312-cp312-win32.whl", hash = "sha256:059c3d2a94b930f4dafe8105bcdc1b21de99b30b51b5bce74c753686de858cb6"},
- {file = "contourpy-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f44d78b61740e4e8c71db1cf1fd56d9050a4747681c59ec1094750a658ceb970"},
- {file = "contourpy-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:70e5a10f8093d228bb2b552beeb318b8928b8a94763ef03b858ef3612b29395d"},
- {file = "contourpy-1.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8394e652925a18ef0091115e3cc191fef350ab6dc3cc417f06da66bf98071ae9"},
- {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5bd5680f844c3ff0008523a71949a3ff5e4953eb7701b28760805bc9bcff217"},
- {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66544f853bfa85c0d07a68f6c648b2ec81dafd30f272565c37ab47a33b220684"},
- {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0c02b75acfea5cab07585d25069207e478d12309557f90a61b5a3b4f77f46ce"},
- {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41339b24471c58dc1499e56783fedc1afa4bb018bcd035cfb0ee2ad2a7501ef8"},
- {file = "contourpy-1.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f29fb0b3f1217dfe9362ec55440d0743fe868497359f2cf93293f4b2701b8251"},
- {file = "contourpy-1.1.1-cp38-cp38-win32.whl", hash = "sha256:f9dc7f933975367251c1b34da882c4f0e0b2e24bb35dc906d2f598a40b72bfc7"},
- {file = "contourpy-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:498e53573e8b94b1caeb9e62d7c2d053c263ebb6aa259c81050766beb50ff8d9"},
- {file = "contourpy-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ba42e3810999a0ddd0439e6e5dbf6d034055cdc72b7c5c839f37a7c274cb4eba"},
- {file = "contourpy-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c06e4c6e234fcc65435223c7b2a90f286b7f1b2733058bdf1345d218cc59e34"},
- {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca6fab080484e419528e98624fb5c4282148b847e3602dc8dbe0cb0669469887"},
- {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93df44ab351119d14cd1e6b52a5063d3336f0754b72736cc63db59307dabb718"},
- {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eafbef886566dc1047d7b3d4b14db0d5b7deb99638d8e1be4e23a7c7ac59ff0f"},
- {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efe0fab26d598e1ec07d72cf03eaeeba8e42b4ecf6b9ccb5a356fde60ff08b85"},
- {file = "contourpy-1.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f08e469821a5e4751c97fcd34bcb586bc243c39c2e39321822060ba902eac49e"},
- {file = "contourpy-1.1.1-cp39-cp39-win32.whl", hash = "sha256:bfc8a5e9238232a45ebc5cb3bfee71f1167064c8d382cadd6076f0d51cff1da0"},
- {file = "contourpy-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:c84fdf3da00c2827d634de4fcf17e3e067490c4aea82833625c4c8e6cdea0887"},
- {file = "contourpy-1.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:229a25f68046c5cf8067d6d6351c8b99e40da11b04d8416bf8d2b1d75922521e"},
- {file = "contourpy-1.1.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a10dab5ea1bd4401c9483450b5b0ba5416be799bbd50fc7a6cc5e2a15e03e8a3"},
- {file = "contourpy-1.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4f9147051cb8fdb29a51dc2482d792b3b23e50f8f57e3720ca2e3d438b7adf23"},
- {file = "contourpy-1.1.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a75cc163a5f4531a256f2c523bd80db509a49fc23721b36dd1ef2f60ff41c3cb"},
- {file = "contourpy-1.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b53d5769aa1f2d4ea407c65f2d1d08002952fac1d9e9d307aa2e1023554a163"},
- {file = "contourpy-1.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11b836b7dbfb74e049c302bbf74b4b8f6cb9d0b6ca1bf86cfa8ba144aedadd9c"},
- {file = "contourpy-1.1.1.tar.gz", hash = "sha256:96ba37c2e24b7212a77da85004c38e7c4d155d3e72a45eeaf22c1f03f607e8ab"},
+ {file = "contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8"},
+ {file = "contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4"},
+ {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f"},
+ {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e"},
+ {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9"},
+ {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa"},
+ {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9"},
+ {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab"},
+ {file = "contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488"},
+ {file = "contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41"},
+ {file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"},
+ {file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"},
+ {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"},
+ {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"},
+ {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"},
+ {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"},
+ {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"},
+ {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"},
+ {file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"},
+ {file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"},
+ {file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"},
+ {file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"},
+ {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"},
+ {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"},
+ {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"},
+ {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"},
+ {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"},
+ {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"},
+ {file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"},
+ {file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"},
+ {file = "contourpy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc"},
+ {file = "contourpy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9"},
+ {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8"},
+ {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e"},
+ {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8"},
+ {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5"},
+ {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e"},
+ {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808"},
+ {file = "contourpy-1.2.0-cp39-cp39-win32.whl", hash = "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4"},
+ {file = "contourpy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843"},
+ {file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"},
+ {file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"},
+ {file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"},
+ {file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"},
]
[package.dependencies]
-numpy = {version = ">=1.16,<2.0", markers = "python_version <= \"3.11\""}
+numpy = ">=1.20,<2.0"
[package.extras]
bokeh = ["bokeh", "selenium"]
docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"]
-mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.4.1)", "types-Pillow"]
+mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.6.1)", "types-Pillow"]
test = ["Pillow", "contourpy[test-no-images]", "matplotlib"]
-test-no-images = ["pytest", "pytest-cov", "wurlitzer"]
+test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"]
[[package]]
name = "cycler"
-version = "0.12.0"
+version = "0.12.1"
description = "Composable style cycles"
optional = false
python-versions = ">=3.8"
files = [
- {file = "cycler-0.12.0-py3-none-any.whl", hash = "sha256:7896994252d006771357777d0251f3e34d266f4fa5f2c572247a80ab01440947"},
- {file = "cycler-0.12.0.tar.gz", hash = "sha256:8cc3a7b4861f91b1095157f9916f748549a617046e67eb7619abed9b34d2c94a"},
+ {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"},
+ {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"},
]
[package.extras]
@@ -634,24 +586,35 @@ files = [
[[package]]
name = "distlib"
-version = "0.3.7"
+version = "0.3.8"
description = "Distribution utilities"
optional = false
python-versions = "*"
files = [
- {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"},
- {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"},
+ {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
+ {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
+]
+
+[[package]]
+name = "distro"
+version = "1.9.0"
+description = "Distro - an OS platform information API"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"},
+ {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"},
]
[[package]]
name = "exceptiongroup"
-version = "1.1.3"
+version = "1.2.0"
description = "Backport of PEP 654 (exception groups)"
optional = false
python-versions = ">=3.7"
files = [
- {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"},
- {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"},
+ {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"},
+ {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"},
]
[package.extras]
@@ -659,52 +622,52 @@ test = ["pytest (>=6)"]
[[package]]
name = "executing"
-version = "1.2.0"
+version = "2.0.1"
description = "Get the currently executing AST node of a frame, and other information"
optional = false
-python-versions = "*"
+python-versions = ">=3.5"
files = [
- {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"},
- {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"},
+ {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"},
+ {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"},
]
[package.extras]
-tests = ["asttokens", "littleutils", "pytest", "rich"]
+tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"]
[[package]]
name = "fastapi"
-version = "0.99.1"
+version = "0.109.2"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "fastapi-0.99.1-py3-none-any.whl", hash = "sha256:976df7bab51ac7beda9f68c4513b8c4490b5c1135c72aafd0a5ee4023ec5282e"},
- {file = "fastapi-0.99.1.tar.gz", hash = "sha256:ac78f717cd80d657bd183f94d33b9bda84aa376a46a9dab513586b8eef1dc6fc"},
+ {file = "fastapi-0.109.2-py3-none-any.whl", hash = "sha256:2c9bab24667293b501cad8dd388c05240c850b58ec5876ee3283c47d6e1e3a4d"},
+ {file = "fastapi-0.109.2.tar.gz", hash = "sha256:f3817eac96fe4f65a2ebb4baa000f394e55f5fccdaf7f75250804bc58f354f73"},
]
[package.dependencies]
-pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0"
-starlette = ">=0.27.0,<0.28.0"
-typing-extensions = ">=4.5.0"
+pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
+starlette = ">=0.36.3,<0.37.0"
+typing-extensions = ">=4.8.0"
[package.extras]
-all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
+all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
[[package]]
name = "filelock"
-version = "3.12.4"
+version = "3.13.1"
description = "A platform independent file lock."
optional = false
python-versions = ">=3.8"
files = [
- {file = "filelock-3.12.4-py3-none-any.whl", hash = "sha256:08c21d87ded6e2b9da6728c3dff51baf1dcecf973b768ef35bcbc3447edb9ad4"},
- {file = "filelock-3.12.4.tar.gz", hash = "sha256:2e6f249f1f3654291606e046b09f1fd5eac39b360664c27f5aad072012f8bcbd"},
+ {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"},
+ {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"},
]
[package.extras]
-docs = ["furo (>=2023.7.26)", "sphinx (>=7.1.2)", "sphinx-autodoc-typehints (>=1.24)"]
-testing = ["covdefaults (>=2.3)", "coverage (>=7.3)", "diff-cover (>=7.7)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "pytest-timeout (>=2.1)"]
-typing = ["typing-extensions (>=4.7.1)"]
+docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"]
+testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"]
+typing = ["typing-extensions (>=4.8)"]
[[package]]
name = "flake8"
@@ -724,51 +687,59 @@ pyflakes = ">=2.3.0,<2.4.0"
[[package]]
name = "fonttools"
-version = "4.42.1"
+version = "4.47.2"
description = "Tools to manipulate font files"
optional = false
python-versions = ">=3.8"
files = [
- {file = "fonttools-4.42.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ed1a13a27f59d1fc1920394a7f596792e9d546c9ca5a044419dca70c37815d7c"},
- {file = "fonttools-4.42.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c9b1ce7a45978b821a06d375b83763b27a3a5e8a2e4570b3065abad240a18760"},
- {file = "fonttools-4.42.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f720fa82a11c0f9042376fd509b5ed88dab7e3cd602eee63a1af08883b37342b"},
- {file = "fonttools-4.42.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db55cbaea02a20b49fefbd8e9d62bd481aaabe1f2301dabc575acc6b358874fa"},
- {file = "fonttools-4.42.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a35981d90feebeaef05e46e33e6b9e5b5e618504672ca9cd0ff96b171e4bfff"},
- {file = "fonttools-4.42.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:68a02bbe020dc22ee0540e040117535f06df9358106d3775e8817d826047f3fd"},
- {file = "fonttools-4.42.1-cp310-cp310-win32.whl", hash = "sha256:12a7c247d1b946829bfa2f331107a629ea77dc5391dfd34fdcd78efa61f354ca"},
- {file = "fonttools-4.42.1-cp310-cp310-win_amd64.whl", hash = "sha256:a398bdadb055f8de69f62b0fc70625f7cbdab436bbb31eef5816e28cab083ee8"},
- {file = "fonttools-4.42.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:689508b918332fb40ce117131633647731d098b1b10d092234aa959b4251add5"},
- {file = "fonttools-4.42.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e36344e48af3e3bde867a1ca54f97c308735dd8697005c2d24a86054a114a71"},
- {file = "fonttools-4.42.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19b7db825c8adee96fac0692e6e1ecd858cae9affb3b4812cdb9d934a898b29e"},
- {file = "fonttools-4.42.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:113337c2d29665839b7d90b39f99b3cac731f72a0eda9306165a305c7c31d341"},
- {file = "fonttools-4.42.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:37983b6bdab42c501202500a2be3a572f50d4efe3237e0686ee9d5f794d76b35"},
- {file = "fonttools-4.42.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6ed2662a3d9c832afa36405f8748c250be94ae5dfc5283d668308391f2102861"},
- {file = "fonttools-4.42.1-cp311-cp311-win32.whl", hash = "sha256:179737095eb98332a2744e8f12037b2977f22948cf23ff96656928923ddf560a"},
- {file = "fonttools-4.42.1-cp311-cp311-win_amd64.whl", hash = "sha256:f2b82f46917d8722e6b5eafeefb4fb585d23babd15d8246c664cd88a5bddd19c"},
- {file = "fonttools-4.42.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:62f481ac772fd68901573956231aea3e4b1ad87b9b1089a61613a91e2b50bb9b"},
- {file = "fonttools-4.42.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f2f806990160d1ce42d287aa419df3ffc42dfefe60d473695fb048355fe0c6a0"},
- {file = "fonttools-4.42.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db372213d39fa33af667c2aa586a0c1235e88e9c850f5dd5c8e1f17515861868"},
- {file = "fonttools-4.42.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d18fc642fd0ac29236ff88ecfccff229ec0386090a839dd3f1162e9a7944a40"},
- {file = "fonttools-4.42.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8708b98c278012ad267ee8a7433baeb809948855e81922878118464b274c909d"},
- {file = "fonttools-4.42.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c95b0724a6deea2c8c5d3222191783ced0a2f09bd6d33f93e563f6f1a4b3b3a4"},
- {file = "fonttools-4.42.1-cp38-cp38-win32.whl", hash = "sha256:4aa79366e442dbca6e2c8595645a3a605d9eeabdb7a094d745ed6106816bef5d"},
- {file = "fonttools-4.42.1-cp38-cp38-win_amd64.whl", hash = "sha256:acb47f6f8680de24c1ab65ebde39dd035768e2a9b571a07c7b8da95f6c8815fd"},
- {file = "fonttools-4.42.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb289b7a815638a7613d46bcf324c9106804725b2bb8ad913c12b6958ffc4ec"},
- {file = "fonttools-4.42.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:53eb5091ddc8b1199330bb7b4a8a2e7995ad5d43376cadce84523d8223ef3136"},
- {file = "fonttools-4.42.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46a0ec8adbc6ff13494eb0c9c2e643b6f009ce7320cf640de106fb614e4d4360"},
- {file = "fonttools-4.42.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cc7d685b8eeca7ae69dc6416833fbfea61660684b7089bca666067cb2937dcf"},
- {file = "fonttools-4.42.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:be24fcb80493b2c94eae21df70017351851652a37de514de553435b256b2f249"},
- {file = "fonttools-4.42.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:515607ec756d7865f23070682622c49d922901943697871fc292277cf1e71967"},
- {file = "fonttools-4.42.1-cp39-cp39-win32.whl", hash = "sha256:0eb79a2da5eb6457a6f8ab904838454accc7d4cccdaff1fd2bd3a0679ea33d64"},
- {file = "fonttools-4.42.1-cp39-cp39-win_amd64.whl", hash = "sha256:7286aed4ea271df9eab8d7a9b29e507094b51397812f7ce051ecd77915a6e26b"},
- {file = "fonttools-4.42.1-py3-none-any.whl", hash = "sha256:9398f244e28e0596e2ee6024f808b06060109e33ed38dcc9bded452fd9bbb853"},
- {file = "fonttools-4.42.1.tar.gz", hash = "sha256:c391cd5af88aacaf41dd7cfb96eeedfad297b5899a39e12f4c2c3706d0a3329d"},
+ {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3b629108351d25512d4ea1a8393a2dba325b7b7d7308116b605ea3f8e1be88df"},
+ {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c19044256c44fe299d9a73456aabee4b4d06c6b930287be93b533b4737d70aa1"},
+ {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8be28c036b9f186e8c7eaf8a11b42373e7e4949f9e9f370202b9da4c4c3f56c"},
+ {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f83a4daef6d2a202acb9bf572958f91cfde5b10c8ee7fb1d09a4c81e5d851fd8"},
+ {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5a5318ba5365d992666ac4fe35365f93004109d18858a3e18ae46f67907670"},
+ {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8f57ecd742545362a0f7186774b2d1c53423ed9ece67689c93a1055b236f638c"},
+ {file = "fonttools-4.47.2-cp310-cp310-win32.whl", hash = "sha256:a1c154bb85dc9a4cf145250c88d112d88eb414bad81d4cb524d06258dea1bdc0"},
+ {file = "fonttools-4.47.2-cp310-cp310-win_amd64.whl", hash = "sha256:3e2b95dce2ead58fb12524d0ca7d63a63459dd489e7e5838c3cd53557f8933e1"},
+ {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:29495d6d109cdbabe73cfb6f419ce67080c3ef9ea1e08d5750240fd4b0c4763b"},
+ {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0a1d313a415eaaba2b35d6cd33536560deeebd2ed758b9bfb89ab5d97dc5deac"},
+ {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f898cdd67f52f18049250a6474185ef6544c91f27a7bee70d87d77a8daf89c"},
+ {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3480eeb52770ff75140fe7d9a2ec33fb67b07efea0ab5129c7e0c6a639c40c70"},
+ {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0255dbc128fee75fb9be364806b940ed450dd6838672a150d501ee86523ac61e"},
+ {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f791446ff297fd5f1e2247c188de53c1bfb9dd7f0549eba55b73a3c2087a2703"},
+ {file = "fonttools-4.47.2-cp311-cp311-win32.whl", hash = "sha256:740947906590a878a4bde7dd748e85fefa4d470a268b964748403b3ab2aeed6c"},
+ {file = "fonttools-4.47.2-cp311-cp311-win_amd64.whl", hash = "sha256:63fbed184979f09a65aa9c88b395ca539c94287ba3a364517698462e13e457c9"},
+ {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4ec558c543609e71b2275c4894e93493f65d2f41c15fe1d089080c1d0bb4d635"},
+ {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e040f905d542362e07e72e03612a6270c33d38281fd573160e1003e43718d68d"},
+ {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dd58cc03016b281bd2c74c84cdaa6bd3ce54c5a7f47478b7657b930ac3ed8eb"},
+ {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32ab2e9702dff0dd4510c7bb958f265a8d3dd5c0e2547e7b5f7a3df4979abb07"},
+ {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a808f3c1d1df1f5bf39be869b6e0c263570cdafb5bdb2df66087733f566ea71"},
+ {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac71e2e201df041a2891067dc36256755b1229ae167edbdc419b16da78732c2f"},
+ {file = "fonttools-4.47.2-cp312-cp312-win32.whl", hash = "sha256:69731e8bea0578b3c28fdb43dbf95b9386e2d49a399e9a4ad736b8e479b08085"},
+ {file = "fonttools-4.47.2-cp312-cp312-win_amd64.whl", hash = "sha256:b3e1304e5f19ca861d86a72218ecce68f391646d85c851742d265787f55457a4"},
+ {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:254d9a6f7be00212bf0c3159e0a420eb19c63793b2c05e049eb337f3023c5ecc"},
+ {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eabae77a07c41ae0b35184894202305c3ad211a93b2eb53837c2a1143c8bc952"},
+ {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86a5ab2873ed2575d0fcdf1828143cfc6b977ac448e3dc616bb1e3d20efbafa"},
+ {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13819db8445a0cec8c3ff5f243af6418ab19175072a9a92f6cc8ca7d1452754b"},
+ {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4e743935139aa485fe3253fc33fe467eab6ea42583fa681223ea3f1a93dd01e6"},
+ {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d49ce3ea7b7173faebc5664872243b40cf88814ca3eb135c4a3cdff66af71946"},
+ {file = "fonttools-4.47.2-cp38-cp38-win32.whl", hash = "sha256:94208ea750e3f96e267f394d5588579bb64cc628e321dbb1d4243ffbc291b18b"},
+ {file = "fonttools-4.47.2-cp38-cp38-win_amd64.whl", hash = "sha256:0f750037e02beb8b3569fbff701a572e62a685d2a0e840d75816592280e5feae"},
+ {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3d71606c9321f6701642bd4746f99b6089e53d7e9817fc6b964e90d9c5f0ecc6"},
+ {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86e0427864c6c91cf77f16d1fb9bf1bbf7453e824589e8fb8461b6ee1144f506"},
+ {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a00bd0e68e88987dcc047ea31c26d40a3c61185153b03457956a87e39d43c37"},
+ {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5d77479fb885ef38a16a253a2f4096bc3d14e63a56d6246bfdb56365a12b20c"},
+ {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5465df494f20a7d01712b072ae3ee9ad2887004701b95cb2cc6dcb9c2c97a899"},
+ {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4c811d3c73b6abac275babb8aa439206288f56fdb2c6f8835e3d7b70de8937a7"},
+ {file = "fonttools-4.47.2-cp39-cp39-win32.whl", hash = "sha256:5b60e3afa9635e3dfd3ace2757039593e3bd3cf128be0ddb7a1ff4ac45fa5a50"},
+ {file = "fonttools-4.47.2-cp39-cp39-win_amd64.whl", hash = "sha256:7ee48bd9d6b7e8f66866c9090807e3a4a56cf43ffad48962725a190e0dd774c8"},
+ {file = "fonttools-4.47.2-py3-none-any.whl", hash = "sha256:7eb7ad665258fba68fd22228a09f347469d95a97fb88198e133595947a20a184"},
+ {file = "fonttools-4.47.2.tar.gz", hash = "sha256:7df26dd3650e98ca45f1e29883c96a0b9f5bb6af8d632a6a108bc744fa0bd9b3"},
]
[package.extras]
-all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.0.0)", "xattr", "zopfli (>=0.1.4)"]
+all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"]
graphite = ["lz4 (>=1.7.4.2)"]
-interpolatable = ["munkres", "scipy"]
+interpolatable = ["munkres", "pycairo", "scipy"]
lxml = ["lxml (>=4.0,<5)"]
pathops = ["skia-pathops (>=0.5.0)"]
plot = ["matplotlib"]
@@ -776,88 +747,104 @@ repacker = ["uharfbuzz (>=0.23.0)"]
symfont = ["sympy"]
type1 = ["xattr"]
ufo = ["fs (>=2.2.0,<3)"]
-unicode = ["unicodedata2 (>=15.0.0)"]
+unicode = ["unicodedata2 (>=15.1.0)"]
woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"]
[[package]]
name = "frozenlist"
-version = "1.4.0"
+version = "1.4.1"
description = "A list-like structure which implements collections.abc.MutableSequence"
optional = false
python-versions = ">=3.8"
files = [
- {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"},
- {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"},
- {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"},
- {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"},
- {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"},
- {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"},
- {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"},
- {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"},
- {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"},
- {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"},
- {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"},
- {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"},
- {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"},
- {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"},
- {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"},
- {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"},
- {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"},
- {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"},
- {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"},
- {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"},
- {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"},
- {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"},
- {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"},
- {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"},
- {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"},
- {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"},
- {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"},
- {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"},
- {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"},
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"},
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"},
+ {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"},
+ {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"},
+ {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"},
+ {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"},
+ {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"},
+ {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"},
+ {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"},
+ {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"},
+ {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"},
+ {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"},
+ {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"},
+ {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"},
+ {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"},
+ {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"},
+ {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"},
+ {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"},
+ {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"},
+ {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"},
+ {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"},
+ {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"},
+ {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"},
+ {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"},
+ {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"},
+ {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"},
+ {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"},
+ {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"},
+ {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"},
]
[[package]]
name = "gitdb"
-version = "4.0.10"
+version = "4.0.11"
description = "Git Object Database"
optional = false
python-versions = ">=3.7"
files = [
- {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"},
- {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"},
+ {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"},
+ {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"},
]
[package.dependencies]
@@ -865,30 +852,30 @@ smmap = ">=3.0.1,<6"
[[package]]
name = "gitpython"
-version = "3.1.37"
+version = "3.1.41"
description = "GitPython is a Python library used to interact with Git repositories"
optional = false
python-versions = ">=3.7"
files = [
- {file = "GitPython-3.1.37-py3-none-any.whl", hash = "sha256:5f4c4187de49616d710a77e98ddf17b4782060a1788df441846bddefbb89ab33"},
- {file = "GitPython-3.1.37.tar.gz", hash = "sha256:f9b9ddc0761c125d5780eab2d64be4873fc6817c2899cbcb34b02344bdc7bc54"},
+ {file = "GitPython-3.1.41-py3-none-any.whl", hash = "sha256:c36b6634d069b3f719610175020a9aed919421c87552185b085e04fbbdb10b7c"},
+ {file = "GitPython-3.1.41.tar.gz", hash = "sha256:ed66e624884f76df22c8e16066d567aaa5a37d5b5fa19db2c6df6f7156db9048"},
]
[package.dependencies]
gitdb = ">=4.0.1,<5"
[package.extras]
-test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-sugar"]
+test = ["black", "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", "sumtypes"]
[[package]]
name = "google-auth"
-version = "2.23.2"
+version = "2.26.2"
description = "Google Authentication Library"
optional = false
python-versions = ">=3.7"
files = [
- {file = "google-auth-2.23.2.tar.gz", hash = "sha256:5a9af4be520ba33651471a0264eead312521566f44631cbb621164bc30c8fd40"},
- {file = "google_auth-2.23.2-py2.py3-none-any.whl", hash = "sha256:c2e253347579d483004f17c3bd0bf92e611ef6c7ba24d41c5c59f2e7aeeaf088"},
+ {file = "google-auth-2.26.2.tar.gz", hash = "sha256:97327dbbf58cccb58fc5a1712bba403ae76668e64814eb30f7316f7e27126b81"},
+ {file = "google_auth-2.26.2-py2.py3-none-any.whl", hash = "sha256:3f445c8ce9b61ed6459aad86d8ccdba4a9afed841b2d1451a11ef4db08957424"},
]
[package.dependencies]
@@ -905,13 +892,13 @@ requests = ["requests (>=2.20.0,<3.0.0.dev0)"]
[[package]]
name = "google-auth-oauthlib"
-version = "1.1.0"
+version = "1.2.0"
description = "Google Authentication Library"
optional = false
python-versions = ">=3.6"
files = [
- {file = "google-auth-oauthlib-1.1.0.tar.gz", hash = "sha256:83ea8c3b0881e453790baff4448e8a6112ac8778d1de9da0b68010b843937afb"},
- {file = "google_auth_oauthlib-1.1.0-py2.py3-none-any.whl", hash = "sha256:089c6e587d36f4803ac7e0720c045c6a8b1fd1790088b8424975b90d0ee61c12"},
+ {file = "google-auth-oauthlib-1.2.0.tar.gz", hash = "sha256:292d2d3783349f2b0734a0a0207b1e1e322ac193c2c09d8f7c613fb7cc501ea8"},
+ {file = "google_auth_oauthlib-1.2.0-py2.py3-none-any.whl", hash = "sha256:297c1ce4cb13a99b5834c74a1fe03252e1e499716718b190f56bcb9c4abc4faf"},
]
[package.dependencies]
@@ -923,13 +910,13 @@ tool = ["click (>=6.0.0)"]
[[package]]
name = "gspread"
-version = "5.11.2"
+version = "5.12.4"
description = "Google Spreadsheets Python API"
optional = false
python-versions = ">=3.7"
files = [
- {file = "gspread-5.11.2-py3-none-any.whl", hash = "sha256:525a9d3ef712d5747867d32b61f5d7aa035ead0835b56cd1ae2a6d310eaef077"},
- {file = "gspread-5.11.2.tar.gz", hash = "sha256:fdc477cbda48bc9ea77eb8a4bf737985bfdba44f04677e4d791eb70bcbae2b95"},
+ {file = "gspread-5.12.4-py3-none-any.whl", hash = "sha256:1e453d87e0fde23bc5546e33eb684cf8b8c26540615f2f1ae004a9084a29051d"},
+ {file = "gspread-5.12.4.tar.gz", hash = "sha256:3fcef90183f15d3c9233b4caa021a83682f2b2ee678340c42d7ca7d8be98c6d1"},
]
[package.dependencies]
@@ -948,21 +935,6 @@ files = [
]
[[package]]
-name = "helicone"
-version = "1.0.9"
-description = "A Python wrapper for the OpenAI API that logs all requests to Helicone."
-optional = false
-python-versions = ">=3.8.1"
-files = [
- {file = "helicone-1.0.9-py3-none-any.whl", hash = "sha256:440b4ff1ba65239f33b70aab3f53b7c69d7c6883a3552a76f8b13818dbef915c"},
- {file = "helicone-1.0.9.tar.gz", hash = "sha256:96122e95d40917a722f79ea71ff5099e248951623b5d0068275b08760e351b0b"},
-]
-
-[package.dependencies]
-lockfile = ">=0.12.2,<0.13.0"
-openai = ">=0.27.0,<0.28.0"
-
-[[package]]
name = "httpcore"
version = "0.17.3"
description = "A minimal low-level HTTP client."
@@ -1022,13 +994,13 @@ socks = ["socksio (==1.*)"]
[[package]]
name = "identify"
-version = "2.5.29"
+version = "2.5.33"
description = "File identification library for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "identify-2.5.29-py2.py3-none-any.whl", hash = "sha256:24437fbf6f4d3fe6efd0eb9d67e24dd9106db99af5ceb27996a5f7895f24bf1b"},
- {file = "identify-2.5.29.tar.gz", hash = "sha256:d43d52b86b15918c137e3a74fff5224f60385cd0e9c38e99d07c257f02f151a5"},
+ {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"},
+ {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"},
]
[package.extras]
@@ -1036,13 +1008,13 @@ license = ["ukkonen"]
[[package]]
name = "idna"
-version = "3.4"
+version = "3.6"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.5"
files = [
- {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
- {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
+ {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
+ {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
]
[[package]]
@@ -1058,69 +1030,63 @@ files = [
[[package]]
name = "ipython"
-version = "8.15.0"
+version = "8.20.0"
description = "IPython: Productive Interactive Computing"
optional = false
-python-versions = ">=3.9"
+python-versions = ">=3.10"
files = [
- {file = "ipython-8.15.0-py3-none-any.whl", hash = "sha256:45a2c3a529296870a97b7de34eda4a31bee16bc7bf954e07d39abe49caf8f887"},
- {file = "ipython-8.15.0.tar.gz", hash = "sha256:2baeb5be6949eeebf532150f81746f8333e2ccce02de1c7eedde3f23ed5e9f1e"},
+ {file = "ipython-8.20.0-py3-none-any.whl", hash = "sha256:bc9716aad6f29f36c449e30821c9dd0c1c1a7b59ddcc26931685b87b4c569619"},
+ {file = "ipython-8.20.0.tar.gz", hash = "sha256:2f21bd3fc1d51550c89ee3944ae04bbc7bc79e129ea0937da6e6c68bfdbf117a"},
]
[package.dependencies]
-appnope = {version = "*", markers = "sys_platform == \"darwin\""}
-backcall = "*"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
decorator = "*"
exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
jedi = ">=0.16"
matplotlib-inline = "*"
pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""}
-pickleshare = "*"
-prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0"
+prompt-toolkit = ">=3.0.41,<3.1.0"
pygments = ">=2.4.0"
stack-data = "*"
traitlets = ">=5"
[package.extras]
-all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
+all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.23)", "pandas", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
black = ["black"]
-doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"]
+doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"]
kernel = ["ipykernel"]
nbconvert = ["nbconvert"]
nbformat = ["nbformat"]
notebook = ["ipywidgets", "notebook"]
parallel = ["ipyparallel"]
qtconsole = ["qtconsole"]
-test = ["pytest (<7.1)", "pytest-asyncio", "testpath"]
-test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"]
+test = ["pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"]
+test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath", "trio"]
[[package]]
name = "isort"
-version = "5.12.0"
+version = "5.13.2"
description = "A Python utility / library to sort Python imports."
optional = false
python-versions = ">=3.8.0"
files = [
- {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
- {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
+ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"},
+ {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"},
]
[package.extras]
-colors = ["colorama (>=0.4.3)"]
-pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
-plugins = ["setuptools"]
-requirements-deprecated-finder = ["pip-api", "pipreqs"]
+colors = ["colorama (>=0.4.6)"]
[[package]]
name = "jedi"
-version = "0.19.0"
+version = "0.19.1"
description = "An autocompletion tool for Python that can be used for text editors."
optional = false
python-versions = ">=3.6"
files = [
- {file = "jedi-0.19.0-py2.py3-none-any.whl", hash = "sha256:cb8ce23fbccff0025e9386b5cf85e892f94c9b822378f8da49970471335ac64e"},
- {file = "jedi-0.19.0.tar.gz", hash = "sha256:bcf9894f1753969cbac8022a8c2eaee06bfa3724e4192470aaffe7eb6272b0c4"},
+ {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"},
+ {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"},
]
[package.dependencies]
@@ -1129,17 +1095,17 @@ parso = ">=0.8.3,<0.9.0"
[package.extras]
docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"]
qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
-testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
+testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
[[package]]
name = "jinja2"
-version = "3.1.2"
+version = "3.1.3"
description = "A very fast and expressive template engine."
optional = false
python-versions = ">=3.7"
files = [
- {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
- {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+ {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"},
+ {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"},
]
[package.dependencies]
@@ -1278,17 +1244,6 @@ files = [
]
[[package]]
-name = "lockfile"
-version = "0.12.2"
-description = "Platform-independent file locking module"
-optional = false
-python-versions = "*"
-files = [
- {file = "lockfile-0.12.2-py2.py3-none-any.whl", hash = "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"},
- {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"},
-]
-
-[[package]]
name = "markupsafe"
version = "2.1.3"
description = "Safely add untrusted strings to HTML/XML markup."
@@ -1359,52 +1314,51 @@ files = [
[[package]]
name = "matplotlib"
-version = "3.8.0"
+version = "3.8.2"
description = "Python plotting package"
optional = false
python-versions = ">=3.9"
files = [
- {file = "matplotlib-3.8.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c4940bad88a932ddc69734274f6fb047207e008389489f2b6f77d9ca485f0e7a"},
- {file = "matplotlib-3.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a33bd3045c7452ca1fa65676d88ba940867880e13e2546abb143035fa9072a9d"},
- {file = "matplotlib-3.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea6886e93401c22e534bbfd39201ce8931b75502895cfb115cbdbbe2d31f287"},
- {file = "matplotlib-3.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d670b9348e712ec176de225d425f150dc8e37b13010d85233c539b547da0be39"},
- {file = "matplotlib-3.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7b37b74f00c4cb6af908cb9a00779d97d294e89fd2145ad43f0cdc23f635760c"},
- {file = "matplotlib-3.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:0e723f5b96f3cd4aad99103dc93e9e3cdc4f18afdcc76951f4857b46f8e39d2d"},
- {file = "matplotlib-3.8.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5dc945a9cb2deb7d197ba23eb4c210e591d52d77bf0ba27c35fc82dec9fa78d4"},
- {file = "matplotlib-3.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8b5a1bf27d078453aa7b5b27f52580e16360d02df6d3dc9504f3d2ce11f6309"},
- {file = "matplotlib-3.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f25ffb6ad972cdffa7df8e5be4b1e3cadd2f8d43fc72085feb1518006178394"},
- {file = "matplotlib-3.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee482731c8c17d86d9ddb5194d38621f9b0f0d53c99006275a12523ab021732"},
- {file = "matplotlib-3.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:36eafe2128772195b373e1242df28d1b7ec6c04c15b090b8d9e335d55a323900"},
- {file = "matplotlib-3.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:061ee58facb3580cd2d046a6d227fb77e9295599c5ec6ad069f06b5821ad1cfc"},
- {file = "matplotlib-3.8.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3cc3776836d0f4f22654a7f2d2ec2004618d5cf86b7185318381f73b80fd8a2d"},
- {file = "matplotlib-3.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6c49a2bd6981264bddcb8c317b6bd25febcece9e2ebfcbc34e7f4c0c867c09dc"},
- {file = "matplotlib-3.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23ed11654fc83cd6cfdf6170b453e437674a050a452133a064d47f2f1371f8d3"},
- {file = "matplotlib-3.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dae97fdd6996b3a25da8ee43e3fc734fff502f396801063c6b76c20b56683196"},
- {file = "matplotlib-3.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:87df75f528020a6299f76a1d986c0ed4406e3b2bd44bc5e306e46bca7d45e53e"},
- {file = "matplotlib-3.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:90d74a95fe055f73a6cd737beecc1b81c26f2893b7a3751d52b53ff06ca53f36"},
- {file = "matplotlib-3.8.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c3499c312f5def8f362a2bf761d04fa2d452b333f3a9a3f58805273719bf20d9"},
- {file = "matplotlib-3.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31e793c8bd4ea268cc5d3a695c27b30650ec35238626961d73085d5e94b6ab68"},
- {file = "matplotlib-3.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d5ee602ef517a89d1f2c508ca189cfc395dd0b4a08284fb1b97a78eec354644"},
- {file = "matplotlib-3.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5de39dc61ca35342cf409e031f70f18219f2c48380d3886c1cf5ad9f17898e06"},
- {file = "matplotlib-3.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:dd386c80a98b5f51571b9484bf6c6976de383cd2a8cd972b6a9562d85c6d2087"},
- {file = "matplotlib-3.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:f691b4ef47c7384d0936b2e8ebdeb5d526c81d004ad9403dfb9d4c76b9979a93"},
- {file = "matplotlib-3.8.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0b11f354aae62a2aa53ec5bb09946f5f06fc41793e351a04ff60223ea9162955"},
- {file = "matplotlib-3.8.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f54b9fb87ca5acbcdd0f286021bedc162e1425fa5555ebf3b3dfc167b955ad9"},
- {file = "matplotlib-3.8.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:60a6e04dfd77c0d3bcfee61c3cd335fff1b917c2f303b32524cd1235e194ef99"},
- {file = "matplotlib-3.8.0.tar.gz", hash = "sha256:df8505e1c19d5c2c26aff3497a7cbd3ccfc2e97043d1e4db3e76afa399164b69"},
+ {file = "matplotlib-3.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7"},
+ {file = "matplotlib-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367"},
+ {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18"},
+ {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31"},
+ {file = "matplotlib-3.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a"},
+ {file = "matplotlib-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a"},
+ {file = "matplotlib-3.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63"},
+ {file = "matplotlib-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8"},
+ {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6"},
+ {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788"},
+ {file = "matplotlib-3.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0"},
+ {file = "matplotlib-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717"},
+ {file = "matplotlib-3.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627"},
+ {file = "matplotlib-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4"},
+ {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d"},
+ {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331"},
+ {file = "matplotlib-3.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213"},
+ {file = "matplotlib-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630"},
+ {file = "matplotlib-3.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:deaed9ad4da0b1aea77fe0aa0cebb9ef611c70b3177be936a95e5d01fa05094f"},
+ {file = "matplotlib-3.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:172f4d0fbac3383d39164c6caafd3255ce6fa58f08fc392513a0b1d3b89c4f89"},
+ {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7d36c2209d9136cd8e02fab1c0ddc185ce79bc914c45054a9f514e44c787917"},
+ {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5864bdd7da445e4e5e011b199bb67168cdad10b501750367c496420f2ad00843"},
+ {file = "matplotlib-3.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ef8345b48e95cee45ff25192ed1f4857273117917a4dcd48e3905619bcd9c9b8"},
+ {file = "matplotlib-3.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:7c48d9e221b637c017232e3760ed30b4e8d5dfd081daf327e829bf2a72c731b4"},
+ {file = "matplotlib-3.8.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa11b3c6928a1e496c1a79917d51d4cd5d04f8a2e75f21df4949eeefdf697f4b"},
+ {file = "matplotlib-3.8.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1095fecf99eeb7384dabad4bf44b965f929a5f6079654b681193edf7169ec20"},
+ {file = "matplotlib-3.8.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:bddfb1db89bfaa855912261c805bd0e10218923cc262b9159a49c29a7a1c1afa"},
+ {file = "matplotlib-3.8.2.tar.gz", hash = "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1"},
]
[package.dependencies]
contourpy = ">=1.0.1"
cycler = ">=0.10"
fonttools = ">=4.22.0"
-kiwisolver = ">=1.0.1"
+kiwisolver = ">=1.3.1"
numpy = ">=1.21,<2"
packaging = ">=20.0"
-pillow = ">=6.2.0"
+pillow = ">=8"
pyparsing = ">=2.3.1"
python-dateutil = ">=2.7"
-setuptools_scm = ">=7"
[[package]]
name = "matplotlib-inline"
@@ -1527,21 +1481,21 @@ files = [
[[package]]
name = "networkx"
-version = "3.1"
+version = "3.2.1"
description = "Python package for creating and manipulating graphs and networks"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.9"
files = [
- {file = "networkx-3.1-py3-none-any.whl", hash = "sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36"},
- {file = "networkx-3.1.tar.gz", hash = "sha256:de346335408f84de0eada6ff9fafafff9bcda11f0a0dfaa931133debb146ab61"},
+ {file = "networkx-3.2.1-py3-none-any.whl", hash = "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2"},
+ {file = "networkx-3.2.1.tar.gz", hash = "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6"},
]
[package.extras]
-default = ["matplotlib (>=3.4)", "numpy (>=1.20)", "pandas (>=1.3)", "scipy (>=1.8)"]
-developer = ["mypy (>=1.1)", "pre-commit (>=3.2)"]
-doc = ["nb2plots (>=0.6)", "numpydoc (>=1.5)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.13)", "sphinx (>=6.1)", "sphinx-gallery (>=0.12)", "texext (>=0.6.7)"]
-extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.10)", "sympy (>=1.10)"]
-test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"]
+default = ["matplotlib (>=3.5)", "numpy (>=1.22)", "pandas (>=1.4)", "scipy (>=1.9,!=1.11.0,!=1.11.1)"]
+developer = ["changelist (==0.4)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"]
+doc = ["nb2plots (>=0.7)", "nbconvert (<7.9)", "numpydoc (>=1.6)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.14)", "sphinx (>=7)", "sphinx-gallery (>=0.14)", "texext (>=0.6.7)"]
+extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.11)", "sympy (>=1.10)"]
+test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"]
[[package]]
name = "nodeenv"
@@ -1559,77 +1513,47 @@ setuptools = "*"
[[package]]
name = "numpy"
-version = "1.25.2"
+version = "1.26.3"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.9"
files = [
- {file = "numpy-1.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db3ccc4e37a6873045580d413fe79b68e47a681af8db2e046f1dacfa11f86eb3"},
- {file = "numpy-1.25.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90319e4f002795ccfc9050110bbbaa16c944b1c37c0baeea43c5fb881693ae1f"},
- {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4a913e29b418d096e696ddd422d8a5d13ffba4ea91f9f60440a3b759b0187"},
- {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357"},
- {file = "numpy-1.25.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bec1e7213c7cb00d67093247f8c4db156fd03075f49876957dca4711306d39c9"},
- {file = "numpy-1.25.2-cp310-cp310-win32.whl", hash = "sha256:7dc869c0c75988e1c693d0e2d5b26034644399dd929bc049db55395b1379e044"},
- {file = "numpy-1.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:834b386f2b8210dca38c71a6e0f4fd6922f7d3fcff935dbe3a570945acb1b545"},
- {file = "numpy-1.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418"},
- {file = "numpy-1.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f"},
- {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2"},
- {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf"},
- {file = "numpy-1.25.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364"},
- {file = "numpy-1.25.2-cp311-cp311-win32.whl", hash = "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d"},
- {file = "numpy-1.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4"},
- {file = "numpy-1.25.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b79e513d7aac42ae918db3ad1341a015488530d0bb2a6abcbdd10a3a829ccfd3"},
- {file = "numpy-1.25.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb942bfb6f84df5ce05dbf4b46673ffed0d3da59f13635ea9b926af3deb76926"},
- {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e0746410e73384e70d286f93abf2520035250aad8c5714240b0492a7302fdca"},
- {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7806500e4f5bdd04095e849265e55de20d8cc4b661b038957354327f6d9b295"},
- {file = "numpy-1.25.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8b77775f4b7df768967a7c8b3567e309f617dd5e99aeb886fa14dc1a0791141f"},
- {file = "numpy-1.25.2-cp39-cp39-win32.whl", hash = "sha256:2792d23d62ec51e50ce4d4b7d73de8f67a2fd3ea710dcbc8563a51a03fb07b01"},
- {file = "numpy-1.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:76b4115d42a7dfc5d485d358728cdd8719be33cc5ec6ec08632a5d6fca2ed380"},
- {file = "numpy-1.25.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a1329e26f46230bf77b02cc19e900db9b52f398d6722ca853349a782d4cff55"},
- {file = "numpy-1.25.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3abc71e8b6edba80a01a52e66d83c5d14433cbcd26a40c329ec7ed09f37901"},
- {file = "numpy-1.25.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b9735c27cea5d995496f46a8b1cd7b408b3f34b6d50459d9ac8fe3a20cc17bf"},
- {file = "numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"},
-]
-
-[[package]]
-name = "numpy"
-version = "1.26.0"
-description = "Fundamental package for array computing in Python"
-optional = false
-python-versions = "<3.13,>=3.9"
-files = [
- {file = "numpy-1.26.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8db2f125746e44dce707dd44d4f4efeea8d7e2b43aace3f8d1f235cfa2733dd"},
- {file = "numpy-1.26.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0621f7daf973d34d18b4e4bafb210bbaf1ef5e0100b5fa750bd9cde84c7ac292"},
- {file = "numpy-1.26.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51be5f8c349fdd1a5568e72713a21f518e7d6707bcf8503b528b88d33b57dc68"},
- {file = "numpy-1.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:767254ad364991ccfc4d81b8152912e53e103ec192d1bb4ea6b1f5a7117040be"},
- {file = "numpy-1.26.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:436c8e9a4bdeeee84e3e59614d38c3dbd3235838a877af8c211cfcac8a80b8d3"},
- {file = "numpy-1.26.0-cp310-cp310-win32.whl", hash = "sha256:c2e698cb0c6dda9372ea98a0344245ee65bdc1c9dd939cceed6bb91256837896"},
- {file = "numpy-1.26.0-cp310-cp310-win_amd64.whl", hash = "sha256:09aaee96c2cbdea95de76ecb8a586cb687d281c881f5f17bfc0fb7f5890f6b91"},
- {file = "numpy-1.26.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:637c58b468a69869258b8ae26f4a4c6ff8abffd4a8334c830ffb63e0feefe99a"},
- {file = "numpy-1.26.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:306545e234503a24fe9ae95ebf84d25cba1fdc27db971aa2d9f1ab6bba19a9dd"},
- {file = "numpy-1.26.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6adc33561bd1d46f81131d5352348350fc23df4d742bb246cdfca606ea1208"},
- {file = "numpy-1.26.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e062aa24638bb5018b7841977c360d2f5917268d125c833a686b7cbabbec496c"},
- {file = "numpy-1.26.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:546b7dd7e22f3c6861463bebb000646fa730e55df5ee4a0224408b5694cc6148"},
- {file = "numpy-1.26.0-cp311-cp311-win32.whl", hash = "sha256:c0b45c8b65b79337dee5134d038346d30e109e9e2e9d43464a2970e5c0e93229"},
- {file = "numpy-1.26.0-cp311-cp311-win_amd64.whl", hash = "sha256:eae430ecf5794cb7ae7fa3808740b015aa80747e5266153128ef055975a72b99"},
- {file = "numpy-1.26.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:166b36197e9debc4e384e9c652ba60c0bacc216d0fc89e78f973a9760b503388"},
- {file = "numpy-1.26.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f042f66d0b4ae6d48e70e28d487376204d3cbf43b84c03bac57e28dac6151581"},
- {file = "numpy-1.26.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5e18e5b14a7560d8acf1c596688f4dfd19b4f2945b245a71e5af4ddb7422feb"},
- {file = "numpy-1.26.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f6bad22a791226d0a5c7c27a80a20e11cfe09ad5ef9084d4d3fc4a299cca505"},
- {file = "numpy-1.26.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4acc65dd65da28060e206c8f27a573455ed724e6179941edb19f97e58161bb69"},
- {file = "numpy-1.26.0-cp312-cp312-win32.whl", hash = "sha256:bb0d9a1aaf5f1cb7967320e80690a1d7ff69f1d47ebc5a9bea013e3a21faec95"},
- {file = "numpy-1.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:ee84ca3c58fe48b8ddafdeb1db87388dce2c3c3f701bf447b05e4cfcc3679112"},
- {file = "numpy-1.26.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4a873a8180479bc829313e8d9798d5234dfacfc2e8a7ac188418189bb8eafbd2"},
- {file = "numpy-1.26.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:914b28d3215e0c721dc75db3ad6d62f51f630cb0c277e6b3bcb39519bed10bd8"},
- {file = "numpy-1.26.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c78a22e95182fb2e7874712433eaa610478a3caf86f28c621708d35fa4fd6e7f"},
- {file = "numpy-1.26.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86f737708b366c36b76e953c46ba5827d8c27b7a8c9d0f471810728e5a2fe57c"},
- {file = "numpy-1.26.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b44e6a09afc12952a7d2a58ca0a2429ee0d49a4f89d83a0a11052da696440e49"},
- {file = "numpy-1.26.0-cp39-cp39-win32.whl", hash = "sha256:5671338034b820c8d58c81ad1dafc0ed5a00771a82fccc71d6438df00302094b"},
- {file = "numpy-1.26.0-cp39-cp39-win_amd64.whl", hash = "sha256:020cdbee66ed46b671429c7265cf00d8ac91c046901c55684954c3958525dab2"},
- {file = "numpy-1.26.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0792824ce2f7ea0c82ed2e4fecc29bb86bee0567a080dacaf2e0a01fe7654369"},
- {file = "numpy-1.26.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d484292eaeb3e84a51432a94f53578689ffdea3f90e10c8b203a99be5af57d8"},
- {file = "numpy-1.26.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:186ba67fad3c60dbe8a3abff3b67a91351100f2661c8e2a80364ae6279720299"},
- {file = "numpy-1.26.0.tar.gz", hash = "sha256:f93fc78fe8bf15afe2b8d6b6499f1c73953169fad1e9a8dd086cdff3190e7fdf"},
+ {file = "numpy-1.26.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:806dd64230dbbfaca8a27faa64e2f414bf1c6622ab78cc4264f7f5f028fee3bf"},
+ {file = "numpy-1.26.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f98011ba4ab17f46f80f7f8f1c291ee7d855fcef0a5a98db80767a468c85cd"},
+ {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d45b3ec2faed4baca41c76617fcdcfa4f684ff7a151ce6fc78ad3b6e85af0a6"},
+ {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdd2b45bf079d9ad90377048e2747a0c82351989a2165821f0c96831b4a2a54b"},
+ {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:211ddd1e94817ed2d175b60b6374120244a4dd2287f4ece45d49228b4d529178"},
+ {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1240f767f69d7c4c8a29adde2310b871153df9b26b5cb2b54a561ac85146485"},
+ {file = "numpy-1.26.3-cp310-cp310-win32.whl", hash = "sha256:21a9484e75ad018974a2fdaa216524d64ed4212e418e0a551a2d83403b0531d3"},
+ {file = "numpy-1.26.3-cp310-cp310-win_amd64.whl", hash = "sha256:9e1591f6ae98bcfac2a4bbf9221c0b92ab49762228f38287f6eeb5f3f55905ce"},
+ {file = "numpy-1.26.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b831295e5472954104ecb46cd98c08b98b49c69fdb7040483aff799a755a7374"},
+ {file = "numpy-1.26.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9e87562b91f68dd8b1c39149d0323b42e0082db7ddb8e934ab4c292094d575d6"},
+ {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c66d6fec467e8c0f975818c1796d25c53521124b7cfb760114be0abad53a0a2"},
+ {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f25e2811a9c932e43943a2615e65fc487a0b6b49218899e62e426e7f0a57eeda"},
+ {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af36e0aa45e25c9f57bf684b1175e59ea05d9a7d3e8e87b7ae1a1da246f2767e"},
+ {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:51c7f1b344f302067b02e0f5b5d2daa9ed4a721cf49f070280ac202738ea7f00"},
+ {file = "numpy-1.26.3-cp311-cp311-win32.whl", hash = "sha256:7ca4f24341df071877849eb2034948459ce3a07915c2734f1abb4018d9c49d7b"},
+ {file = "numpy-1.26.3-cp311-cp311-win_amd64.whl", hash = "sha256:39763aee6dfdd4878032361b30b2b12593fb445ddb66bbac802e2113eb8a6ac4"},
+ {file = "numpy-1.26.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a7081fd19a6d573e1a05e600c82a1c421011db7935ed0d5c483e9dd96b99cf13"},
+ {file = "numpy-1.26.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12c70ac274b32bc00c7f61b515126c9205323703abb99cd41836e8125ea0043e"},
+ {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f784e13e598e9594750b2ef6729bcd5a47f6cfe4a12cca13def35e06d8163e3"},
+ {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f24750ef94d56ce6e33e4019a8a4d68cfdb1ef661a52cdaee628a56d2437419"},
+ {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:77810ef29e0fb1d289d225cabb9ee6cf4d11978a00bb99f7f8ec2132a84e0166"},
+ {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8ed07a90f5450d99dad60d3799f9c03c6566709bd53b497eb9ccad9a55867f36"},
+ {file = "numpy-1.26.3-cp312-cp312-win32.whl", hash = "sha256:f73497e8c38295aaa4741bdfa4fda1a5aedda5473074369eca10626835445511"},
+ {file = "numpy-1.26.3-cp312-cp312-win_amd64.whl", hash = "sha256:da4b0c6c699a0ad73c810736303f7fbae483bcb012e38d7eb06a5e3b432c981b"},
+ {file = "numpy-1.26.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1666f634cb3c80ccbd77ec97bc17337718f56d6658acf5d3b906ca03e90ce87f"},
+ {file = "numpy-1.26.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18c3319a7d39b2c6a9e3bb75aab2304ab79a811ac0168a671a62e6346c29b03f"},
+ {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b7e807d6888da0db6e7e75838444d62495e2b588b99e90dd80c3459594e857b"},
+ {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4d362e17bcb0011738c2d83e0a65ea8ce627057b2fdda37678f4374a382a137"},
+ {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b8c275f0ae90069496068c714387b4a0eba5d531aace269559ff2b43655edd58"},
+ {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cc0743f0302b94f397a4a65a660d4cd24267439eb16493fb3caad2e4389bccbb"},
+ {file = "numpy-1.26.3-cp39-cp39-win32.whl", hash = "sha256:9bc6d1a7f8cedd519c4b7b1156d98e051b726bf160715b769106661d567b3f03"},
+ {file = "numpy-1.26.3-cp39-cp39-win_amd64.whl", hash = "sha256:867e3644e208c8922a3be26fc6bbf112a035f50f0a86497f98f228c50c607bb2"},
+ {file = "numpy-1.26.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3c67423b3703f8fbd90f5adaa37f85b5794d3366948efe9a5190a5f3a83fc34e"},
+ {file = "numpy-1.26.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46f47ee566d98849323f01b349d58f2557f02167ee301e5e28809a8c0e27a2d0"},
+ {file = "numpy-1.26.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a8474703bffc65ca15853d5fd4d06b18138ae90c17c8d12169968e998e448bb5"},
+ {file = "numpy-1.26.3.tar.gz", hash = "sha256:697df43e2b6310ecc9d95f05d5ef20eacc09c7c4ecc9da3f235d39e71b7da1e4"},
]
[[package]]
@@ -1668,35 +1592,36 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"]
[[package]]
name = "openai"
-version = "0.27.10"
-description = "Python client library for the OpenAI API"
+version = "1.7.2"
+description = "The official Python library for the openai API"
optional = false
python-versions = ">=3.7.1"
files = [
- {file = "openai-0.27.10-py3-none-any.whl", hash = "sha256:beabd1757e3286fa166dde3b70ebb5ad8081af046876b47c14c41e203ed22a14"},
- {file = "openai-0.27.10.tar.gz", hash = "sha256:60e09edf7100080283688748c6803b7b3b52d5a55d21890f3815292a0552d83b"},
+ {file = "openai-1.7.2-py3-none-any.whl", hash = "sha256:8f41b90a762f5fd9d182b45851041386fed94c8ad240a70abefee61a68e0ef53"},
+ {file = "openai-1.7.2.tar.gz", hash = "sha256:c73c78878258b07f1b468b0602c6591f25a1478f49ecb90b9bd44b7cc80bce73"},
]
[package.dependencies]
-aiohttp = "*"
-requests = ">=2.20"
-tqdm = "*"
+anyio = ">=3.5.0,<5"
+distro = ">=1.7.0,<2"
+httpx = ">=0.23.0,<1"
+pydantic = ">=1.9.0,<3"
+sniffio = "*"
+tqdm = ">4"
+typing-extensions = ">=4.7,<5"
[package.extras]
-datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
-dev = ["black (>=21.6b0,<22.0)", "pytest (==6.*)", "pytest-asyncio", "pytest-mock"]
-embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"]
-wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"]
+datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
[[package]]
name = "outcome"
-version = "1.2.0"
+version = "1.3.0.post0"
description = "Capture the outcome of Python function calls."
optional = false
python-versions = ">=3.7"
files = [
- {file = "outcome-1.2.0-py2.py3-none-any.whl", hash = "sha256:c4ab89a56575d6d38a05aa16daeaa333109c1f96167aba8901ab18b6b5e0f7f5"},
- {file = "outcome-1.2.0.tar.gz", hash = "sha256:6f82bd3de45da303cf1f771ecafa1633750a358436a8bb60e06a1ceb745d2672"},
+ {file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"},
+ {file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"},
]
[package.dependencies]
@@ -1704,118 +1629,61 @@ attrs = ">=19.2.0"
[[package]]
name = "packaging"
-version = "23.1"
+version = "23.2"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.7"
files = [
- {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
- {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
+ {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
+ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
]
[[package]]
name = "pandas"
-version = "2.1.0"
-description = "Powerful data structures for data analysis, time series, and statistics"
-optional = false
-python-versions = ">=3.9"
-files = [
- {file = "pandas-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:40dd20439ff94f1b2ed55b393ecee9cb6f3b08104c2c40b0cb7186a2f0046242"},
- {file = "pandas-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d4f38e4fedeba580285eaac7ede4f686c6701a9e618d8a857b138a126d067f2f"},
- {file = "pandas-2.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e6a0fe052cf27ceb29be9429428b4918f3740e37ff185658f40d8702f0b3e09"},
- {file = "pandas-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d81e1813191070440d4c7a413cb673052b3b4a984ffd86b8dd468c45742d3cc"},
- {file = "pandas-2.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:eb20252720b1cc1b7d0b2879ffc7e0542dd568f24d7c4b2347cb035206936421"},
- {file = "pandas-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:38f74ef7ebc0ffb43b3d633e23d74882bce7e27bfa09607f3c5d3e03ffd9a4a5"},
- {file = "pandas-2.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cda72cc8c4761c8f1d97b169661f23a86b16fdb240bdc341173aee17e4d6cedd"},
- {file = "pandas-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d97daeac0db8c993420b10da4f5f5b39b01fc9ca689a17844e07c0a35ac96b4b"},
- {file = "pandas-2.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8c58b1113892e0c8078f006a167cc210a92bdae23322bb4614f2f0b7a4b510f"},
- {file = "pandas-2.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:629124923bcf798965b054a540f9ccdfd60f71361255c81fa1ecd94a904b9dd3"},
- {file = "pandas-2.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:70cf866af3ab346a10debba8ea78077cf3a8cd14bd5e4bed3d41555a3280041c"},
- {file = "pandas-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:d53c8c1001f6a192ff1de1efe03b31a423d0eee2e9e855e69d004308e046e694"},
- {file = "pandas-2.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86f100b3876b8c6d1a2c66207288ead435dc71041ee4aea789e55ef0e06408cb"},
- {file = "pandas-2.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28f330845ad21c11db51e02d8d69acc9035edfd1116926ff7245c7215db57957"},
- {file = "pandas-2.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9a6ccf0963db88f9b12df6720e55f337447aea217f426a22d71f4213a3099a6"},
- {file = "pandas-2.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d99e678180bc59b0c9443314297bddce4ad35727a1a2656dbe585fd78710b3b9"},
- {file = "pandas-2.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b31da36d376d50a1a492efb18097b9101bdbd8b3fbb3f49006e02d4495d4c644"},
- {file = "pandas-2.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:0164b85937707ec7f70b34a6c3a578dbf0f50787f910f21ca3b26a7fd3363437"},
- {file = "pandas-2.1.0.tar.gz", hash = "sha256:62c24c7fc59e42b775ce0679cfa7b14a5f9bfb7643cfbe708c960699e05fb918"},
-]
-
-[package.dependencies]
-numpy = {version = ">=1.23.2", markers = "python_version >= \"3.11\""}
-python-dateutil = ">=2.8.2"
-pytz = ">=2020.1"
-tzdata = ">=2022.1"
-
-[package.extras]
-all = ["PyQt5 (>=5.15.6)", "SQLAlchemy (>=1.4.36)", "beautifulsoup4 (>=4.11.1)", "bottleneck (>=1.3.4)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=0.8.1)", "fsspec (>=2022.05.0)", "gcsfs (>=2022.05.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.8.0)", "matplotlib (>=3.6.1)", "numba (>=0.55.2)", "numexpr (>=2.8.0)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pandas-gbq (>=0.17.5)", "psycopg2 (>=2.9.3)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.5)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "pyxlsb (>=1.0.9)", "qtpy (>=2.2.0)", "s3fs (>=2022.05.0)", "scipy (>=1.8.1)", "tables (>=3.7.0)", "tabulate (>=0.8.10)", "xarray (>=2022.03.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)", "zstandard (>=0.17.0)"]
-aws = ["s3fs (>=2022.05.0)"]
-clipboard = ["PyQt5 (>=5.15.6)", "qtpy (>=2.2.0)"]
-compression = ["zstandard (>=0.17.0)"]
-computation = ["scipy (>=1.8.1)", "xarray (>=2022.03.0)"]
-consortium-standard = ["dataframe-api-compat (>=0.1.7)"]
-excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pyxlsb (>=1.0.9)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)"]
-feather = ["pyarrow (>=7.0.0)"]
-fss = ["fsspec (>=2022.05.0)"]
-gcp = ["gcsfs (>=2022.05.0)", "pandas-gbq (>=0.17.5)"]
-hdf5 = ["tables (>=3.7.0)"]
-html = ["beautifulsoup4 (>=4.11.1)", "html5lib (>=1.1)", "lxml (>=4.8.0)"]
-mysql = ["SQLAlchemy (>=1.4.36)", "pymysql (>=1.0.2)"]
-output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.8.10)"]
-parquet = ["pyarrow (>=7.0.0)"]
-performance = ["bottleneck (>=1.3.4)", "numba (>=0.55.2)", "numexpr (>=2.8.0)"]
-plot = ["matplotlib (>=3.6.1)"]
-postgresql = ["SQLAlchemy (>=1.4.36)", "psycopg2 (>=2.9.3)"]
-spss = ["pyreadstat (>=1.1.5)"]
-sql-other = ["SQLAlchemy (>=1.4.36)"]
-test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"]
-xml = ["lxml (>=4.8.0)"]
-
-[[package]]
-name = "pandas"
-version = "2.1.1"
+version = "2.1.4"
description = "Powerful data structures for data analysis, time series, and statistics"
optional = false
python-versions = ">=3.9"
files = [
- {file = "pandas-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58d997dbee0d4b64f3cb881a24f918b5f25dd64ddf31f467bb9b67ae4c63a1e4"},
- {file = "pandas-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02304e11582c5d090e5a52aec726f31fe3f42895d6bfc1f28738f9b64b6f0614"},
- {file = "pandas-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffa8f0966de2c22de408d0e322db2faed6f6e74265aa0856f3824813cf124363"},
- {file = "pandas-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1f84c144dee086fe4f04a472b5cd51e680f061adf75c1ae4fc3a9275560f8f4"},
- {file = "pandas-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75ce97667d06d69396d72be074f0556698c7f662029322027c226fd7a26965cb"},
- {file = "pandas-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:4c3f32fd7c4dccd035f71734df39231ac1a6ff95e8bdab8d891167197b7018d2"},
- {file = "pandas-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e2959720b70e106bb1d8b6eadd8ecd7c8e99ccdbe03ee03260877184bb2877d"},
- {file = "pandas-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25e8474a8eb258e391e30c288eecec565bfed3e026f312b0cbd709a63906b6f8"},
- {file = "pandas-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8bd1685556f3374520466998929bade3076aeae77c3e67ada5ed2b90b4de7f0"},
- {file = "pandas-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc3657869c7902810f32bd072f0740487f9e030c1a3ab03e0af093db35a9d14e"},
- {file = "pandas-2.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:05674536bd477af36aa2effd4ec8f71b92234ce0cc174de34fd21e2ee99adbc2"},
- {file = "pandas-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:b407381258a667df49d58a1b637be33e514b07f9285feb27769cedb3ab3d0b3a"},
- {file = "pandas-2.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c747793c4e9dcece7bb20156179529898abf505fe32cb40c4052107a3c620b49"},
- {file = "pandas-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3bcad1e6fb34b727b016775bea407311f7721db87e5b409e6542f4546a4951ea"},
- {file = "pandas-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5ec7740f9ccb90aec64edd71434711f58ee0ea7f5ed4ac48be11cfa9abf7317"},
- {file = "pandas-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29deb61de5a8a93bdd033df328441a79fcf8dd3c12d5ed0b41a395eef9cd76f0"},
- {file = "pandas-2.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4f99bebf19b7e03cf80a4e770a3e65eee9dd4e2679039f542d7c1ace7b7b1daa"},
- {file = "pandas-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:84e7e910096416adec68075dc87b986ff202920fb8704e6d9c8c9897fe7332d6"},
- {file = "pandas-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:366da7b0e540d1b908886d4feb3d951f2f1e572e655c1160f5fde28ad4abb750"},
- {file = "pandas-2.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e50e72b667415a816ac27dfcfe686dc5a0b02202e06196b943d54c4f9c7693e"},
- {file = "pandas-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc1ab6a25da197f03ebe6d8fa17273126120874386b4ac11c1d687df288542dd"},
- {file = "pandas-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0dbfea0dd3901ad4ce2306575c54348d98499c95be01b8d885a2737fe4d7a98"},
- {file = "pandas-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0489b0e6aa3d907e909aef92975edae89b1ee1654db5eafb9be633b0124abe97"},
- {file = "pandas-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:4cdb0fab0400c2cb46dafcf1a0fe084c8bb2480a1fa8d81e19d15e12e6d4ded2"},
- {file = "pandas-2.1.1.tar.gz", hash = "sha256:fecb198dc389429be557cde50a2d46da8434a17fe37d7d41ff102e3987fd947b"},
+ {file = "pandas-2.1.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bdec823dc6ec53f7a6339a0e34c68b144a7a1fd28d80c260534c39c62c5bf8c9"},
+ {file = "pandas-2.1.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:294d96cfaf28d688f30c918a765ea2ae2e0e71d3536754f4b6de0ea4a496d034"},
+ {file = "pandas-2.1.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b728fb8deba8905b319f96447a27033969f3ea1fea09d07d296c9030ab2ed1d"},
+ {file = "pandas-2.1.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00028e6737c594feac3c2df15636d73ace46b8314d236100b57ed7e4b9ebe8d9"},
+ {file = "pandas-2.1.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:426dc0f1b187523c4db06f96fb5c8d1a845e259c99bda74f7de97bd8a3bb3139"},
+ {file = "pandas-2.1.4-cp310-cp310-win_amd64.whl", hash = "sha256:f237e6ca6421265643608813ce9793610ad09b40154a3344a088159590469e46"},
+ {file = "pandas-2.1.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b7d852d16c270e4331f6f59b3e9aa23f935f5c4b0ed2d0bc77637a8890a5d092"},
+ {file = "pandas-2.1.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7d5f2f54f78164b3d7a40f33bf79a74cdee72c31affec86bfcabe7e0789821"},
+ {file = "pandas-2.1.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0aa6e92e639da0d6e2017d9ccff563222f4eb31e4b2c3cf32a2a392fc3103c0d"},
+ {file = "pandas-2.1.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d797591b6846b9db79e65dc2d0d48e61f7db8d10b2a9480b4e3faaddc421a171"},
+ {file = "pandas-2.1.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2d3e7b00f703aea3945995ee63375c61b2e6aa5aa7871c5d622870e5e137623"},
+ {file = "pandas-2.1.4-cp311-cp311-win_amd64.whl", hash = "sha256:dc9bf7ade01143cddc0074aa6995edd05323974e6e40d9dbde081021ded8510e"},
+ {file = "pandas-2.1.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:482d5076e1791777e1571f2e2d789e940dedd927325cc3cb6d0800c6304082f6"},
+ {file = "pandas-2.1.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8a706cfe7955c4ca59af8c7a0517370eafbd98593155b48f10f9811da440248b"},
+ {file = "pandas-2.1.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0513a132a15977b4a5b89aabd304647919bc2169eac4c8536afb29c07c23540"},
+ {file = "pandas-2.1.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9f17f2b6fc076b2a0078862547595d66244db0f41bf79fc5f64a5c4d635bead"},
+ {file = "pandas-2.1.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:45d63d2a9b1b37fa6c84a68ba2422dc9ed018bdaa668c7f47566a01188ceeec1"},
+ {file = "pandas-2.1.4-cp312-cp312-win_amd64.whl", hash = "sha256:f69b0c9bb174a2342818d3e2778584e18c740d56857fc5cdb944ec8bbe4082cf"},
+ {file = "pandas-2.1.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3f06bda01a143020bad20f7a85dd5f4a1600112145f126bc9e3e42077c24ef34"},
+ {file = "pandas-2.1.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab5796839eb1fd62a39eec2916d3e979ec3130509930fea17fe6f81e18108f6a"},
+ {file = "pandas-2.1.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edbaf9e8d3a63a9276d707b4d25930a262341bca9874fcb22eff5e3da5394732"},
+ {file = "pandas-2.1.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ebfd771110b50055712b3b711b51bee5d50135429364d0498e1213a7adc2be8"},
+ {file = "pandas-2.1.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8ea107e0be2aba1da619cc6ba3f999b2bfc9669a83554b1904ce3dd9507f0860"},
+ {file = "pandas-2.1.4-cp39-cp39-win_amd64.whl", hash = "sha256:d65148b14788b3758daf57bf42725caa536575da2b64df9964c563b015230984"},
+ {file = "pandas-2.1.4.tar.gz", hash = "sha256:fcb68203c833cc735321512e13861358079a96c174a61f5116a1de89c58c0ef7"},
]
[package.dependencies]
numpy = [
- {version = ">=1.22.4", markers = "python_version < \"3.11\""},
- {version = ">=1.23.2", markers = "python_version == \"3.11\""},
+ {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""},
+ {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""},
+ {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""},
]
python-dateutil = ">=2.8.2"
pytz = ">=2020.1"
tzdata = ">=2022.1"
[package.extras]
-all = ["PyQt5 (>=5.15.6)", "SQLAlchemy (>=1.4.36)", "beautifulsoup4 (>=4.11.1)", "bottleneck (>=1.3.4)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=0.8.1)", "fsspec (>=2022.05.0)", "gcsfs (>=2022.05.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.8.0)", "matplotlib (>=3.6.1)", "numba (>=0.55.2)", "numexpr (>=2.8.0)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pandas-gbq (>=0.17.5)", "psycopg2 (>=2.9.3)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.5)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "pyxlsb (>=1.0.9)", "qtpy (>=2.2.0)", "s3fs (>=2022.05.0)", "scipy (>=1.8.1)", "tables (>=3.7.0)", "tabulate (>=0.8.10)", "xarray (>=2022.03.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)", "zstandard (>=0.17.0)"]
+all = ["PyQt5 (>=5.15.6)", "SQLAlchemy (>=1.4.36)", "beautifulsoup4 (>=4.11.1)", "bottleneck (>=1.3.4)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=0.8.1)", "fsspec (>=2022.05.0)", "gcsfs (>=2022.05.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.8.0)", "matplotlib (>=3.6.1)", "numba (>=0.55.2)", "numexpr (>=2.8.0)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pandas-gbq (>=0.17.5)", "psycopg2 (>=2.9.3)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.5)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "pyxlsb (>=1.0.9)", "qtpy (>=2.2.0)", "s3fs (>=2022.05.0)", "scipy (>=1.8.1)", "tables (>=3.7.0)", "tabulate (>=0.8.10)", "xarray (>=2022.03.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)", "zstandard (>=0.17.0)"]
aws = ["s3fs (>=2022.05.0)"]
clipboard = ["PyQt5 (>=5.15.6)", "qtpy (>=2.2.0)"]
compression = ["zstandard (>=0.17.0)"]
@@ -1835,7 +1703,7 @@ plot = ["matplotlib (>=3.6.1)"]
postgresql = ["SQLAlchemy (>=1.4.36)", "psycopg2 (>=2.9.3)"]
spss = ["pyreadstat (>=1.1.5)"]
sql-other = ["SQLAlchemy (>=1.4.36)"]
-test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"]
+test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"]
xml = ["lxml (>=4.8.0)"]
[[package]]
@@ -1855,116 +1723,123 @@ testing = ["docopt", "pytest (<6.0.0)"]
[[package]]
name = "pathspec"
-version = "0.11.2"
+version = "0.12.1"
description = "Utility library for gitignore style pattern matching of file paths."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
- {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
+ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
+ {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
]
[[package]]
name = "pexpect"
-version = "4.8.0"
+version = "4.9.0"
description = "Pexpect allows easy control of interactive console applications."
optional = false
python-versions = "*"
files = [
- {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"},
- {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"},
+ {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"},
+ {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"},
]
[package.dependencies]
ptyprocess = ">=0.5"
[[package]]
-name = "pickleshare"
-version = "0.7.5"
-description = "Tiny 'shelve'-like database with concurrency support"
-optional = false
-python-versions = "*"
-files = [
- {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"},
- {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"},
-]
-
-[[package]]
name = "pillow"
-version = "10.0.1"
+version = "10.2.0"
description = "Python Imaging Library (Fork)"
optional = false
python-versions = ">=3.8"
files = [
- {file = "Pillow-10.0.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:8f06be50669087250f319b706decf69ca71fdecd829091a37cc89398ca4dc17a"},
- {file = "Pillow-10.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50bd5f1ebafe9362ad622072a1d2f5850ecfa44303531ff14353a4059113b12d"},
- {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6a90167bcca1216606223a05e2cf991bb25b14695c518bc65639463d7db722d"},
- {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f11c9102c56ffb9ca87134bd025a43d2aba3f1155f508eff88f694b33a9c6d19"},
- {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:186f7e04248103482ea6354af6d5bcedb62941ee08f7f788a1c7707bc720c66f"},
- {file = "Pillow-10.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0462b1496505a3462d0f35dc1c4d7b54069747d65d00ef48e736acda2c8cbdff"},
- {file = "Pillow-10.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d889b53ae2f030f756e61a7bff13684dcd77e9af8b10c6048fb2c559d6ed6eaf"},
- {file = "Pillow-10.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:552912dbca585b74d75279a7570dd29fa43b6d93594abb494ebb31ac19ace6bd"},
- {file = "Pillow-10.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:787bb0169d2385a798888e1122c980c6eff26bf941a8ea79747d35d8f9210ca0"},
- {file = "Pillow-10.0.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:fd2a5403a75b54661182b75ec6132437a181209b901446ee5724b589af8edef1"},
- {file = "Pillow-10.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2d7e91b4379f7a76b31c2dda84ab9e20c6220488e50f7822e59dac36b0cd92b1"},
- {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19e9adb3f22d4c416e7cd79b01375b17159d6990003633ff1d8377e21b7f1b21"},
- {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93139acd8109edcdeffd85e3af8ae7d88b258b3a1e13a038f542b79b6d255c54"},
- {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:92a23b0431941a33242b1f0ce6c88a952e09feeea9af4e8be48236a68ffe2205"},
- {file = "Pillow-10.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cbe68deb8580462ca0d9eb56a81912f59eb4542e1ef8f987405e35a0179f4ea2"},
- {file = "Pillow-10.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:522ff4ac3aaf839242c6f4e5b406634bfea002469656ae8358644fc6c4856a3b"},
- {file = "Pillow-10.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:84efb46e8d881bb06b35d1d541aa87f574b58e87f781cbba8d200daa835b42e1"},
- {file = "Pillow-10.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:898f1d306298ff40dc1b9ca24824f0488f6f039bc0e25cfb549d3195ffa17088"},
- {file = "Pillow-10.0.1-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:bcf1207e2f2385a576832af02702de104be71301c2696d0012b1b93fe34aaa5b"},
- {file = "Pillow-10.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d6c9049c6274c1bb565021367431ad04481ebb54872edecfcd6088d27edd6ed"},
- {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28444cb6ad49726127d6b340217f0627abc8732f1194fd5352dec5e6a0105635"},
- {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de596695a75496deb3b499c8c4f8e60376e0516e1a774e7bc046f0f48cd620ad"},
- {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:2872f2d7846cf39b3dbff64bc1104cc48c76145854256451d33c5faa55c04d1a"},
- {file = "Pillow-10.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4ce90f8a24e1c15465048959f1e94309dfef93af272633e8f37361b824532e91"},
- {file = "Pillow-10.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ee7810cf7c83fa227ba9125de6084e5e8b08c59038a7b2c9045ef4dde61663b4"},
- {file = "Pillow-10.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b1be1c872b9b5fcc229adeadbeb51422a9633abd847c0ff87dc4ef9bb184ae08"},
- {file = "Pillow-10.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:98533fd7fa764e5f85eebe56c8e4094db912ccbe6fbf3a58778d543cadd0db08"},
- {file = "Pillow-10.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:764d2c0daf9c4d40ad12fbc0abd5da3af7f8aa11daf87e4fa1b834000f4b6b0a"},
- {file = "Pillow-10.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fcb59711009b0168d6ee0bd8fb5eb259c4ab1717b2f538bbf36bacf207ef7a68"},
- {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:697a06bdcedd473b35e50a7e7506b1d8ceb832dc238a336bd6f4f5aa91a4b500"},
- {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f665d1e6474af9f9da5e86c2a3a2d2d6204e04d5af9c06b9d42afa6ebde3f21"},
- {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:2fa6dd2661838c66f1a5473f3b49ab610c98a128fc08afbe81b91a1f0bf8c51d"},
- {file = "Pillow-10.0.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:3a04359f308ebee571a3127fdb1bd01f88ba6f6fb6d087f8dd2e0d9bff43f2a7"},
- {file = "Pillow-10.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:723bd25051454cea9990203405fa6b74e043ea76d4968166dfd2569b0210886a"},
- {file = "Pillow-10.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:71671503e3015da1b50bd18951e2f9daf5b6ffe36d16f1eb2c45711a301521a7"},
- {file = "Pillow-10.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:44e7e4587392953e5e251190a964675f61e4dae88d1e6edbe9f36d6243547ff3"},
- {file = "Pillow-10.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:3855447d98cced8670aaa63683808df905e956f00348732448b5a6df67ee5849"},
- {file = "Pillow-10.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ed2d9c0704f2dc4fa980b99d565c0c9a543fe5101c25b3d60488b8ba80f0cce1"},
- {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5bb289bb835f9fe1a1e9300d011eef4d69661bb9b34d5e196e5e82c4cb09b37"},
- {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a0d3e54ab1df9df51b914b2233cf779a5a10dfd1ce339d0421748232cea9876"},
- {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:2cc6b86ece42a11f16f55fe8903595eff2b25e0358dec635d0a701ac9586588f"},
- {file = "Pillow-10.0.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:ca26ba5767888c84bf5a0c1a32f069e8204ce8c21d00a49c90dabeba00ce0145"},
- {file = "Pillow-10.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f0b4b06da13275bc02adfeb82643c4a6385bd08d26f03068c2796f60d125f6f2"},
- {file = "Pillow-10.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bc2e3069569ea9dbe88d6b8ea38f439a6aad8f6e7a6283a38edf61ddefb3a9bf"},
- {file = "Pillow-10.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:8b451d6ead6e3500b6ce5c7916a43d8d8d25ad74b9102a629baccc0808c54971"},
- {file = "Pillow-10.0.1-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:32bec7423cdf25c9038fef614a853c9d25c07590e1a870ed471f47fb80b244db"},
- {file = "Pillow-10.0.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cf63d2c6928b51d35dfdbda6f2c1fddbe51a6bc4a9d4ee6ea0e11670dd981e"},
- {file = "Pillow-10.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f6d3d4c905e26354e8f9d82548475c46d8e0889538cb0657aa9c6f0872a37aa4"},
- {file = "Pillow-10.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:847e8d1017c741c735d3cd1883fa7b03ded4f825a6e5fcb9378fd813edee995f"},
- {file = "Pillow-10.0.1-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:7f771e7219ff04b79e231d099c0a28ed83aa82af91fd5fa9fdb28f5b8d5addaf"},
- {file = "Pillow-10.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459307cacdd4138edee3875bbe22a2492519e060660eaf378ba3b405d1c66317"},
- {file = "Pillow-10.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b059ac2c4c7a97daafa7dc850b43b2d3667def858a4f112d1aa082e5c3d6cf7d"},
- {file = "Pillow-10.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6caf3cd38449ec3cd8a68b375e0c6fe4b6fd04edb6c9766b55ef84a6e8ddf2d"},
- {file = "Pillow-10.0.1.tar.gz", hash = "sha256:d72967b06be9300fed5cfbc8b5bafceec48bf7cdc7dab66b1d2549035287191d"},
+ {file = "pillow-10.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e"},
+ {file = "pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563"},
+ {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2"},
+ {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c"},
+ {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0"},
+ {file = "pillow-10.2.0-cp310-cp310-win32.whl", hash = "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023"},
+ {file = "pillow-10.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72"},
+ {file = "pillow-10.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad"},
+ {file = "pillow-10.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5"},
+ {file = "pillow-10.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f"},
+ {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311"},
+ {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1"},
+ {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757"},
+ {file = "pillow-10.2.0-cp311-cp311-win32.whl", hash = "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068"},
+ {file = "pillow-10.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56"},
+ {file = "pillow-10.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1"},
+ {file = "pillow-10.2.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef"},
+ {file = "pillow-10.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2"},
+ {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04"},
+ {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f"},
+ {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb"},
+ {file = "pillow-10.2.0-cp312-cp312-win32.whl", hash = "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f"},
+ {file = "pillow-10.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9"},
+ {file = "pillow-10.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48"},
+ {file = "pillow-10.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9"},
+ {file = "pillow-10.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213"},
+ {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d"},
+ {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6"},
+ {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe"},
+ {file = "pillow-10.2.0-cp38-cp38-win32.whl", hash = "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e"},
+ {file = "pillow-10.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39"},
+ {file = "pillow-10.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67"},
+ {file = "pillow-10.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01"},
+ {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13"},
+ {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7"},
+ {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591"},
+ {file = "pillow-10.2.0-cp39-cp39-win32.whl", hash = "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516"},
+ {file = "pillow-10.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8"},
+ {file = "pillow-10.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a"},
+ {file = "pillow-10.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6"},
+ {file = "pillow-10.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a"},
+ {file = "pillow-10.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"},
+ {file = "pillow-10.2.0.tar.gz", hash = "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e"},
]
[package.extras]
docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"]
+fpx = ["olefile"]
+mic = ["olefile"]
tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
+typing = ["typing-extensions"]
+xmp = ["defusedxml"]
[[package]]
name = "platformdirs"
-version = "3.10.0"
+version = "4.1.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"},
- {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"},
+ {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"},
+ {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"},
]
[package.extras]
@@ -1988,13 +1863,13 @@ testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "pre-commit"
-version = "3.4.0"
+version = "3.6.0"
description = "A framework for managing and maintaining multi-language pre-commit hooks."
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.9"
files = [
- {file = "pre_commit-3.4.0-py2.py3-none-any.whl", hash = "sha256:96d529a951f8b677f730a7212442027e8ba53f9b04d217c4c67dc56c393ad945"},
- {file = "pre_commit-3.4.0.tar.gz", hash = "sha256:6bbd5129a64cad4c0dfaeeb12cd8f7ea7e15b77028d985341478c8af3c759522"},
+ {file = "pre_commit-3.6.0-py2.py3-none-any.whl", hash = "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376"},
+ {file = "pre_commit-3.6.0.tar.gz", hash = "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d"},
]
[package.dependencies]
@@ -2006,13 +1881,13 @@ virtualenv = ">=20.10.0"
[[package]]
name = "prompt-toolkit"
-version = "3.0.39"
+version = "3.0.43"
description = "Library for building powerful interactive command lines in Python"
optional = false
python-versions = ">=3.7.0"
files = [
- {file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"},
- {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"},
+ {file = "prompt_toolkit-3.0.43-py3-none-any.whl", hash = "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6"},
+ {file = "prompt_toolkit-3.0.43.tar.gz", hash = "sha256:3527b7af26106cbc65a040bcc84839a3566ec1b051bb0bfe953631e704b0ff7d"},
]
[package.dependencies]
@@ -2020,25 +1895,27 @@ wcwidth = "*"
[[package]]
name = "psutil"
-version = "5.9.5"
+version = "5.9.7"
description = "Cross-platform lib for process and system monitoring in Python."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-files = [
- {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"},
- {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"},
- {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"},
- {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"},
- {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"},
- {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"},
- {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"},
- {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"},
- {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"},
- {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"},
- {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"},
- {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"},
- {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"},
- {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"},
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+files = [
+ {file = "psutil-5.9.7-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0bd41bf2d1463dfa535942b2a8f0e958acf6607ac0be52265ab31f7923bcd5e6"},
+ {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:5794944462509e49d4d458f4dbfb92c47539e7d8d15c796f141f474010084056"},
+ {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:fe361f743cb3389b8efda21980d93eb55c1f1e3898269bc9a2a1d0bb7b1f6508"},
+ {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:e469990e28f1ad738f65a42dcfc17adaed9d0f325d55047593cb9033a0ab63df"},
+ {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:3c4747a3e2ead1589e647e64aad601981f01b68f9398ddf94d01e3dc0d1e57c7"},
+ {file = "psutil-5.9.7-cp27-none-win32.whl", hash = "sha256:1d4bc4a0148fdd7fd8f38e0498639ae128e64538faa507df25a20f8f7fb2341c"},
+ {file = "psutil-5.9.7-cp27-none-win_amd64.whl", hash = "sha256:4c03362e280d06bbbfcd52f29acd79c733e0af33d707c54255d21029b8b32ba6"},
+ {file = "psutil-5.9.7-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ea36cc62e69a13ec52b2f625c27527f6e4479bca2b340b7a452af55b34fcbe2e"},
+ {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1132704b876e58d277168cd729d64750633d5ff0183acf5b3c986b8466cd0284"},
+ {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe8b7f07948f1304497ce4f4684881250cd859b16d06a1dc4d7941eeb6233bfe"},
+ {file = "psutil-5.9.7-cp36-cp36m-win32.whl", hash = "sha256:b27f8fdb190c8c03914f908a4555159327d7481dac2f01008d483137ef3311a9"},
+ {file = "psutil-5.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:44969859757f4d8f2a9bd5b76eba8c3099a2c8cf3992ff62144061e39ba8568e"},
+ {file = "psutil-5.9.7-cp37-abi3-win32.whl", hash = "sha256:c727ca5a9b2dd5193b8644b9f0c883d54f1248310023b5ad3e92036c5e2ada68"},
+ {file = "psutil-5.9.7-cp37-abi3-win_amd64.whl", hash = "sha256:f37f87e4d73b79e6c5e749440c3113b81d1ee7d26f21c19c47371ddea834f414"},
+ {file = "psutil-5.9.7-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:032f4f2c909818c86cea4fe2cc407f1c0f0cde8e6c6d702b28b8ce0c0d143340"},
+ {file = "psutil-5.9.7.tar.gz", hash = "sha256:3f02134e82cfb5d089fddf20bb2e03fd5cd52395321d1c8458a9e58500ff417c"},
]
[package.extras]
@@ -2071,13 +1948,13 @@ tests = ["pytest"]
[[package]]
name = "pyasn1"
-version = "0.5.0"
+version = "0.5.1"
description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
files = [
- {file = "pyasn1-0.5.0-py2.py3-none-any.whl", hash = "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57"},
- {file = "pyasn1-0.5.0.tar.gz", hash = "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"},
+ {file = "pyasn1-0.5.1-py2.py3-none-any.whl", hash = "sha256:4439847c58d40b1d0a573d07e3856e95333f1976294494c325775aeca506eb58"},
+ {file = "pyasn1-0.5.1.tar.gz", hash = "sha256:6d391a96e59b23130a5cfa74d6fd7f388dbbe26cc8f1edf39fdddf08d9d6676c"},
]
[[package]]
@@ -2181,17 +2058,18 @@ files = [
[[package]]
name = "pygments"
-version = "2.16.1"
+version = "2.17.2"
description = "Pygments is a syntax highlighting package written in Python."
optional = false
python-versions = ">=3.7"
files = [
- {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"},
- {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"},
+ {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"},
+ {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"},
]
[package.extras]
plugins = ["importlib-metadata"]
+windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pyparsing"
@@ -2221,13 +2099,13 @@ files = [
[[package]]
name = "pytest"
-version = "7.4.2"
+version = "7.4.4"
description = "pytest: simple powerful testing with Python"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"},
- {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"},
+ {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"},
+ {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"},
]
[package.dependencies]
@@ -2289,17 +2167,17 @@ cli = ["click (>=5.0)"]
[[package]]
name = "python-multipart"
-version = "0.0.6"
+version = "0.0.7"
description = "A streaming multipart parser for Python"
optional = false
python-versions = ">=3.7"
files = [
- {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"},
- {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"},
+ {file = "python_multipart-0.0.7-py3-none-any.whl", hash = "sha256:b1fef9a53b74c795e2347daac8c54b252d9e0df9c619712691c1cc8021bd3c49"},
+ {file = "python_multipart-0.0.7.tar.gz", hash = "sha256:288a6c39b06596c1b988bb6794c6fbc80e6c369e35e5062637df256bee0c9af9"},
]
[package.extras]
-dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"]
+dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==2.2.0)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"]
[[package]]
name = "pytz"
@@ -2442,13 +2320,13 @@ pyasn1 = ">=0.1.3"
[[package]]
name = "selenium"
-version = "4.13.0"
+version = "4.16.0"
description = ""
optional = false
python-versions = ">=3.8"
files = [
- {file = "selenium-4.13.0-py3-none-any.whl", hash = "sha256:f0f9185c01ae249a321529c4e3aa0edc2a900642e61fdbb76988cd72d2762ece"},
- {file = "selenium-4.13.0.tar.gz", hash = "sha256:3c413a4f1b8af67824703195e3b1c19cfb1c3186c799efa035d55fd59d6dd59f"},
+ {file = "selenium-4.16.0-py3-none-any.whl", hash = "sha256:aec71f4e6ed6cb3ec25c9c1b5ed56ae31b6da0a7f17474c7566d303f84e6219f"},
+ {file = "selenium-4.16.0.tar.gz", hash = "sha256:b2e987a445306151f7be0e6dfe2aa72a479c2ac6a91b9d5ef2d6dd4e49ad0435"},
]
[package.dependencies]
@@ -2459,43 +2337,21 @@ urllib3 = {version = ">=1.26,<3", extras = ["socks"]}
[[package]]
name = "setuptools"
-version = "68.2.2"
+version = "69.0.3"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"},
- {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"},
+ {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"},
+ {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"},
]
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
[[package]]
-name = "setuptools-scm"
-version = "8.0.3"
-description = "the blessed package to manage your versions by scm tags"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "setuptools-scm-8.0.3.tar.gz", hash = "sha256:0169fd70197efda2f8c4d0b2a7a3d614431b488116f37b79d031e9e7ec884d8c"},
- {file = "setuptools_scm-8.0.3-py3-none-any.whl", hash = "sha256:813822234453438a13c78d05c8af29918fbc06f88efb33d38f065340bbb48c39"},
-]
-
-[package.dependencies]
-packaging = ">=20"
-setuptools = "*"
-tomli = {version = ">=1", markers = "python_version < \"3.11\""}
-typing-extensions = {version = "*", markers = "python_version < \"3.11\""}
-
-[package.extras]
-docs = ["entangled-cli[rich]", "mkdocs", "mkdocs-entangled-plugin", "mkdocs-material", "mkdocstrings[python]", "pygments"]
-rich = ["rich"]
-test = ["pytest", "rich", "virtualenv (>20)"]
-
-[[package]]
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
@@ -2541,13 +2397,13 @@ files = [
[[package]]
name = "stack-data"
-version = "0.6.2"
+version = "0.6.3"
description = "Extract data from python stack frames and tracebacks for informative displays"
optional = false
python-versions = "*"
files = [
- {file = "stack_data-0.6.2-py3-none-any.whl", hash = "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"},
- {file = "stack_data-0.6.2.tar.gz", hash = "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815"},
+ {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"},
+ {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"},
]
[package.dependencies]
@@ -2560,20 +2416,34 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
[[package]]
name = "starlette"
-version = "0.27.0"
+version = "0.36.3"
description = "The little ASGI library that shines."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"},
- {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"},
+ {file = "starlette-0.36.3-py3-none-any.whl", hash = "sha256:13d429aa93a61dc40bf503e8c801db1f1bca3dc706b10ef2434a36123568f044"},
+ {file = "starlette-0.36.3.tar.gz", hash = "sha256:90a671733cfb35771d8cc605e0b679d23b992f8dcfad48cc60b38cb29aeb7080"},
]
[package.dependencies]
anyio = ">=3.4.0,<5"
[package.extras]
-full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"]
+full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"]
+
+[[package]]
+name = "tabulate"
+version = "0.9.0"
+description = "Pretty-print tabular data"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"},
+ {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"},
+]
+
+[package.extras]
+widechars = ["wcwidth"]
[[package]]
name = "toml"
@@ -2619,37 +2489,37 @@ telegram = ["requests"]
[[package]]
name = "traitlets"
-version = "5.10.1"
+version = "5.14.1"
description = "Traitlets Python configuration system"
optional = false
python-versions = ">=3.8"
files = [
- {file = "traitlets-5.10.1-py3-none-any.whl", hash = "sha256:07ab9c5bf8a0499fd7b088ba51be899c90ffc936ffc797d7b6907fc516bcd116"},
- {file = "traitlets-5.10.1.tar.gz", hash = "sha256:db9c4aa58139c3ba850101913915c042bdba86f7c8a0dda1c6f7f92c5da8e542"},
+ {file = "traitlets-5.14.1-py3-none-any.whl", hash = "sha256:2e5a030e6eff91737c643231bfcf04a65b0132078dad75e4936700b213652e74"},
+ {file = "traitlets-5.14.1.tar.gz", hash = "sha256:8585105b371a04b8316a43d5ce29c098575c2e477850b62b848b964f1444527e"},
]
[package.extras]
docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"]
-test = ["argcomplete (>=3.0.3)", "mypy (>=1.5.1)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"]
+test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"]
[[package]]
name = "trio"
-version = "0.22.2"
+version = "0.24.0"
description = "A friendly Python library for async concurrency and I/O"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "trio-0.22.2-py3-none-any.whl", hash = "sha256:f43da357620e5872b3d940a2e3589aa251fd3f881b65a608d742e00809b1ec38"},
- {file = "trio-0.22.2.tar.gz", hash = "sha256:3887cf18c8bcc894433420305468388dac76932e9668afa1c49aa3806b6accb3"},
+ {file = "trio-0.24.0-py3-none-any.whl", hash = "sha256:c3bd3a4e3e3025cd9a2241eae75637c43fe0b9e88b4c97b9161a55b9e54cd72c"},
+ {file = "trio-0.24.0.tar.gz", hash = "sha256:ffa09a74a6bf81b84f8613909fb0beaee84757450183a7a2e0b47b455c0cac5d"},
]
[package.dependencies]
attrs = ">=20.1.0"
cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""}
-exceptiongroup = {version = ">=1.0.0rc9", markers = "python_version < \"3.11\""}
+exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
idna = "*"
outcome = "*"
-sniffio = "*"
+sniffio = ">=1.3.0"
sortedcontainers = "*"
[[package]]
@@ -2695,45 +2565,44 @@ files = [
[[package]]
name = "typing-extensions"
-version = "4.8.0"
+version = "4.9.0"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
files = [
- {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"},
- {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
+ {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"},
+ {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"},
]
[[package]]
name = "tzdata"
-version = "2023.3"
+version = "2023.4"
description = "Provider of IANA time zone data"
optional = false
python-versions = ">=2"
files = [
- {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"},
- {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"},
+ {file = "tzdata-2023.4-py2.py3-none-any.whl", hash = "sha256:aa3ace4329eeacda5b7beb7ea08ece826c28d761cda36e747cfbf97996d39bf3"},
+ {file = "tzdata-2023.4.tar.gz", hash = "sha256:dd54c94f294765522c77399649b4fefd95522479a664a0cec87f41bebc6148c9"},
]
[[package]]
name = "urllib3"
-version = "2.0.5"
+version = "1.26.18"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
- {file = "urllib3-2.0.5-py3-none-any.whl", hash = "sha256:ef16afa8ba34a1f989db38e1dbbe0c302e4289a47856990d0682e374563ce35e"},
- {file = "urllib3-2.0.5.tar.gz", hash = "sha256:13abf37382ea2ce6fb744d4dad67838eec857c9f4f57009891805e0b5e123594"},
+ {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"},
+ {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"},
]
[package.dependencies]
-pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""}
+PySocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""}
[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
-secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"]
-socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
-zstd = ["zstandard (>=0.18.0)"]
+brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
+secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
+socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "uvicorn"
@@ -2756,19 +2625,19 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)",
[[package]]
name = "virtualenv"
-version = "20.24.5"
+version = "20.25.0"
description = "Virtual Python Environment builder"
optional = false
python-versions = ">=3.7"
files = [
- {file = "virtualenv-20.24.5-py3-none-any.whl", hash = "sha256:b80039f280f4919c77b30f1c23294ae357c4c8701042086e3fc005963e4e537b"},
- {file = "virtualenv-20.24.5.tar.gz", hash = "sha256:e8361967f6da6fbdf1426483bfe9fca8287c242ac0bc30429905721cefbff752"},
+ {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"},
+ {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"},
]
[package.dependencies]
distlib = ">=0.3.7,<1"
filelock = ">=3.12.2,<4"
-platformdirs = ">=3.9.1,<4"
+platformdirs = ">=3.9.1,<5"
[package.extras]
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
@@ -2776,13 +2645,13 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess
[[package]]
name = "wcwidth"
-version = "0.2.7"
+version = "0.2.13"
description = "Measures the displayed width of unicode strings in a terminal"
optional = false
python-versions = "*"
files = [
- {file = "wcwidth-0.2.7-py2.py3-none-any.whl", hash = "sha256:fabf3e32999d9b0dab7d19d845149f326f04fe29bac67709ee071dbd92640a36"},
- {file = "wcwidth-0.2.7.tar.gz", hash = "sha256:1b6d30a98ddd5ce9bbdb33658191fd2423fc9da203fe3ef1855407dcb7ee4e26"},
+ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
+ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
]
[[package]]
@@ -2801,85 +2670,101 @@ h11 = ">=0.9.0,<1"
[[package]]
name = "yarl"
-version = "1.9.2"
+version = "1.9.4"
description = "Yet another URL library"
optional = false
python-versions = ">=3.7"
files = [
- {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"},
- {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"},
- {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"},
- {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"},
- {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"},
- {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"},
- {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"},
- {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"},
- {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"},
- {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"},
- {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"},
- {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"},
- {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"},
- {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"},
- {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"},
- {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"},
- {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"},
- {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"},
- {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"},
- {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"},
- {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"},
- {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"},
- {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"},
- {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"},
- {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"},
- {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"},
- {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"},
- {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"},
- {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"},
- {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"},
- {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"},
- {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"},
- {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"},
- {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"},
- {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"},
- {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"},
- {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"},
- {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"},
- {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"},
- {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"},
- {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"},
- {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"},
- {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"},
- {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"},
- {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"},
- {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"},
- {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"},
- {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"},
- {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"},
- {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"},
- {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"},
- {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"},
- {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"},
- {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"},
- {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"},
- {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"},
- {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"},
- {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"},
- {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"},
- {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"},
- {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"},
- {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"},
- {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"},
- {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"},
- {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"},
- {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"},
- {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"},
- {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"},
- {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"},
- {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"},
- {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"},
- {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"},
- {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"},
- {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"},
+ {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"},
+ {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"},
+ {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"},
+ {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"},
+ {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"},
+ {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"},
+ {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"},
+ {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"},
+ {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"},
+ {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"},
+ {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"},
+ {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"},
+ {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"},
+ {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"},
+ {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"},
+ {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"},
+ {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"},
+ {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"},
+ {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"},
+ {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"},
+ {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"},
+ {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"},
+ {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"},
+ {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"},
+ {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"},
+ {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"},
+ {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"},
+ {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"},
+ {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"},
+ {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"},
+ {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"},
+ {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"},
+ {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"},
+ {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"},
+ {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"},
+ {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"},
+ {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"},
+ {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"},
+ {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"},
+ {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"},
+ {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"},
+ {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"},
+ {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"},
+ {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"},
+ {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"},
+ {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"},
+ {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"},
+ {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"},
+ {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"},
+ {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"},
+ {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"},
+ {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"},
+ {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"},
+ {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"},
+ {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"},
+ {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"},
+ {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"},
+ {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"},
+ {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"},
+ {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"},
+ {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"},
+ {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"},
+ {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"},
+ {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"},
+ {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"},
+ {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"},
+ {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"},
+ {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"},
+ {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"},
+ {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"},
+ {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"},
+ {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"},
+ {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"},
+ {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"},
+ {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"},
+ {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"},
+ {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"},
+ {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"},
+ {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"},
+ {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"},
+ {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"},
+ {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"},
+ {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"},
+ {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"},
+ {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"},
+ {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"},
+ {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"},
+ {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"},
+ {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"},
+ {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"},
]
[package.dependencies]
@@ -2889,4 +2774,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
-content-hash = "88fb4ebec8909eb124de6f9c2027aade4a7df333744ad1ea3151d5fbda5308fb"
+content-hash = "6eefdbbefb500de627cac39eb6eb1fdcecab76dd4c3599cf08ef6dc647cf71c9"
diff --git a/benchmark/pyproject.toml b/benchmark/pyproject.toml
index 61c987b55..6c3976743 100644
--- a/benchmark/pyproject.toml
+++ b/benchmark/pyproject.toml
@@ -11,7 +11,7 @@ packages = [{ include = "agbenchmark" }]
python = "^3.10"
pytest = "^7.3.2"
requests = "^2.31.0"
-openai = "^0.27.8"
+openai = "^1.7.2"
pydantic = "^1.10.9"
python-dotenv = "^1.0.0"
click = "^8.1.3"
@@ -27,11 +27,14 @@ pyvis = "^0.3.2"
selenium = "^4.11.2"
pytest-asyncio = "^0.21.1"
uvicorn = "^0.23.2"
-fastapi = "^0.99.0"
-python-multipart = "^0.0.6"
+fastapi = "^0.109.1"
+python-multipart = "^0.0.7"
toml = "^0.10.2"
-helicone = "^1.0.9"
+# helicone = "^1.0.9" # incompatible with openai@^1.0.0
httpx = "^0.24.0"
+agent-protocol-client = "^1.1.0"
+click-default-group = "^1.2.4"
+tabulate = "^0.9.0"
[tool.poetry.group.dev.dependencies]
flake8 = "^3.9.2"
diff --git a/benchmark/reports/format.py b/benchmark/reports/format.py
new file mode 100755
index 000000000..8a9a872ea
--- /dev/null
+++ b/benchmark/reports/format.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+
+import click
+
+from agbenchmark.reports.processing.report_types import Report
+
+
+@click.command()
+@click.argument("report_json_file", type=click.Path(exists=True, dir_okay=False))
+def print_markdown_report(report_json_file: str):
+ """
+ Generates a Markdown report from a given report.json file.
+
+ :param report_json_file: Path to the report.json file.
+ :return: A string containing the Markdown formatted report.
+ """
+ report = Report.parse_file(report_json_file)
+
+ # Header and metadata
+ click.echo(f"# Benchmark Report")
+ click.echo(f"- ⌛ **Run time:** `{report.metrics.run_time}`")
+ click.echo(
+ f" - **Started at:** `{report.benchmark_start_time[:16].replace('T', '` `')}`"
+ )
+ if report.completion_time:
+ click.echo(
+ f" - **Completed at:** `{report.completion_time[:16].replace('T', '` `')}`"
+ )
+ if report.metrics.total_cost:
+ click.echo(f"- 💸 **Total cost:** `${round(report.metrics.total_cost, 2)}`")
+ click.echo(
+ f"- 🏅 **Highest achieved difficulty:** `{report.metrics.highest_difficulty}`"
+ )
+ click.echo(f"- ⚙️ **Command:** `{report.command}`")
+
+ click.echo() # spacing
+
+ # Aggregate information
+ successful, failed, unreliable = [], [], []
+ for test in report.tests.values():
+ test.metrics.success_percentage = (
+ rsp
+ if (rsp := test.metrics.success_percentage) is not None
+ else sum(float(r.success or 0) for r in test.results)
+ * 100
+ / len(test.results)
+ )
+ if test.metrics.success_percentage == 100.0:
+ successful.append(test)
+ elif test.metrics.success_percentage == 0.0:
+ failed.append(test)
+ else:
+ unreliable.append(test)
+
+ # Summary
+ click.echo("## Summary")
+ click.echo(f"- **`{len(successful)}` passed** {'✅'*len(successful)}")
+ click.echo(f"- **`{len(failed)}` failed** {'❌'*len(failed)}")
+ click.echo(f"- **`{len(unreliable)}` unreliable** {'⚠️'*len(unreliable)}")
+
+ click.echo() # spacing
+
+ # Test results
+ click.echo("## Challenges")
+ for test_name, test in report.tests.items():
+ click.echo() # spacing
+
+ result_indicator = (
+ "✅"
+ if test.metrics.success_percentage == 100.0
+ else "⚠️"
+ if test.metrics.success_percentage > 0
+ else "❌"
+ )
+ click.echo(
+ f"### {test_name} {result_indicator if test.metrics.attempted else '❔'}"
+ )
+ click.echo(f"{test.description}")
+
+ click.echo() # spacing
+
+ click.echo(f"- **Attempted:** {'Yes 👍' if test.metrics.attempted else 'No 👎'}")
+ click.echo(
+ f"- **Success rate:** {round(test.metrics.success_percentage)}% "
+ f"({len([r for r in test.results if r.success])}/{len(test.results)})"
+ )
+ click.echo(f"- **Difficulty:** `{test.difficulty}`")
+ click.echo(f"- **Categories:** `{'`, `'.join(test.category)}`")
+ click.echo(
+ f"<details>\n<summary><strong>Task</strong> (click to expand)</summary>\n\n"
+ f"{indent('> ', test.task)}\n\n"
+ f"Reference answer:\n{indent('> ', test.answer)}\n"
+ "</details>"
+ )
+
+ click.echo() # spacing
+
+ click.echo("\n#### Attempts")
+ for i, attempt in enumerate(test.results, 1):
+ click.echo(
+ f"\n{i}. **{'✅ Passed' if attempt.success else '❌ Failed'}** "
+ f"in **{attempt.run_time}** "
+ f"and **{quantify('step', attempt.n_steps)}**\n"
+ )
+ if attempt.cost is not None:
+ click.echo(f" - **Cost:** `${round(attempt.cost, 3)}`")
+ if attempt.fail_reason:
+ click.echo(
+ " - **Failure reason:**\n"
+ + indent(" > ", attempt.fail_reason)
+ + "\n"
+ )
+ if attempt.steps:
+ click.echo(
+ indent(
+ 3 * " ",
+ "<details>\n<summary><strong>Steps</strong></summary>\n",
+ )
+ )
+ for j, step in enumerate(attempt.steps, 1):
+ click.echo()
+ click.echo(
+ indent(3 * " ", f"{j}. {indent(3*' ', step.output, False)}")
+ )
+ click.echo("\n</details>")
+
+
+def indent(indent: str, text: str, prefix_indent: bool = True) -> str:
+ return (indent if prefix_indent else "") + text.replace("\n", "\n" + indent)
+
+
+def quantify(noun: str, count: int, plural_suffix: str = "s") -> str:
+ if count == 1:
+ return f"{count} {noun}"
+ return f"{count} {noun}{plural_suffix}"
+
+
+if __name__ == "__main__":
+ print_markdown_report()
diff --git a/benchmark/server.py b/benchmark/server.py
deleted file mode 100644
index e7f639eb8..000000000
--- a/benchmark/server.py
+++ /dev/null
@@ -1,121 +0,0 @@
-import io
-import json
-import logging
-import shutil
-from pathlib import Path
-from random import randint
-from typing import Annotated, Any, Dict, List
-
-from fastapi import FastAPI, File, Form, HTTPException, UploadFile
-from fastapi.responses import StreamingResponse
-from pydantic import BaseModel
-
-# Set up logging
-logging.basicConfig(level=logging.INFO)
-logger = logging.getLogger(__name__)
-
-app = FastAPI()
-artifacts: List[Dict[str, Any]] = []
-
-
-class Task(BaseModel):
- input: str
-
-
-@app.post("/agent/tasks/{task_id}/artifacts")
-async def upload_file(
- task_id: str, file: Annotated[UploadFile, File()], relative_path: str = Form("")
-) -> Dict[str, Any]:
- logger.info(
- "Uploading file for task_id: %s with relative path: %s", task_id, relative_path
- )
- absolute_directory_path = Path(__file__).parent.absolute()
- save_path = (
- absolute_directory_path
- / "agent/gpt-engineer"
- / "projects/my-new-project/workspace"
- )
-
- random_string = str(randint(0, 100000))
- while random_string in artifacts:
- random_string = str(randint(0, 100000))
-
- artifact_data = await file.read()
- artifacts.append(
- {
- "binary": artifact_data,
- "relative_path": relative_path,
- "file_name": file.filename,
- "artifact_id": random_string,
- }
- )
-
- print(artifacts)
- return {
- "artifact_id": random_string,
- "file_name": "file_name",
- "relative_path": "relative_path",
- }
-
-
-@app.get("/agent/tasks/{task_id}/artifacts")
-async def get_files() -> List[Dict[str, Any]]:
- logger.info("Fetching list of files for task")
- return artifacts
-
-
-@app.get("/agent/tasks/{task_id}/artifacts/{artifact_id}")
-async def get_file(artifact_id: str):
- for artifact in artifacts:
- if artifact["artifact_id"] == artifact_id:
- break
- else:
- logger.error("Attempt to access nonexistent artifact with ID: %s", artifact_id)
- raise HTTPException(status_code=404, detail="Artifact not found")
-
- logger.info("Fetching artifact with ID: %s", artifact_id)
- # find aritifact where artifact_id = artifact_id
-
- for artifact in artifacts:
- if artifact["artifact_id"] == artifact_id:
- return StreamingResponse(
- io.BytesIO(artifact["binary"]),
- media_type="application/octet-stream",
- headers={"Content-Disposition": f"attachment; filename=test.txt"},
- )
- # return 404
- return HTTPException(status_code=404, detail="Artifact not found")
-
-
-@app.post("/agent/tasks/{task_id}/steps")
-async def create_steps(task_id: str):
- logger.info("Creating step for task_id: %s", task_id)
- return {
- "input": "random",
- "additional_input": {},
- "task_id": task_id,
- "step_id": "random_step",
- "name": "random",
- "status": "created",
- "output": "random",
- "additional_output": {},
- "artifacts": [],
- "is_last": True,
- }
-
-
-@app.post("/agent/tasks")
-async def create_tasks(task: Task):
- artifacts.clear()
- return {
- "input": "random",
- "additional_input": {},
- "task_id": "static_task_id",
- "artifacts": [],
- }
-
-
-if __name__ == "__main__":
- import uvicorn
-
- uvicorn.run(app, host="0.0.0.0", port=8000)
diff --git a/cli.py b/cli.py
index cd18982e9..bd218b103 100644
--- a/cli.py
+++ b/cli.py
@@ -98,14 +98,10 @@ d88P 888 "Y88888 "Y888 "Y88P" "Y8888P88 888 888
)
)
click.echo(
- click.style(
- ' git config --global user.name "Your (user)name"', fg="red"
- )
+ click.style(' git config --global user.name "Your (user)name"', fg="red")
)
click.echo(
- click.style(
- ' git config --global user.email "Your email"', fg="red"
- )
+ click.style(' git config --global user.email "Your email"', fg="red")
)
install_error = True
@@ -181,7 +177,9 @@ d88P 888 "Y88888 "Y888 "Y88P" "Y8888P88 888 888
click.style("\t2. Navigate to https://github.com/settings/tokens", fg="red")
)
click.echo(click.style("\t3. Click on 'Generate new token'.", fg="red"))
- click.echo(click.style("\t4. Click on 'Generate new token (classic)'.", fg="red"))
+ click.echo(
+ click.style("\t4. Click on 'Generate new token (classic)'.", fg="red")
+ )
click.echo(
click.style(
"\t5. Fill out the form to generate a new token. Ensure you select the 'repo' scope.",
@@ -236,7 +234,10 @@ def create(agent_name):
existing_arena_files = [name.lower() for name in os.listdir("./arena/")]
- if not os.path.exists(new_agent_dir) and not new_agent_name in existing_arena_files:
+ if (
+ not os.path.exists(new_agent_dir)
+ and not new_agent_name in existing_arena_files
+ ):
shutil.copytree("./autogpts/forge", new_agent_dir)
click.echo(
click.style(
@@ -271,15 +272,27 @@ def start(agent_name, no_setup):
agent_dir = os.path.join(script_dir, f"autogpts/{agent_name}")
run_command = os.path.join(agent_dir, "run")
run_bench_command = os.path.join(agent_dir, "run_benchmark")
- if os.path.exists(agent_dir) and os.path.isfile(run_command) and os.path.isfile(run_bench_command):
+ if (
+ os.path.exists(agent_dir)
+ and os.path.isfile(run_command)
+ and os.path.isfile(run_bench_command)
+ ):
os.chdir(agent_dir)
if not no_setup:
+ click.echo(f"⌛ Running setup for agent '{agent_name}'...")
setup_process = subprocess.Popen(["./setup"], cwd=agent_dir)
setup_process.wait()
+ click.echo()
+
subprocess.Popen(["./run_benchmark", "serve"], cwd=agent_dir)
- click.echo(f"Benchmark Server starting please wait...")
+ click.echo("⌛ (Re)starting benchmark server...")
+ wait_until_conn_ready(8080)
+ click.echo()
+
subprocess.Popen(["./run"], cwd=agent_dir)
- click.echo(f"Agent '{agent_name}' starting please wait...")
+ click.echo(f"⌛ (Re)starting agent '{agent_name}'...")
+ wait_until_conn_ready(8000)
+ click.echo("✅ Agent application started and available on port 8000")
elif not os.path.exists(agent_dir):
click.echo(
click.style(
@@ -323,6 +336,7 @@ def stop():
except subprocess.CalledProcessError:
click.echo("No process is running on port 8080")
+
@agent.command()
def list():
"""List agents command"""
@@ -409,7 +423,7 @@ def benchmark_categories_list():
)
# Use it as the base for the glob pattern, excluding 'deprecated' directory
for data_file in glob.glob(glob_path, recursive=True):
- if 'deprecated' not in data_file:
+ if "deprecated" not in data_file:
with open(data_file, "r") as f:
try:
data = json.load(f)
@@ -453,7 +467,7 @@ def benchmark_tests_list():
)
# Use it as the base for the glob pattern, excluding 'deprecated' directory
for data_file in glob.glob(glob_path, recursive=True):
- if 'deprecated' not in data_file:
+ if "deprecated" not in data_file:
with open(data_file, "r") as f:
try:
data = json.load(f)
@@ -590,6 +604,7 @@ def benchmark_tests_details(test_name):
print(f"IOError: file could not be read: {data_file}")
continue
+
@cli.group()
def arena():
"""Commands to enter the arena"""
@@ -752,7 +767,7 @@ def enter(agent_name, branch):
# Create a PR into the parent repository
g = Github(github_access_token)
- repo_name = github_repo_url.replace("https://github.com/", '')
+ repo_name = github_repo_url.replace("https://github.com/", "")
repo = g.get_repo(repo_name)
parent_repo = repo.parent
if parent_repo:
@@ -830,8 +845,8 @@ Hey there amazing builders! We're thrilled to have you join this exciting journe
def update(agent_name, hash, branch):
import json
import os
- from datetime import datetime
import subprocess
+ from datetime import datetime
# Check if the agent_name.json file exists in the arena directory
agent_json_file = f"./arena/{agent_name}.json"
@@ -889,5 +904,30 @@ def update(agent_name, hash, branch):
)
)
+
+def wait_until_conn_ready(port: int = 8000, timeout: int = 30):
+ """
+ Polls localhost:{port} until it is available for connections
+
+ Params:
+ port: The port for which to wait until it opens
+ timeout: Timeout in seconds; maximum amount of time to wait
+
+ Raises:
+ TimeoutError: If the timeout (seconds) expires before the port opens
+ """
+ import socket
+ import time
+
+ start = time.time()
+ while True:
+ time.sleep(0.5)
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+ if s.connect_ex(("localhost", port)) == 0:
+ break
+ if time.time() > start + timeout:
+ raise TimeoutError(f"Port {port} did not open within {timeout} seconds")
+
+
if __name__ == "__main__":
cli()
diff --git a/docs/content/AutoGPT/configuration/options.md b/docs/content/AutoGPT/configuration/options.md
index 12df23c33..dd0291bfa 100644
--- a/docs/content/AutoGPT/configuration/options.md
+++ b/docs/content/AutoGPT/configuration/options.md
@@ -14,10 +14,10 @@ Configuration is controlled through the `Config` object. You can set configurati
- `DISABLED_COMMAND_CATEGORIES`: Command categories to disable. Command categories are Python module names, e.g. autogpt.commands.execute_code. See the directory `autogpt/commands` in the source for all command modules. Default: None
- `ELEVENLABS_API_KEY`: ElevenLabs API Key. Optional.
- `ELEVENLABS_VOICE_ID`: ElevenLabs Voice ID. Optional.
-- `EMBEDDING_MODEL`: LLM Model to use for embedding tasks. Default: text-embedding-ada-002
+- `EMBEDDING_MODEL`: LLM Model to use for embedding tasks. Default: `text-embedding-3-small`
- `EXECUTE_LOCAL_COMMANDS`: If shell commands should be executed locally. Default: False
- `EXIT_KEY`: Exit key accepted to exit. Default: n
-- `FAST_LLM`: LLM Model to use for most tasks. Default: gpt-3.5-turbo
+- `FAST_LLM`: LLM Model to use for most tasks. Default: `gpt-3.5-turbo-0125`
- `GITHUB_API_KEY`: [Github API Key](https://github.com/settings/tokens). Optional.
- `GITHUB_USERNAME`: GitHub Username. Optional.
- `GOOGLE_API_KEY`: Google API key. Optional.
@@ -44,7 +44,7 @@ Configuration is controlled through the `Config` object. You can set configurati
- `SHELL_ALLOWLIST`: List of shell commands that ARE allowed to be executed by AutoGPT. Only applies if `SHELL_COMMAND_CONTROL` is set to `allowlist`. Default: None
- `SHELL_COMMAND_CONTROL`: Whether to use `allowlist` or `denylist` to determine what shell commands can be executed (Default: denylist)
- `SHELL_DENYLIST`: List of shell commands that ARE NOT allowed to be executed by AutoGPT. Only applies if `SHELL_COMMAND_CONTROL` is set to `denylist`. Default: sudo,su
-- `SMART_LLM`: LLM Model to use for "smart" tasks. Default: gpt-4
+- `SMART_LLM`: LLM Model to use for "smart" tasks. Default: `gpt-4-turbo-preview`
- `STREAMELEMENTS_VOICE`: StreamElements voice to use. Default: Brian
- `TEMPERATURE`: Value of temperature given to OpenAI. Value from 0 to 2. Lower is more deterministic, higher is more random. See https://platform.openai.com/docs/api-reference/completions/create#completions/create-temperature
- `TEXT_TO_SPEECH_PROVIDER`: Text to Speech Provider. Options are `gtts`, `macos`, `elevenlabs`, and `streamelements`. Default: gtts
diff --git a/docs/content/AutoGPT/setup/docker.md b/docs/content/AutoGPT/setup/docker.md
index 35bd7c2c1..af4794a25 100644
--- a/docs/content/AutoGPT/setup/docker.md
+++ b/docs/content/AutoGPT/setup/docker.md
@@ -124,10 +124,7 @@ found in the [repository].
If you want to use GPT on an Azure instance, set `USE_AZURE` to `True` and
make an Azure configuration file:
- - Rename `azure.yaml.template` to `azure.yaml` and provide the relevant `azure_api_base`, `azure_api_version` and all the deployment IDs for the relevant models in the `azure_model_map` section:
- - `fast_llm_deployment_id`: your gpt-3.5-turbo or gpt-4 deployment ID
- - `smart_llm_deployment_id`: your gpt-4 deployment ID
- - `embedding_model_deployment_id`: your text-embedding-ada-002 v2 deployment ID
+ - Rename `azure.yaml.template` to `azure.yaml` and provide the relevant `azure_api_base`, `azure_api_version` and all the deployment IDs for the relevant models in the `azure_model_map` section.
Example:
@@ -135,7 +132,7 @@ found in the [repository].
# Please specify all of these values as double-quoted strings
# Replace string in angled brackets (<>) to your own deployment Name
azure_model_map:
- fast_llm_deployment_id: "<auto-gpt-deployment>"
+ gpt-4-turbo-preview: "<gpt-4-turbo deployment ID>"
...
```
diff --git a/docs/content/AutoGPT/usage.md b/docs/content/AutoGPT/usage.md
index 4ab752dcf..09447f03d 100644
--- a/docs/content/AutoGPT/usage.md
+++ b/docs/content/AutoGPT/usage.md
@@ -115,7 +115,7 @@ To exit the program, press ++ctrl+c++
### `serve` &ndash; Agent Protocol mode with UI
With `serve`, the application exposes an Agent Protocol compliant API and serves a
-frontend, by default on `http://localhost:8000`.
+frontend, by default on `http://localhost:8000`. You can configure the port it is served on with the `AP_SERVER_PORT` environment variable.
<details>
<summary>
diff --git a/docs/content/forge/get-started.md b/docs/content/forge/get-started.md
index f1ca63e17..ca5af2b07 100644
--- a/docs/content/forge/get-started.md
+++ b/docs/content/forge/get-started.md
@@ -2,6 +2,9 @@
### 🛠️ Build your own Agent 🛠️
+!!! warning
+ If you are trying to use AutoGPT this is not the tutorial for you! You need to use [this one](../../AutoGPT/setup/)
+
Forge is a ready-to-go template for *your* agent application. All the boilerplate code is already handled, letting you channel all your creativity into the things that set *your* agent apart.
---
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index 3628df6c7..49605461b 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -127,5 +127,5 @@ extra_javascript:
- https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js
- _javascript/tablesort.js
- _javascript/mathjax.js
- - https://polyfill.io/v3/polyfill.min.js?features=es6
+ - https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=es6
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
diff --git a/docs/netlify.toml b/docs/netlify.toml
index 5a3348c9d..e542e1824 100644
--- a/docs/netlify.toml
+++ b/docs/netlify.toml
@@ -3,4 +3,4 @@
[build]
publish = "public/"
command = "mkdocs build -d public"
- ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF docs mkdocs.yml CONTRIBUTING.md CODE_OF_CONDUCT.md LICENSE"
+ ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF . ../CONTRIBUTING.md ../CODE_OF_CONDUCT.md"
diff --git a/frontend/lib/views/chat/chat_input_field.dart b/frontend/lib/views/chat/chat_input_field.dart
index b46badd61..63afa2319 100644
--- a/frontend/lib/views/chat/chat_input_field.dart
+++ b/frontend/lib/views/chat/chat_input_field.dart
@@ -116,6 +116,11 @@ class _ChatInputFieldState extends State<ChatInputField> {
child: TextField(
controller: _controller,
focusNode: _focusNode,
+ // Enable enter key stroke to send the message
+ onSubmitted: (_) {
+ widget.onSendPressed(_controller.text);
+ _controller.clear();
+ },
// Allowing the TextField to expand vertically and accommodate multiple lines
maxLines: null,
decoration: InputDecoration(