mirror of
https://github.com/trailofbits/buttercup
synced 2026-06-21 14:11:39 +00:00
Standardize Python packaging and project configuration (#285)
* fix: respect OSS_FUZZ_CONTAINER_ORG environment variable The oss_fuzz_container_org property now checks the OSS_FUZZ_CONTAINER_ORG environment variable first before falling back to parsing the helper file. This fixes the failing test_container_image_custom_org integration test that was caught in nightly CI. The test was expecting that setting OSS_FUZZ_CONTAINER_ORG=myorg would result in container images using that organization, but the code was ignoring the environment variable entirely. * fix: standardize Python packaging and project configuration - Fix critical Python version inconsistency (common was 3.10+, dependents required 3.12+) - Standardize project metadata: add descriptions, licenses, consistent author emails - Implement consistent dependency management using compatible release (~=) strategy - Modernize all components to use [project.optional-dependencies] instead of [dependency-groups] - Restore essential tool configurations (ruff lint rules, pytest settings, coverage config) - Remove redundant component Makefiles (orchestrator, program-model) - Add project URLs for better package discoverability This resolves packaging inconsistencies introduced in PR #271 while maintaining modern Python packaging standards. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: restore accidentally removed Makefiles with unique functionality - Restore orchestrator/Makefile: contains unique API management targets (update-apis, generate-competition-api) - Restore program-model/Makefile: contains specific integration test commands not in root Makefile - These Makefiles provide component-specific functionality not available elsewhere * fix: standardize program-model Dockerfile to use Python 3.12 Ensures consistency with pyproject.toml requirement of Python >=3.12,<3.13. This aligns with the other components and standardizes Python version across all Dockerfiles in the project. * refactor: improve Dockerfile consistency and layer caching - Combine consecutive apt operations to reduce layers - Add missing DEBIAN_FRONTEND=noninteractive declarations - Ensure all apt operations include cleanup with rm -rf /var/lib/apt/lists/* - Reduces image size and improves build consistency * fix: use [dependency-groups] instead of [project.optional-dependencies] Addresses reviewer feedback that [dependency-groups] is the semantically correct approach for development dependencies like test, lint, and typing tools. Per PEP 735 and packaging.python.org guidance: - [dependency-groups] for development workflow dependencies - [project.optional-dependencies] for optional user-facing features This standardizes all components to use the modern PEP 735 approach. * fix: move dependencies from [project.urls] to [project] section Fixes TOML syntax error where dependencies array was incorrectly placed under [project.urls] instead of [project], causing build failures: 'TypeError: URL of field must be a string' This resolves CI failures across all components during uv sync. * fix: temporarily disable ruff rules to resolve CI failures Temporarily disabled the following ruff rules for standardization PR: - I001: Import block is un-sorted or un-formatted - E501: Line too long - W291: Trailing whitespace - UP006: Use built-in collection types for type annotations - UP015: Unnecessary mode argument - UP035: Import from modern locations instead of deprecated typing - UP046: Use modern generic class syntax These rules were disabled in common/ and fuzzer/ components where they were causing CI failures. Rules are commented with intention to re-enable after refactoring work is complete. Also fixed ruff formatting issues in seed-gen component. * refactor: simplify dependency groups per maintainer feedback Address maintainer feedback by consolidating dependency groups: - Combined dev/test/typing/lint groups into single practical 'dev' group - Ensures mypy gets all required type stubs (no more missing dependencies) - Eliminates duplication and reduces cognitive overhead - Users now only need: uv sync --group dev Also removed pytest configuration from common/ as requested, since most settings were defaults and only existed in one component. Changes provide better developer experience with simpler, working dependency management. * fix: add missing UP045 rule to ruff ignore lists Addresses CI failure: 'UP045 Use X | None for type annotations' Added UP045 to ruff ignore lists in: - common/pyproject.toml - fuzzer/pyproject.toml - orchestrator/pyproject.toml - seed-gen/pyproject.toml This completes the temporary rule disabling for the standardization PR. UP045 enforces modern union syntax (X | None vs Optional[X]) - will re-enable after refactoring. * fix: correct argon2-cffi version constraint in orchestrator Changes argon2-cffi from ~=21.0.0 to ~=21.3.0 to resolve dependency resolution failure. Version 21.0.0 never existed on PyPI - available versions jump from 20.1.0 directly to 21.1.0. This restores the previously working constraint and resolves: 'No solution found when resolving dependencies: argon2-cffi>=21.0.0,<21.1.dev0' * chore: update mypy to latest version 1.17.1 Updates mypy from 1.15.0 to 1.17.1 across all components to ensure we're using the latest type checker features and bug fixes. ruff is already on the latest version (0.12.8). This keeps the linting tools current and prevents them from becoming outdated over time. * fix: add necessary ruff ignore rules to orchestrator Add the specific ruff rules that orchestrator needs disabled based on CI lint failures. Other components passed linting, so only orchestrator needs these additional rules. Rules added: - I001: Import block formatting - E501: Line too long - UP006: Built-in collection types - UP007: Union type annotations - UP009: UTF-8 encoding declarations - UP015: Unnecessary mode argument - UP035: Modern import locations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: add missing ruff config and project metadata - Add ruff configuration to program-model for consistency - Add project URLs to 4 components for discoverability - Add types-redis to fuzzer dev dependencies for type checking - Ensure all components have consistent ignore rules * fix: add additional ruff ignore rules for patcher and program-model - Add W293, UP012, UP031 to patcher ignore list - Add UP032 to program-model ignore list - Ensures ruff checks pass for both components * fix: resolve ruff formatting and dependency issues - Format all program-model files with ruff (28 files reformatted) - Standardize patcher dependencies to use ~= version specifiers - Update langgraph-checkpoint to ~=2.1.0 to resolve conflicts - Fix Docker PYTHON_VERSION variable usage in patcher/Dockerfile - Update patcher lock file with new dependency constraints * Update tree-sitter-language-pack and refresh uv.lock --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Michael D Brown <michael.brown@trailofbits.com> Co-authored-by: Riccardo Schirone <riccardo.schirone@trailofbits.com>
This commit is contained in:
+68
-21
@@ -1,24 +1,29 @@
|
||||
[project]
|
||||
name = "common"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = [{ name = "Trail of Bits", email = "opensource@trailofbits" }]
|
||||
requires-python = ">=3.10,<3.13"
|
||||
description = "Shared utilities and components for Buttercup CRS"
|
||||
authors = [{ name = "Trail of Bits", email = "opensource@trailofbits.com" }]
|
||||
license = "AGPL-3.0-only"
|
||||
requires-python = ">=3.12,<3.13"
|
||||
dependencies = [
|
||||
"protobuf (>=3.20, <=3.20.3)",
|
||||
"pydantic-settings>=2.7.1",
|
||||
"pymongo>=4.10.1",
|
||||
"redis (>=5.2.1,<6.0.0)",
|
||||
"langchain-core~=0.3.32",
|
||||
"langchain-openai~=0.3.2",
|
||||
"langfuse ~= 2.59.2",
|
||||
"langchain ~= 0.3.18",
|
||||
"six>=1.17.0",
|
||||
"openlit == 1.32.12", # 1.33 currently fails to import opentelemetry.sdk._events
|
||||
"langchain-community ~= 0.3.20", # implicit dep of openlit if you instrument langchain
|
||||
"langchain-text-splitters ~= 0.3.7", # implicit dep of openlit if you instrument langchain
|
||||
"protobuf ==3.20.3", # Pin exactly for stability
|
||||
"pydantic-settings ~=2.7.1",
|
||||
"pymongo ~=4.10.1",
|
||||
"redis ~=5.2.1",
|
||||
"langchain-core ~=0.3.32",
|
||||
"langchain-openai ~=0.3.2",
|
||||
"langfuse ~=2.59.2",
|
||||
"langchain ~=0.3.18",
|
||||
"six ~=1.17.0",
|
||||
"openlit ==1.32.12", # 1.33 currently fails to import opentelemetry.sdk._events
|
||||
"langchain-community ~=0.3.20", # implicit dep of openlit if you instrument langchain
|
||||
"langchain-text-splitters ~=0.3.7", # implicit dep of openlit if you instrument langchain
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/trailofbits/buttercup"
|
||||
Issues = "https://github.com/trailofbits/buttercup/issues"
|
||||
|
||||
[project.scripts]
|
||||
buttercup-util = "buttercup.common.util_cli:main"
|
||||
buttercup-challenge-task = "buttercup.common.challenge_task_cli:main"
|
||||
@@ -34,17 +39,22 @@ build-backend = "hatchling.build"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=8.3.4",
|
||||
"ruff>=0.9.2",
|
||||
"mypy>=1.15.0",
|
||||
"types-requests",
|
||||
# Testing tools
|
||||
"pytest ~=8.3.4",
|
||||
"pytest-cov ~=6.0.0",
|
||||
"dirty-equals ~=0.9.0",
|
||||
# Linting and type checking
|
||||
"ruff ~=0.12.8",
|
||||
"mypy ~=1.17.1",
|
||||
# Type stubs
|
||||
"types-requests ~=2.32.0",
|
||||
"types-PyYAML",
|
||||
"types-redis",
|
||||
"dirty-equals>=0.9.0",
|
||||
"types-redis ~=4.6.0",
|
||||
]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
target-version = "py312"
|
||||
exclude = [
|
||||
"./src/buttercup/common/datastructures",
|
||||
"./src/buttercup/common/clusterfuzz_env",
|
||||
@@ -52,6 +62,43 @@ exclude = [
|
||||
"src/buttercup/common/clusterfuzz_utils.py",
|
||||
]
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "I", "W", "UP"]
|
||||
ignore = [
|
||||
"COM812", "ISC001", # Formatter conflicts
|
||||
# Temporarily disabled for standardization PR - re-enable after refactoring:
|
||||
"I001", # Import block is un-sorted or un-formatted
|
||||
"E501", # Line too long
|
||||
"W291", # Trailing whitespace
|
||||
"UP006", # Use built-in collection types for type annotations
|
||||
"UP015", # Unnecessary mode argument
|
||||
"UP035", # Import from modern locations instead of deprecated typing
|
||||
"UP045", # Use X | None for type annotations
|
||||
"UP046", # Use modern generic class syntax
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"tests/**/*.py" = ["S101", "D"] # Allow asserts, no docstrings in tests
|
||||
"*/__cli__.py" = ["T201"] # Allow print in CLI modules
|
||||
"*/util_cli.py" = ["T201"]
|
||||
"*/challenge_task_cli.py" = ["T201"]
|
||||
"*/task_registry.py" = ["T201"]
|
||||
"src/buttercup/common/node_local.py" = ["UP040"] # PEP 695 type aliases break runtime usage as constructors
|
||||
|
||||
|
||||
[tool.coverage.run]
|
||||
source = ["src/buttercup"]
|
||||
omit = ["*/tests/*", "*/__cli__.py", "*/_cli.py", "*/util_cli.py", "*/challenge_task_cli.py", "*/task_registry.py"]
|
||||
|
||||
[tool.coverage.report]
|
||||
exclude_lines = [
|
||||
"pragma: no cover",
|
||||
"def __repr__",
|
||||
"if __name__ == .__main__.:",
|
||||
"raise NotImplementedError",
|
||||
"if TYPE_CHECKING:",
|
||||
]
|
||||
|
||||
[tool.mypy]
|
||||
plugins = ["pydantic.mypy"]
|
||||
mypy_path = "src"
|
||||
|
||||
@@ -453,6 +453,10 @@ class ChallengeTask:
|
||||
|
||||
@cached_property
|
||||
def oss_fuzz_container_org(self) -> str:
|
||||
# Check environment variable first
|
||||
if env_org := os.environ.get("OSS_FUZZ_CONTAINER_ORG"):
|
||||
return env_org
|
||||
|
||||
# Read the helper_path file and grep for the BASE_RUNNER_IMAGE line.
|
||||
result = "gcr.io/oss-fuzz"
|
||||
try:
|
||||
|
||||
Generated
+98
-749
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ ENV UV_LINK_MODE=copy
|
||||
ENV UV_COMPILE_BYTECODE=1
|
||||
ENV UV_PYTHON_DOWNLOADS=manual
|
||||
|
||||
RUN uv python install python3.10
|
||||
RUN uv python install python3.12
|
||||
|
||||
FROM base-image AS runner-base
|
||||
RUN apt-get update
|
||||
|
||||
+43
-10
@@ -1,19 +1,24 @@
|
||||
[project]
|
||||
name = "fuzzing-infra"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = [{ name = "Trail of Bits", email = "opensource@trailofbits" }]
|
||||
requires-python = ">=3.10,<3.13"
|
||||
description = "Automated vulnerability discovery and fuzzing infrastructure"
|
||||
authors = [{ name = "Trail of Bits", email = "opensource@trailofbits.com" }]
|
||||
license = "AGPL-3.0-only"
|
||||
requires-python = ">=3.12,<3.13"
|
||||
dependencies = [
|
||||
"protobuf (>=3.20, <=3.20.3)",
|
||||
"redis (>=5.2.1,<6.0.0)",
|
||||
"clusterfuzz==2.6.0",
|
||||
"protobuf ==3.20.3", # Pin exactly for stability
|
||||
"redis ~=5.2.1",
|
||||
"clusterfuzz ==2.6.0", # Pin exactly for stability
|
||||
"common",
|
||||
"pydantic-settings>=2.7.1",
|
||||
"beautifulsoup4>=4.13.3",
|
||||
"lxml>=5.3.1",
|
||||
"pydantic-settings ~=2.7.1",
|
||||
"beautifulsoup4 ~=4.13.3",
|
||||
"lxml ~=5.3.1",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/trailofbits/buttercup"
|
||||
Issues = "https://github.com/trailofbits/buttercup/issues"
|
||||
|
||||
[project.scripts]
|
||||
buttercup-fuzzer-builder = "buttercup.fuzzing_infra.builder_bot:main"
|
||||
buttercup-fuzzer = "buttercup.fuzzing_infra.fuzzer_bot:main"
|
||||
@@ -34,10 +39,38 @@ requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[dependency-groups]
|
||||
dev = ["pytest>=8.3.4", "ruff>=0.9.2", "mypy>=1.15.0"]
|
||||
dev = [
|
||||
# Testing tools
|
||||
"pytest ~=8.3.4",
|
||||
"pytest-cov ~=6.0.0",
|
||||
# Linting and type checking
|
||||
"ruff ~=0.12.8",
|
||||
"mypy ~=1.17.1",
|
||||
# Type stubs
|
||||
"types-redis ~=4.6.0",
|
||||
]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
target-version = "py312"
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "I", "W", "UP"]
|
||||
ignore = [
|
||||
"COM812", "ISC001", # Formatter conflicts
|
||||
# Temporarily disabled for standardization PR - re-enable after refactoring:
|
||||
"I001", # Import block is un-sorted or un-formatted
|
||||
"E501", # Line too long
|
||||
"W291", # Trailing whitespace
|
||||
"UP006", # Use built-in collection types for type annotations
|
||||
"UP015", # Unnecessary mode argument
|
||||
"UP035", # Import from modern locations instead of deprecated typing
|
||||
"UP045", # Use X | None for type annotations
|
||||
"UP046", # Use modern generic class syntax
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"tests/**/*.py" = ["S101", "D"] # Allow asserts, no docstrings in tests
|
||||
|
||||
[tool.mypy]
|
||||
plugins = ["pydantic.mypy"]
|
||||
|
||||
Generated
+210
-797
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,7 @@
|
||||
|
||||
update-apis:
|
||||
@echo "Updating Competition/CRS APIs..."
|
||||
@./scripts/update_apis.sh $(shell pwd)
|
||||
|
||||
generate-competition-api:
|
||||
@echo "Generating FastAPI Competition API skeleton..."
|
||||
@./scripts/generate_competition_api.sh $(shell pwd)
|
||||
@./scripts/generate_competition_api.sh $(shell pwd)
|
||||
+57
-28
@@ -4,24 +4,29 @@ version = "0.5.0"
|
||||
description = "Buttercup orchestrator"
|
||||
readme = "README.md"
|
||||
authors = [{ name = "Trail of Bits", email = "opensource@trailofbits.com" }]
|
||||
license = "AGPL-3.0-only"
|
||||
requires-python = ">=3.12,<3.13"
|
||||
dependencies = [
|
||||
"argon2-cffi>=21.0.0",
|
||||
"argon2-cffi ~=21.3.0",
|
||||
"common",
|
||||
"fastapi>=0.115.6",
|
||||
"pydantic>=2.10.5",
|
||||
"pydantic-settings>=2.7.1",
|
||||
"python-dateutil>=2.9.0.post0",
|
||||
"pyyaml>=6.0.1",
|
||||
"requests>=2.32.3",
|
||||
"requests-file>=2.1.0",
|
||||
"rich>=13.9.4",
|
||||
"sqlalchemy>=2.0.0",
|
||||
"typing-extensions>=4.12.2",
|
||||
"urllib3>=2.3.0",
|
||||
"uvicorn>=0.34.0",
|
||||
"fastapi ~=0.115.6",
|
||||
"pydantic ~=2.10.5",
|
||||
"pydantic-settings ~=2.7.1",
|
||||
"python-dateutil ~=2.9.0",
|
||||
"pyyaml ~=6.0.1",
|
||||
"requests ~=2.32.3",
|
||||
"requests-file ~=2.1.0",
|
||||
"rich ~=13.9.4",
|
||||
"sqlalchemy ~=2.0.0",
|
||||
"typing-extensions ~=4.12.2",
|
||||
"urllib3 ~=2.3.0",
|
||||
"uvicorn ~=0.34.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/trailofbits/buttercup"
|
||||
Issues = "https://github.com/trailofbits/buttercup/issues"
|
||||
|
||||
[project.scripts]
|
||||
buttercup-task-server = "buttercup.orchestrator.task_server.__cli__:main"
|
||||
buttercup-task-downloader = "buttercup.orchestrator.downloader.__cli__:main"
|
||||
@@ -32,21 +37,23 @@ buttercup-scratch-cleaner = "buttercup.orchestrator.scratch_cleaner.__cli__:main
|
||||
buttercup-ui = "buttercup.orchestrator.ui.__cli__:main"
|
||||
|
||||
|
||||
[project.optional-dependencies]
|
||||
tests = [
|
||||
"flake8>=7.1.1",
|
||||
"mypy>=1.15.0",
|
||||
"pytest>=8.3.4",
|
||||
"pytest-asyncio>=0.25.2",
|
||||
"pytest-cov>=6.0.0",
|
||||
"pytest-xdist>=3.6.1",
|
||||
"ruff>=0.9.2",
|
||||
"types-python-dateutil>=2.9.0.20241206",
|
||||
"types-requests>=2.32.0",
|
||||
"types-redis>=4.6.0",
|
||||
"fastapi[standard]>=0.115.6",
|
||||
"responses>=0.25.6",
|
||||
"httpx>=0.28.1",
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
# Testing tools
|
||||
"pytest ~=8.3.4",
|
||||
"pytest-asyncio ~=0.25.2",
|
||||
"pytest-cov ~=6.0.0",
|
||||
"pytest-xdist ~=3.6.1",
|
||||
"fastapi[standard] ~=0.115.6",
|
||||
"responses ~=0.25.6",
|
||||
"httpx ~=0.28.1",
|
||||
# Linting and type checking
|
||||
"ruff ~=0.12.8",
|
||||
"mypy ~=1.17.1",
|
||||
# Type stubs
|
||||
"types-python-dateutil ~=2.9.0.20241206",
|
||||
"types-requests ~=2.32.0",
|
||||
"types-redis ~=4.6.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
@@ -61,6 +68,7 @@ common = { path = "../common", editable = true }
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
target-version = "py312"
|
||||
exclude = [
|
||||
"src/buttercup/orchestrator/competition_api_client",
|
||||
"test/test_types_*.py",
|
||||
@@ -70,6 +78,27 @@ exclude = [
|
||||
"src/buttercup/orchestrator/task_server/models/",
|
||||
]
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "I", "W", "UP"]
|
||||
ignore = [
|
||||
"COM812", "ISC001", # Formatter conflicts
|
||||
# Temporarily disabled for standardization PR - re-enable after refactoring:
|
||||
"I001", # Import block is un-sorted or un-formatted
|
||||
"E501", # Line too long
|
||||
"UP006", # Use built-in collection types for type annotations
|
||||
"UP007", # Use X | Y for type annotations
|
||||
"UP009", # UTF-8 encoding declaration is unnecessary
|
||||
"UP015", # Unnecessary mode argument
|
||||
"UP035", # Import from modern locations instead of deprecated typing
|
||||
"UP045", # Use X | None for type annotations
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"tests/**/*.py" = ["S101", "D"] # Allow asserts, no docstrings in tests
|
||||
"test/test_submissions.py" = ["S101", "D", "UP045"] # UP045: Protobuf enums don't support | operator
|
||||
"*/__cli__.py" = ["T201"] # Allow print in CLI modules
|
||||
"*/auth_tool.py" = ["T201"]
|
||||
|
||||
[tool.mypy]
|
||||
plugins = ["pydantic.mypy"]
|
||||
mypy_path = "src"
|
||||
|
||||
Generated
+138
-204
@@ -101,14 +101,14 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "argon2-cffi"
|
||||
version = "25.1.0"
|
||||
version = "21.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "argon2-cffi-bindings" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3f/18/20bb5b6bf55e55d14558b57afc3d4476349ab90e0c43e60f27a7c2187289/argon2-cffi-21.3.0.tar.gz", hash = "sha256:d384164d944190a7dd7ef22c6aa3ff197da12962bd04b17f64d4e93d934dba5b", size = 38446, upload-time = "2021-12-11T11:47:50.012Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/07/946d5a9431bae05a776a59746ec385fbb79b526738d25e4202d3e0bbf7f4/argon2_cffi-21.3.0-py3-none-any.whl", hash = "sha256:8c976986f2c5c0e5000919e6de187906cfd81fb1c72bf9d88c01177e77da7f80", size = 14443, upload-time = "2021-12-11T11:47:48.265Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -280,22 +280,23 @@ requires-dist = [
|
||||
{ name = "langchain-text-splitters", specifier = "~=0.3.7" },
|
||||
{ name = "langfuse", specifier = "~=2.59.2" },
|
||||
{ name = "openlit", specifier = "==1.32.12" },
|
||||
{ name = "protobuf", specifier = ">=3.20,<=3.20.3" },
|
||||
{ name = "pydantic-settings", specifier = ">=2.7.1" },
|
||||
{ name = "pymongo", specifier = ">=4.10.1" },
|
||||
{ name = "redis", specifier = ">=5.2.1,<6.0.0" },
|
||||
{ name = "six", specifier = ">=1.17.0" },
|
||||
{ name = "protobuf", specifier = "==3.20.3" },
|
||||
{ name = "pydantic-settings", specifier = "~=2.7.1" },
|
||||
{ name = "pymongo", specifier = "~=4.10.1" },
|
||||
{ name = "redis", specifier = "~=5.2.1" },
|
||||
{ name = "six", specifier = "~=1.17.0" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "dirty-equals", specifier = ">=0.9.0" },
|
||||
{ name = "mypy", specifier = ">=1.15.0" },
|
||||
{ name = "pytest", specifier = ">=8.3.4" },
|
||||
{ name = "ruff", specifier = ">=0.9.2" },
|
||||
{ name = "dirty-equals", specifier = "~=0.9.0" },
|
||||
{ name = "mypy", specifier = "~=1.17.1" },
|
||||
{ name = "pytest", specifier = "~=8.3.4" },
|
||||
{ name = "pytest-cov", specifier = "~=6.0.0" },
|
||||
{ name = "ruff", specifier = "~=0.12.8" },
|
||||
{ name = "types-pyyaml" },
|
||||
{ name = "types-redis" },
|
||||
{ name = "types-requests" },
|
||||
{ name = "types-redis", specifier = "~=4.6.0" },
|
||||
{ name = "types-requests", specifier = "~=2.32.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -420,16 +421,16 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "fastapi"
|
||||
version = "0.116.0"
|
||||
version = "0.115.14"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "starlette" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/20/38/e1da78736143fd885c36213a3ccc493c384ae8fea6a0f0bc272ef42ebea8/fastapi-0.116.0.tar.gz", hash = "sha256:80dc0794627af0390353a6d1171618276616310d37d24faba6648398e57d687a", size = 296518, upload-time = "2025-07-07T15:09:27.82Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ca/53/8c38a874844a8b0fa10dd8adf3836ac154082cf88d3f22b544e9ceea0a15/fastapi-0.115.14.tar.gz", hash = "sha256:b1de15cdc1c499a4da47914db35d0e4ef8f1ce62b624e94e0e5824421df99739", size = 296263, upload-time = "2025-06-26T15:29:08.21Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/68/d80347fe2360445b5f58cf290e588a4729746e7501080947e6cdae114b1f/fastapi-0.116.0-py3-none-any.whl", hash = "sha256:fdcc9ed272eaef038952923bef2b735c02372402d1203ee1210af4eea7a78d2b", size = 95625, upload-time = "2025-07-07T15:09:26.348Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/50/b1222562c6d270fea83e9c9075b8e8600b8479150a18e4516a6138b980d1/fastapi-0.115.14-py3-none-any.whl", hash = "sha256:6c0c8bf9420bd58f565e585036d971872472b4f7d3f6c73b698e10cffdefb3ca", size = 95514, upload-time = "2025-06-26T15:29:06.49Z" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
@@ -489,20 +490,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flake8"
|
||||
version = "7.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mccabe" },
|
||||
{ name = "pycodestyle" },
|
||||
{ name = "pyflakes" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9b/af/fbfe3c4b5a657d79e5c47a2827a362f9e1b763336a52f926126aa6dc7123/flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872", size = 48326, upload-time = "2025-06-20T19:31:35.838Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e", size = 57922, upload-time = "2025-06-20T19:31:34.425Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "frozenlist"
|
||||
version = "1.7.0"
|
||||
@@ -936,15 +923,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/34/75/51952c7b2d3873b44a0028b1bd26a25078c18f92f256608e8d1dc61b39fd/marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", size = 50878, upload-time = "2025-02-03T15:32:22.295Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mccabe"
|
||||
version = "0.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mdurl"
|
||||
version = "0.1.2"
|
||||
@@ -983,22 +961,22 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "mypy"
|
||||
version = "1.16.1"
|
||||
version = "1.17.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mypy-extensions" },
|
||||
{ name = "pathspec" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8e/22/ea637422dedf0bf36f3ef238eab4e455e2a0dcc3082b5cc067615347ab8e/mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01", size = 3352570, upload-time = "2025-07-31T07:54:19.204Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/a2/7034d0d61af8098ec47902108553122baa0f438df8a713be860f7407c9e6/mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb", size = 11086295, upload-time = "2025-07-31T07:53:28.124Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/1f/19e7e44b594d4b12f6ba8064dbe136505cec813549ca3e5191e40b1d3cc2/mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403", size = 10112355, upload-time = "2025-07-31T07:53:21.121Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/69/baa33927e29e6b4c55d798a9d44db5d394072eef2bdc18c3e2048c9ed1e9/mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056", size = 11875285, upload-time = "2025-07-31T07:53:55.293Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/13/f3a89c76b0a41e19490b01e7069713a30949d9a6c147289ee1521bcea245/mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341", size = 12737895, upload-time = "2025-07-31T07:53:43.623Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/a1/c4ee79ac484241301564072e6476c5a5be2590bc2e7bfd28220033d2ef8f/mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb", size = 12931025, upload-time = "2025-07-31T07:54:17.125Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/b8/7409477be7919a0608900e6320b155c72caab4fef46427c5cc75f85edadd/mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19", size = 9584664, upload-time = "2025-07-31T07:54:12.842Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/f3/8fcd2af0f5b806f6cf463efaffd3c9548a28f84220493ecd38d127b6b66d/mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9", size = 2283411, upload-time = "2025-07-31T07:53:24.664Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1220,10 +1198,9 @@ dependencies = [
|
||||
{ name = "uvicorn" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
tests = [
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "fastapi", extra = ["standard"] },
|
||||
{ name = "flake8" },
|
||||
{ name = "httpx" },
|
||||
{ name = "mypy" },
|
||||
{ name = "pytest" },
|
||||
@@ -1239,35 +1216,37 @@ tests = [
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "argon2-cffi", specifier = ">=21.0.0" },
|
||||
{ name = "argon2-cffi", specifier = "~=21.3.0" },
|
||||
{ name = "common", editable = "../common" },
|
||||
{ name = "fastapi", specifier = ">=0.115.6" },
|
||||
{ name = "fastapi", extras = ["standard"], marker = "extra == 'tests'", specifier = ">=0.115.6" },
|
||||
{ name = "flake8", marker = "extra == 'tests'", specifier = ">=7.1.1" },
|
||||
{ name = "httpx", marker = "extra == 'tests'", specifier = ">=0.28.1" },
|
||||
{ name = "mypy", marker = "extra == 'tests'", specifier = ">=1.15.0" },
|
||||
{ name = "pydantic", specifier = ">=2.10.5" },
|
||||
{ name = "pydantic-settings", specifier = ">=2.7.1" },
|
||||
{ name = "pytest", marker = "extra == 'tests'", specifier = ">=8.3.4" },
|
||||
{ name = "pytest-asyncio", marker = "extra == 'tests'", specifier = ">=0.25.2" },
|
||||
{ name = "pytest-cov", marker = "extra == 'tests'", specifier = ">=6.0.0" },
|
||||
{ name = "pytest-xdist", marker = "extra == 'tests'", specifier = ">=3.6.1" },
|
||||
{ name = "python-dateutil", specifier = ">=2.9.0.post0" },
|
||||
{ name = "pyyaml", specifier = ">=6.0.1" },
|
||||
{ name = "requests", specifier = ">=2.32.3" },
|
||||
{ name = "requests-file", specifier = ">=2.1.0" },
|
||||
{ name = "responses", marker = "extra == 'tests'", specifier = ">=0.25.6" },
|
||||
{ name = "rich", specifier = ">=13.9.4" },
|
||||
{ name = "ruff", marker = "extra == 'tests'", specifier = ">=0.9.2" },
|
||||
{ name = "sqlalchemy", specifier = ">=2.0.0" },
|
||||
{ name = "types-python-dateutil", marker = "extra == 'tests'", specifier = ">=2.9.0.20241206" },
|
||||
{ name = "types-redis", marker = "extra == 'tests'", specifier = ">=4.6.0" },
|
||||
{ name = "types-requests", marker = "extra == 'tests'", specifier = ">=2.32.0" },
|
||||
{ name = "typing-extensions", specifier = ">=4.12.2" },
|
||||
{ name = "urllib3", specifier = ">=2.3.0" },
|
||||
{ name = "uvicorn", specifier = ">=0.34.0" },
|
||||
{ name = "fastapi", specifier = "~=0.115.6" },
|
||||
{ name = "pydantic", specifier = "~=2.10.5" },
|
||||
{ name = "pydantic-settings", specifier = "~=2.7.1" },
|
||||
{ name = "python-dateutil", specifier = "~=2.9.0" },
|
||||
{ name = "pyyaml", specifier = "~=6.0.1" },
|
||||
{ name = "requests", specifier = "~=2.32.3" },
|
||||
{ name = "requests-file", specifier = "~=2.1.0" },
|
||||
{ name = "rich", specifier = "~=13.9.4" },
|
||||
{ name = "sqlalchemy", specifier = "~=2.0.0" },
|
||||
{ name = "typing-extensions", specifier = "~=4.12.2" },
|
||||
{ name = "urllib3", specifier = "~=2.3.0" },
|
||||
{ name = "uvicorn", specifier = "~=0.34.0" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "fastapi", extras = ["standard"], specifier = "~=0.115.6" },
|
||||
{ name = "httpx", specifier = "~=0.28.1" },
|
||||
{ name = "mypy", specifier = "~=1.17.1" },
|
||||
{ name = "pytest", specifier = "~=8.3.4" },
|
||||
{ name = "pytest-asyncio", specifier = "~=0.25.2" },
|
||||
{ name = "pytest-cov", specifier = "~=6.0.0" },
|
||||
{ name = "pytest-xdist", specifier = "~=3.6.1" },
|
||||
{ name = "responses", specifier = "~=0.25.6" },
|
||||
{ name = "ruff", specifier = "~=0.12.8" },
|
||||
{ name = "types-python-dateutil", specifier = "~=2.9.0.20241206" },
|
||||
{ name = "types-redis", specifier = "~=4.6.0" },
|
||||
{ name = "types-requests", specifier = "~=2.32.0" },
|
||||
]
|
||||
provides-extras = ["tests"]
|
||||
|
||||
[[package]]
|
||||
name = "orjson"
|
||||
@@ -1353,15 +1332,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/14/619e24a4c70df2901e1f4dbc50a6291eb63a759172558df326347dce1f0d/protobuf-3.20.3-py2.py3-none-any.whl", hash = "sha256:a7ca6d488aa8ff7f329d4c545b2dbad8ac31464f1d8b1c87ad1346717731e4db", size = 162128, upload-time = "2022-09-29T22:39:44.547Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycodestyle"
|
||||
version = "2.14.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/11/e0/abfd2a0d2efe47670df87f3e3a0e2edda42f055053c85361f19c0e2c1ca8/pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783", size = 39472, upload-time = "2025-06-20T18:49:48.75Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d", size = 31594, upload-time = "2025-06-20T18:49:47.491Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "2.22"
|
||||
@@ -1373,17 +1343,16 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.11.7"
|
||||
version = "2.10.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
{ name = "pydantic-core" },
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b7/ae/d5220c5c52b158b1de7ca89fc5edb72f304a70a4c540c84c8844bf4008de/pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236", size = 761681, upload-time = "2025-01-24T01:42:12.693Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696, upload-time = "2025-01-24T01:42:10.371Z" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
@@ -1393,50 +1362,40 @@ email = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.33.2"
|
||||
version = "2.27.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443, upload-time = "2024-12-18T11:31:54.917Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127, upload-time = "2024-12-18T11:28:30.346Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340, upload-time = "2024-12-18T11:28:32.521Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900, upload-time = "2024-12-18T11:28:34.507Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/31/4240bc96025035500c18adc149aa6ffdf1a0062a4b525c932065ceb4d868/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", size = 1869177, upload-time = "2024-12-18T11:28:36.488Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/20/02fbaadb7808be578317015c462655c317a77a7c8f0ef274bc016a784c54/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", size = 2038046, upload-time = "2024-12-18T11:28:39.409Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/86/7f306b904e6c9eccf0668248b3f272090e49c275bc488a7b88b0823444a4/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", size = 2685386, upload-time = "2024-12-18T11:28:41.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/f0/49129b27c43396581a635d8710dae54a791b17dfc50c70164866bbf865e3/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", size = 1997060, upload-time = "2024-12-18T11:28:44.709Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/0f/943b4af7cd416c477fd40b187036c4f89b416a33d3cc0ab7b82708a667aa/pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", size = 2004870, upload-time = "2024-12-18T11:28:46.839Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/40/aea70b5b1a63911c53a4c8117c0a828d6790483f858041f47bab0b779f44/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", size = 1999822, upload-time = "2024-12-18T11:28:48.896Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/b3/807b94fd337d58effc5498fd1a7a4d9d59af4133e83e32ae39a96fddec9d/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", size = 2130364, upload-time = "2024-12-18T11:28:50.755Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/df/791c827cd4ee6efd59248dca9369fb35e80a9484462c33c6649a8d02b565/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", size = 2158303, upload-time = "2024-12-18T11:28:54.122Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064, upload-time = "2024-12-18T11:28:56.074Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046, upload-time = "2024-12-18T11:28:58.107Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092, upload-time = "2024-12-18T11:29:01.335Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-settings"
|
||||
version = "2.10.1"
|
||||
version = "2.7.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "python-dotenv" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/68/85/1ea668bbab3c50071ca613c6ab30047fb36ab0da1b92fa8f17bbc38fd36c/pydantic_settings-2.10.1.tar.gz", hash = "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee", size = 172583, upload-time = "2025-06-24T13:26:46.841Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/73/7b/c58a586cd7d9ac66d2ee4ba60ca2d241fa837c02bca9bea80a9a8c3d22a9/pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93", size = 79920, upload-time = "2024-12-31T11:27:44.632Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl", hash = "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796", size = 45235, upload-time = "2025-06-24T13:26:45.485Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyflakes"
|
||||
version = "3.4.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/45/dc/fd034dc20b4b264b3d015808458391acbf9df40b1e54750ef175d39180b1/pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58", size = 64669, upload-time = "2025-06-20T18:45:27.834Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f", size = 63551, upload-time = "2025-06-20T18:45:26.937Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/46/93416fdae86d40879714f72956ac14df9c7b76f7d41a4d68aa9f71a0028b/pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd", size = 29718, upload-time = "2024-12-31T11:27:43.201Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1448,88 +1407,77 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyjwt"
|
||||
version = "2.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fb/68/ce067f09fca4abeca8771fe667d89cc347d1e99da3e093112ac329c6020e/pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c", size = 78825, upload-time = "2024-08-01T15:01:08.445Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/79/84/0fdf9b18ba31d69877bd39c9cd6052b47f3761e9910c15de788e519f079f/PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850", size = 22344, upload-time = "2024-08-01T15:01:06.481Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pymongo"
|
||||
version = "4.13.2"
|
||||
version = "4.10.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "dnspython" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4b/5a/d664298bf54762f0c89b8aa2c276868070e06afb853b4a8837de5741e5f9/pymongo-4.13.2.tar.gz", hash = "sha256:0f64c6469c2362962e6ce97258ae1391abba1566a953a492562d2924b44815c2", size = 2167844, upload-time = "2025-06-16T18:16:30.685Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1a/35/b62a3139f908c68b69aac6a6a3f8cc146869de0a7929b994600e2c587c77/pymongo-4.10.1.tar.gz", hash = "sha256:a9de02be53b6bb98efe0b9eda84ffa1ec027fcb23a2de62c4f941d9a2f2f3330", size = 1903902, upload-time = "2024-10-01T23:07:58.525Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/03/e0/0e187750e23eed4227282fcf568fdb61f2b53bbcf8cbe3a71dde2a860d12/pymongo-4.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ec89516622dfc8b0fdff499612c0bd235aa45eeb176c9e311bcc0af44bf952b6", size = 912004, upload-time = "2025-06-16T18:15:14.299Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/c2/9b79795382daaf41e5f7379bffdef1880d68160adea352b796d6948cb5be/pymongo-4.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f30eab4d4326df54fee54f31f93e532dc2918962f733ee8e115b33e6fe151d92", size = 911698, upload-time = "2025-06-16T18:15:16.334Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/e4/f04dc9ed5d1d9dbc539dc2d8758dd359c5373b0e06fcf25418b2c366737c/pymongo-4.13.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cce9428d12ba396ea245fc4c51f20228cead01119fcc959e1c80791ea45f820", size = 1690357, upload-time = "2025-06-16T18:15:18.358Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/de/41478a7d527d38f1b98b084f4a78bbb805439a6ebd8689fbbee0a3dfacba/pymongo-4.13.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac9241b727a69c39117c12ac1e52d817ea472260dadc66262c3fdca0bab0709b", size = 1754593, upload-time = "2025-06-16T18:15:20.096Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/d9/8fa2eb110291e154f4312779b1a5b815090b8b05a59ecb4f4a32427db1df/pymongo-4.13.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3efc4c515b371a9fa1d198b6e03340985bfe1a55ae2d2b599a714934e7bc61ab", size = 1723637, upload-time = "2025-06-16T18:15:22.048Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/7b/9863fa60a4a51ea09f5e3cd6ceb231af804e723671230f2daf3bd1b59c2b/pymongo-4.13.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f57a664aa74610eb7a52fa93f2cf794a1491f4f76098343485dd7da5b3bcff06", size = 1693613, upload-time = "2025-06-16T18:15:24.866Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/89/a42efa07820a59089836f409a63c96e7a74e33313e50dc39c554db99ac42/pymongo-4.13.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3dcb0b8cdd499636017a53f63ef64cf9b6bd3fd9355796c5a1d228e4be4a4c94", size = 1652745, upload-time = "2025-06-16T18:15:27.078Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/cf/2c77d1acda61d281edd3e3f00d5017d3fac0c29042c769efd3b8018cb469/pymongo-4.13.2-cp312-cp312-win32.whl", hash = "sha256:bf43ae07804d7762b509f68e5ec73450bb8824e960b03b861143ce588b41f467", size = 883232, upload-time = "2025-06-16T18:15:29.169Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/4f/727f59156e3798850c3c2901f106804053cb0e057ed1bd9883f5fa5aa8fa/pymongo-4.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:812a473d584bcb02ab819d379cd5e752995026a2bb0d7713e78462b6650d3f3a", size = 903304, upload-time = "2025-06-16T18:15:31.346Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/d1/60ad99fe3f64d45e6c71ac0e3078e88d9b64112b1bae571fc3707344d6d1/pymongo-4.10.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fbedc4617faa0edf423621bb0b3b8707836687161210d470e69a4184be9ca011", size = 943356, upload-time = "2024-10-01T23:06:50.9Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/9b/21d4c6b4ee9c1fa9691c68dc2a52565e0acb644b9e95148569b4736a4ebd/pymongo-4.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7bd26b2aec8ceeb95a5d948d5cc0f62b0eb6d66f3f4230705c1e3d3d2c04ec76", size = 943142, upload-time = "2024-10-01T23:06:52.146Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/af/691b7454e219a8eb2d1641aecedd607e3a94b93650c2011ad8a8fd74ef9f/pymongo-4.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb104c3c2a78d9d85571c8ac90ec4f95bca9b297c6eee5ada71fabf1129e1674", size = 1909129, upload-time = "2024-10-01T23:06:53.551Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/74/fd75d5ad4181d6e71ce0fca32404fb71b5046ac84d9a1a2f0862262dd032/pymongo-4.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4924355245a9c79f77b5cda2db36e0f75ece5faf9f84d16014c0a297f6d66786", size = 1987763, upload-time = "2024-10-01T23:06:55.304Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/56/6d3d0ef63c6d8cb98c7c653a3a2e617675f77a95f3853851d17a7664876a/pymongo-4.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:11280809e5dacaef4971113f0b4ff4696ee94cfdb720019ff4fa4f9635138252", size = 1950821, upload-time = "2024-10-01T23:06:57.541Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/ed/1603fa0c0e51444752c3fa91f16c3a97e6d92eb9fe5e553dae4f18df16f6/pymongo-4.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5d55f2a82e5eb23795f724991cac2bffbb1c0f219c0ba3bf73a835f97f1bb2e", size = 1912247, upload-time = "2024-10-01T23:06:59.023Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/66/e98b2308971d45667cb8179d4d66deca47336c90663a7e0527589f1038b7/pymongo-4.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e974ab16a60be71a8dfad4e5afccf8dd05d41c758060f5d5bda9a758605d9a5d", size = 1862230, upload-time = "2024-10-01T23:07:01.407Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/80/ba9b7ed212a5f8cf8ad7037ed5bbebc1c587fc09242108f153776e4a338b/pymongo-4.10.1-cp312-cp312-win32.whl", hash = "sha256:544890085d9641f271d4f7a47684450ed4a7344d6b72d5968bfae32203b1bb7c", size = 903045, upload-time = "2024-10-01T23:07:02.973Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/8b/5afce891d78159912c43726fab32641e3f9718f14be40f978c148ea8db48/pymongo-4.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:dcc07b1277e8b4bf4d7382ca133850e323b7ab048b8353af496d050671c7ac52", size = 926686, upload-time = "2024-10-01T23:07:04.403Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "8.4.1"
|
||||
version = "8.3.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "iniconfig" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pluggy" },
|
||||
{ name = "pygments" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-asyncio"
|
||||
version = "1.0.0"
|
||||
version = "0.25.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d0/d4/14f53324cb1a6381bef29d698987625d80052bb33932d8e7cbf9b337b17c/pytest_asyncio-1.0.0.tar.gz", hash = "sha256:d15463d13f4456e1ead2594520216b225a16f781e144f8fdf6c5bb4667c48b3f", size = 46960, upload-time = "2025-05-26T04:54:40.484Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f2/a8/ecbc8ede70921dd2f544ab1cadd3ff3bf842af27f87bbdea774c7baa1d38/pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a", size = 54239, upload-time = "2025-01-28T18:37:58.729Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/30/05/ce271016e351fddc8399e546f6e23761967ee09c8c568bbfbecb0c150171/pytest_asyncio-1.0.0-py3-none-any.whl", hash = "sha256:4f024da9f1ef945e680dc68610b52550e36590a67fd31bb3b4943979a1f90ef3", size = 15976, upload-time = "2025-05-26T04:54:39.035Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/17/3493c5624e48fd97156ebaec380dcaafee9506d7e2c46218ceebbb57d7de/pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3", size = 19467, upload-time = "2025-01-28T18:37:56.798Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-cov"
|
||||
version = "6.2.1"
|
||||
version = "6.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "coverage" },
|
||||
{ name = "pluggy" },
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/18/99/668cade231f434aaa59bbfbf49469068d2ddd945000621d3d165d2e7dd7b/pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", size = 69432, upload-time = "2025-06-12T10:47:47.684Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945, upload-time = "2024-10-29T20:13:35.363Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/16/4ea354101abb1287856baa4af2732be351c7bee728065aed451b678153fd/pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5", size = 24644, upload-time = "2025-06-12T10:47:45.932Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949, upload-time = "2024-10-29T20:13:33.215Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-xdist"
|
||||
version = "3.8.0"
|
||||
version = "3.6.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "execnet" },
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/41/c4/3c310a19bc1f1e9ef50075582652673ef2bfc8cd62afef9585683821902f/pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d", size = 84060, upload-time = "2024-04-28T19:29:54.414Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/82/1d96bf03ee4c0fdc3c0cbe61470070e659ca78dc0086fb88b66c185e2449/pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7", size = 46108, upload-time = "2024-04-28T19:29:52.813Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1581,14 +1529,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "redis"
|
||||
version = "5.3.0"
|
||||
version = "5.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pyjwt" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/71/dd/2b37032f4119dff2a2f9bbcaade03221b100ba26051bb96e275de3e5db7a/redis-5.3.0.tar.gz", hash = "sha256:8d69d2dde11a12dc85d0dbf5c45577a5af048e2456f7077d87ad35c1c81c310e", size = 4626288, upload-time = "2025-04-30T14:54:40.634Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/47/da/d283a37303a995cd36f8b92db85135153dc4f7a8e4441aa827721b442cfb/redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f", size = 4608355, upload-time = "2024-12-06T09:50:41.956Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/45/b0/aa601efe12180ba492b02e270554877e68467e66bda5d73e51eaa8ecc78a/redis-5.3.0-py3-none-any.whl", hash = "sha256:f1deeca1ea2ef25c1e4e46b07f4ea1275140526b1feea4c6459c0ec27a10ef83", size = 272836, upload-time = "2025-04-30T14:54:30.744Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/5f/fa26b9b2672cbe30e07d9a5bdf39cf16e3b80b42916757c5f92bca88e4ba/redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4", size = 261502, upload-time = "2024-12-06T09:50:39.656Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1669,15 +1614,15 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "rich"
|
||||
version = "14.0.0"
|
||||
version = "13.9.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markdown-it-py" },
|
||||
{ name = "pygments" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078, upload-time = "2025-03-30T14:15:14.23Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149, upload-time = "2024-11-01T16:43:57.873Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424, upload-time = "2024-11-01T16:43:55.817Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1720,27 +1665,28 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.12.2"
|
||||
version = "0.12.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4a/45/2e403fa7007816b5fbb324cb4f8ed3c7402a927a0a0cb2b6279879a8bfdc/ruff-0.12.9.tar.gz", hash = "sha256:fbd94b2e3c623f659962934e52c2bea6fc6da11f667a427a368adaf3af2c866a", size = 5254702, upload-time = "2025-08-14T16:08:55.2Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/20/53bf098537adb7b6a97d98fcdebf6e916fcd11b2e21d15f8c171507909cc/ruff-0.12.9-py3-none-linux_armv6l.whl", hash = "sha256:fcebc6c79fcae3f220d05585229463621f5dbf24d79fdc4936d9302e177cfa3e", size = 11759705, upload-time = "2025-08-14T16:08:12.968Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/4d/c764ee423002aac1ec66b9d541285dd29d2c0640a8086c87de59ebbe80d5/ruff-0.12.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aed9d15f8c5755c0e74467731a007fcad41f19bcce41cd75f768bbd687f8535f", size = 12527042, upload-time = "2025-08-14T16:08:16.54Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/45/cfcdf6d3eb5fc78a5b419e7e616d6ccba0013dc5b180522920af2897e1be/ruff-0.12.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5b15ea354c6ff0d7423814ba6d44be2807644d0c05e9ed60caca87e963e93f70", size = 11724457, upload-time = "2025-08-14T16:08:18.686Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/e6/44615c754b55662200c48bebb02196dbb14111b6e266ab071b7e7297b4ec/ruff-0.12.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d596c2d0393c2502eaabfef723bd74ca35348a8dac4267d18a94910087807c53", size = 11949446, upload-time = "2025-08-14T16:08:21.059Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/d1/9b7d46625d617c7df520d40d5ac6cdcdf20cbccb88fad4b5ecd476a6bb8d/ruff-0.12.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b15599931a1a7a03c388b9c5df1bfa62be7ede6eb7ef753b272381f39c3d0ff", size = 11566350, upload-time = "2025-08-14T16:08:23.433Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/20/b73132f66f2856bc29d2d263c6ca457f8476b0bbbe064dac3ac3337a270f/ruff-0.12.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3d02faa2977fb6f3f32ddb7828e212b7dd499c59eb896ae6c03ea5c303575756", size = 13270430, upload-time = "2025-08-14T16:08:25.837Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/21/eaf3806f0a3d4c6be0a69d435646fba775b65f3f2097d54898b0fd4bb12e/ruff-0.12.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:17d5b6b0b3a25259b69ebcba87908496e6830e03acfb929ef9fd4c58675fa2ea", size = 14264717, upload-time = "2025-08-14T16:08:27.907Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/82/1d0c53bd37dcb582b2c521d352fbf4876b1e28bc0d8894344198f6c9950d/ruff-0.12.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:72db7521860e246adbb43f6ef464dd2a532ef2ef1f5dd0d470455b8d9f1773e0", size = 13684331, upload-time = "2025-08-14T16:08:30.352Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/2f/1c5cf6d8f656306d42a686f1e207f71d7cebdcbe7b2aa18e4e8a0cb74da3/ruff-0.12.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a03242c1522b4e0885af63320ad754d53983c9599157ee33e77d748363c561ce", size = 12739151, upload-time = "2025-08-14T16:08:32.55Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/09/25033198bff89b24d734e6479e39b1968e4c992e82262d61cdccaf11afb9/ruff-0.12.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fc83e4e9751e6c13b5046d7162f205d0a7bac5840183c5beebf824b08a27340", size = 12954992, upload-time = "2025-08-14T16:08:34.816Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/8e/d0dbf2f9dca66c2d7131feefc386523404014968cd6d22f057763935ab32/ruff-0.12.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:881465ed56ba4dd26a691954650de6ad389a2d1fdb130fe51ff18a25639fe4bb", size = 12899569, upload-time = "2025-08-14T16:08:36.852Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/bd/b614d7c08515b1428ed4d3f1d4e3d687deffb2479703b90237682586fa66/ruff-0.12.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:43f07a3ccfc62cdb4d3a3348bf0588358a66da756aa113e071b8ca8c3b9826af", size = 11751983, upload-time = "2025-08-14T16:08:39.314Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/d6/383e9f818a2441b1a0ed898d7875f11273f10882f997388b2b51cb2ae8b5/ruff-0.12.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:07adb221c54b6bba24387911e5734357f042e5669fa5718920ee728aba3cbadc", size = 11538635, upload-time = "2025-08-14T16:08:41.297Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/9c/56f869d314edaa9fc1f491706d1d8a47747b9d714130368fbd69ce9024e9/ruff-0.12.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f5cd34fabfdea3933ab85d72359f118035882a01bff15bd1d2b15261d85d5f66", size = 12534346, upload-time = "2025-08-14T16:08:43.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/4b/d8b95c6795a6c93b439bc913ee7a94fda42bb30a79285d47b80074003ee7/ruff-0.12.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f6be1d2ca0686c54564da8e7ee9e25f93bdd6868263805f8c0b8fc6a449db6d7", size = 13017021, upload-time = "2025-08-14T16:08:45.889Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/c1/5f9a839a697ce1acd7af44836f7c2181cdae5accd17a5cb85fcbd694075e/ruff-0.12.9-py3-none-win32.whl", hash = "sha256:cc7a37bd2509974379d0115cc5608a1a4a6c4bff1b452ea69db83c8855d53f93", size = 11734785, upload-time = "2025-08-14T16:08:48.062Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/66/cdddc2d1d9a9f677520b7cfc490d234336f523d4b429c1298de359a3be08/ruff-0.12.9-py3-none-win_amd64.whl", hash = "sha256:6fb15b1977309741d7d098c8a3cb7a30bc112760a00fb6efb7abc85f00ba5908", size = 12840654, upload-time = "2025-08-14T16:08:50.158Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/fd/669816bc6b5b93b9586f3c1d87cd6bc05028470b3ecfebb5938252c47a35/ruff-0.12.9-py3-none-win_arm64.whl", hash = "sha256:63c8c819739d86b96d500cce885956a1a48ab056bbcbc61b747ad494b2485089", size = 11949623, upload-time = "2025-08-14T16:08:52.233Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1996,11 +1942,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.14.1"
|
||||
version = "4.12.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321, upload-time = "2024-06-07T18:52:15.995Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438, upload-time = "2024-06-07T18:52:13.582Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2016,38 +1962,26 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f", size = 8827, upload-time = "2023-05-24T20:25:45.287Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-inspection"
|
||||
version = "0.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.5.0"
|
||||
version = "2.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268, upload-time = "2024-12-22T07:47:30.032Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369, upload-time = "2024-12-22T07:47:28.074Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uvicorn"
|
||||
version = "0.35.0"
|
||||
version = "0.34.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/de/ad/713be230bcda622eaa35c28f0d328c3675c371238470abdea52417f17a8e/uvicorn-0.34.3.tar.gz", hash = "sha256:35919a9a979d7a59334b6b10e05d77c1d0d574c50e0fc98b8b1a0f165708b55a", size = 76631, upload-time = "2025-06-01T07:48:17.531Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/0d/8adfeaa62945f90d19ddc461c55f4a50c258af7662d34b6a3d5d1f8646f6/uvicorn-0.34.3-py3-none-any.whl", hash = "sha256:16246631db62bdfbf069b0645177d6e8a77ba950cfedbfd093acef9444e4d885", size = 62431, upload-time = "2025-06-01T07:48:15.664Z" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
|
||||
+2
-3
@@ -6,8 +6,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt-get install -y python$PYTHON_VERSION python$PYTHON_VERSION-dev
|
||||
|
||||
FROM python_base AS runtime-base
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get update
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
|
||||
curl \
|
||||
patch \
|
||||
codequery \
|
||||
@@ -25,7 +24,7 @@ COPY --from=ghcr.io/astral-sh/uv:0.5.20 /uv /uvx /bin/
|
||||
ENV UV_LINK_MODE=copy \
|
||||
UV_COMPILE_BYTECODE=1 \
|
||||
UV_PYTHON_DOWNLOADS=never \
|
||||
UV_PYTHON=python3.12
|
||||
UV_PYTHON=python${PYTHON_VERSION}
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
||||
+47
-18
@@ -4,33 +4,40 @@ version = "0.1.0"
|
||||
description = "Buttercup patcher"
|
||||
readme = "README.md"
|
||||
authors = [{ name = "Trail of Bits", email = "opensource@trailofbits.com" }]
|
||||
license = "AGPL-3.0-only"
|
||||
requires-python = ">=3.12,<3.13"
|
||||
dependencies = [
|
||||
"common",
|
||||
"langchain~=0.3.20",
|
||||
"langchain-community>=0.3.16",
|
||||
"langgraph~=0.5.2",
|
||||
"langgraph-checkpoint>=2.0.25",
|
||||
"openai>=1.60.2",
|
||||
"langchain ~=0.3.20",
|
||||
"langchain-community ~=0.3.16",
|
||||
"langgraph ~=0.5.2",
|
||||
"langgraph-checkpoint ~=2.1.0",
|
||||
"openai ~=1.60.2",
|
||||
"program-model",
|
||||
"pydantic-settings>=2.7.1",
|
||||
"python-dotenv>=1.0.1",
|
||||
"unidiff>=0.7.5",
|
||||
"pydantic-settings ~=2.7.1",
|
||||
"python-dotenv ~=1.0.1",
|
||||
"unidiff ~=0.7.5",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/trailofbits/buttercup"
|
||||
Issues = "https://github.com/trailofbits/buttercup/issues"
|
||||
|
||||
[project.scripts]
|
||||
buttercup-patcher = "buttercup.patcher.__cli__:main"
|
||||
|
||||
[project.optional-dependencies]
|
||||
tests = [
|
||||
"flake8>=7.1.1",
|
||||
"mypy>=1.15.0",
|
||||
"pytest>=8.3.4",
|
||||
"pytest-asyncio>=0.25.2",
|
||||
"pytest-cov>=6.0.0",
|
||||
"pytest-xdist>=3.6.1",
|
||||
"ruff>=0.9.2",
|
||||
"types-python-dateutil>=2.9.0.20241206",
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
# Testing tools
|
||||
"pytest ~=8.3.4",
|
||||
"pytest-asyncio ~=0.25.2",
|
||||
"pytest-cov ~=6.0.0",
|
||||
"pytest-xdist ~=3.6.1",
|
||||
# Linting and type checking
|
||||
"ruff ~=0.12.8",
|
||||
"mypy ~=1.17.1",
|
||||
# Type stubs
|
||||
"types-python-dateutil ~=2.9.0.20241206",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
@@ -42,6 +49,28 @@ packages = ["src/buttercup"]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
target-version = "py312"
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "I", "W", "UP"]
|
||||
ignore = [
|
||||
"COM812", "ISC001", # Formatter conflicts
|
||||
# Temporarily disabled for standardization PR - re-enable after refactoring:
|
||||
"I001", # Import block is un-sorted or un-formatted
|
||||
"E501", # Line too long
|
||||
"W291", # Trailing whitespace
|
||||
"W293", # Blank line contains whitespace
|
||||
"UP006", # Use built-in collection types for type annotations
|
||||
"UP012", # Unnecessary call to encode as UTF-8
|
||||
"UP015", # Unnecessary mode argument
|
||||
"UP031", # Use format specifiers instead of percent format
|
||||
"UP035", # Import from modern locations instead of deprecated typing
|
||||
"UP045", # Use X | None for type annotations
|
||||
"UP046", # Use modern generic class syntax
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"tests/**/*.py" = ["S101", "D"] # Allow asserts, no docstrings in tests
|
||||
|
||||
[tool.uv.sources]
|
||||
common = { path = "../common", editable = true }
|
||||
|
||||
Generated
+107
-167
@@ -1,5 +1,5 @@
|
||||
version = 1
|
||||
revision = 2
|
||||
revision = 3
|
||||
requires-python = "==3.12.*"
|
||||
|
||||
[[package]]
|
||||
@@ -235,22 +235,23 @@ requires-dist = [
|
||||
{ name = "langchain-text-splitters", specifier = "~=0.3.7" },
|
||||
{ name = "langfuse", specifier = "~=2.59.2" },
|
||||
{ name = "openlit", specifier = "==1.32.12" },
|
||||
{ name = "protobuf", specifier = ">=3.20,<=3.20.3" },
|
||||
{ name = "pydantic-settings", specifier = ">=2.7.1" },
|
||||
{ name = "pymongo", specifier = ">=4.10.1" },
|
||||
{ name = "redis", specifier = ">=5.2.1,<6.0.0" },
|
||||
{ name = "six", specifier = ">=1.17.0" },
|
||||
{ name = "protobuf", specifier = "==3.20.3" },
|
||||
{ name = "pydantic-settings", specifier = "~=2.7.1" },
|
||||
{ name = "pymongo", specifier = "~=4.10.1" },
|
||||
{ name = "redis", specifier = "~=5.2.1" },
|
||||
{ name = "six", specifier = "~=1.17.0" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "dirty-equals", specifier = ">=0.9.0" },
|
||||
{ name = "mypy", specifier = ">=1.15.0" },
|
||||
{ name = "pytest", specifier = ">=8.3.4" },
|
||||
{ name = "ruff", specifier = ">=0.9.2" },
|
||||
{ name = "dirty-equals", specifier = "~=0.9.0" },
|
||||
{ name = "mypy", specifier = "~=1.17.1" },
|
||||
{ name = "pytest", specifier = "~=8.3.4" },
|
||||
{ name = "pytest-cov", specifier = "~=6.0.0" },
|
||||
{ name = "ruff", specifier = "~=0.12.8" },
|
||||
{ name = "types-pyyaml" },
|
||||
{ name = "types-redis" },
|
||||
{ name = "types-requests" },
|
||||
{ name = "types-redis", specifier = "~=4.6.0" },
|
||||
{ name = "types-requests", specifier = "~=2.32.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -334,20 +335,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flake8"
|
||||
version = "7.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mccabe" },
|
||||
{ name = "pycodestyle" },
|
||||
{ name = "pyflakes" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9b/af/fbfe3c4b5a657d79e5c47a2827a362f9e1b763336a52f926126aa6dc7123/flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872", size = 48326, upload-time = "2025-06-20T19:31:35.838Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e", size = 57922, upload-time = "2025-06-20T19:31:34.425Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "frozenlist"
|
||||
version = "1.7.0"
|
||||
@@ -651,16 +638,16 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "langchain-openai"
|
||||
version = "0.3.27"
|
||||
version = "0.3.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "langchain-core" },
|
||||
{ name = "openai" },
|
||||
{ name = "tiktoken" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6f/7b/e65261a08a03dd43f0ef8a539930b56548ac8136e71258c220d3589d1d07/langchain_openai-0.3.27.tar.gz", hash = "sha256:5d5a55adbff739274dfc3a4102925771736f893758f63679b64ae62fed79ca30", size = 753326, upload-time = "2025-06-27T17:56:29.904Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2e/04/ae071af0b04d1c3a8040498714091afd21149f6f8ae1dbab584317d9dfd7/langchain_openai-0.3.8.tar.gz", hash = "sha256:4d73727eda8102d1d07a2ca036278fccab0bb5e0abf353cec9c3973eb72550ec", size = 256898, upload-time = "2025-03-07T18:33:43.308Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/31/1f0baf6490b082bf4d06f355c5e9c28728931dbf321f3ca03137617a692e/langchain_openai-0.3.27-py3-none-any.whl", hash = "sha256:efe636c3523978c44adc41cf55c8b3766c05c77547982465884d1258afe705df", size = 70368, upload-time = "2025-06-27T17:56:28.726Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/43/9c6a1101bcd751d52a3328a06956f85122f9aaa31da1b15a8e0f99a70317/langchain_openai-0.3.8-py3-none-any.whl", hash = "sha256:9004dc8ef853aece0d8f0feca7753dc97f710fa3e53874c8db66466520436dbb", size = 55446, upload-time = "2025-03-07T18:33:42.169Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -780,15 +767,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/34/75/51952c7b2d3873b44a0028b1bd26a25078c18f92f256608e8d1dc61b39fd/marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", size = 50878, upload-time = "2025-02-03T15:32:22.295Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mccabe"
|
||||
version = "0.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multidict"
|
||||
version = "6.6.3"
|
||||
@@ -818,22 +796,22 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "mypy"
|
||||
version = "1.16.1"
|
||||
version = "1.17.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mypy-extensions" },
|
||||
{ name = "pathspec" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8e/22/ea637422dedf0bf36f3ef238eab4e455e2a0dcc3082b5cc067615347ab8e/mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01", size = 3352570, upload-time = "2025-07-31T07:54:19.204Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/a2/7034d0d61af8098ec47902108553122baa0f438df8a713be860f7407c9e6/mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb", size = 11086295, upload-time = "2025-07-31T07:53:28.124Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/1f/19e7e44b594d4b12f6ba8064dbe136505cec813549ca3e5191e40b1d3cc2/mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403", size = 10112355, upload-time = "2025-07-31T07:53:21.121Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/69/baa33927e29e6b4c55d798a9d44db5d394072eef2bdc18c3e2048c9ed1e9/mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056", size = 11875285, upload-time = "2025-07-31T07:53:55.293Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/13/f3a89c76b0a41e19490b01e7069713a30949d9a6c147289ee1521bcea245/mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341", size = 12737895, upload-time = "2025-07-31T07:53:43.623Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/a1/c4ee79ac484241301564072e6476c5a5be2590bc2e7bfd28220033d2ef8f/mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb", size = 12931025, upload-time = "2025-07-31T07:54:17.125Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/b8/7409477be7919a0608900e6320b155c72caab4fef46427c5cc75f85edadd/mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19", size = 9584664, upload-time = "2025-07-31T07:54:12.842Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/f3/8fcd2af0f5b806f6cf463efaffd3c9548a28f84220493ecd38d127b6b66d/mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9", size = 2283411, upload-time = "2025-07-31T07:53:24.664Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -866,7 +844,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "openai"
|
||||
version = "1.93.3"
|
||||
version = "1.60.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
@@ -878,9 +856,9 @@ dependencies = [
|
||||
{ name = "tqdm" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e0/66/fadc0cad6a229c6a85c3aa5f222a786ec4d9bf14c2a004f80ffa21dbaf21/openai-1.93.3.tar.gz", hash = "sha256:488b76399238c694af7e4e30c58170ea55e6f65038ab27dbe95b5077a00f8af8", size = 487595, upload-time = "2025-07-09T14:08:27.789Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/08/ae/8d9706b8ff2363287b4a8807de2dd29cdbdad5424e9d05d345df724320f5/openai-1.60.2.tar.gz", hash = "sha256:a8f843e10f2855713007f491d96afb2694b11b5e02cb97c7d01a0be60bc5bb51", size = 348185, upload-time = "2025-01-27T19:37:03.72Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/b9/0df6351b25c6bd494c534d2a8191dc9460fb5bb09c88b1427775d49fde05/openai-1.93.3-py3-none-any.whl", hash = "sha256:41aaa7594c7d141b46eed0a58dcd75d20edcc809fdd2c931ecbb4957dc98a892", size = 755132, upload-time = "2025-07-09T14:08:25.533Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/5a/d5474ca67a547dde9b87b5bc8a8f90eadf29f523d410f2ba23d63c9b82ec/openai-1.60.2-py3-none-any.whl", hash = "sha256:993bd11b96900b9098179c728026f016b4982ded7ee30dfcf4555eab1171fff9", size = 456107, upload-time = "2025-01-27T19:37:01.065Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1099,9 +1077,8 @@ dependencies = [
|
||||
{ name = "unidiff" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
tests = [
|
||||
{ name = "flake8" },
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "mypy" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
@@ -1114,25 +1091,27 @@ tests = [
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "common", editable = "../common" },
|
||||
{ name = "flake8", marker = "extra == 'tests'", specifier = ">=7.1.1" },
|
||||
{ name = "langchain", specifier = "~=0.3.20" },
|
||||
{ name = "langchain-community", specifier = ">=0.3.16" },
|
||||
{ name = "langchain-community", specifier = "~=0.3.16" },
|
||||
{ name = "langgraph", specifier = "~=0.5.2" },
|
||||
{ name = "langgraph-checkpoint", specifier = ">=2.0.25" },
|
||||
{ name = "mypy", marker = "extra == 'tests'", specifier = ">=1.15.0" },
|
||||
{ name = "openai", specifier = ">=1.60.2" },
|
||||
{ name = "langgraph-checkpoint", specifier = "~=2.1.0" },
|
||||
{ name = "openai", specifier = "~=1.60.2" },
|
||||
{ name = "program-model", editable = "../program-model" },
|
||||
{ name = "pydantic-settings", specifier = ">=2.7.1" },
|
||||
{ name = "pytest", marker = "extra == 'tests'", specifier = ">=8.3.4" },
|
||||
{ name = "pytest-asyncio", marker = "extra == 'tests'", specifier = ">=0.25.2" },
|
||||
{ name = "pytest-cov", marker = "extra == 'tests'", specifier = ">=6.0.0" },
|
||||
{ name = "pytest-xdist", marker = "extra == 'tests'", specifier = ">=3.6.1" },
|
||||
{ name = "python-dotenv", specifier = ">=1.0.1" },
|
||||
{ name = "ruff", marker = "extra == 'tests'", specifier = ">=0.9.2" },
|
||||
{ name = "types-python-dateutil", marker = "extra == 'tests'", specifier = ">=2.9.0.20241206" },
|
||||
{ name = "unidiff", specifier = ">=0.7.5" },
|
||||
{ name = "pydantic-settings", specifier = "~=2.7.1" },
|
||||
{ name = "python-dotenv", specifier = "~=1.0.1" },
|
||||
{ name = "unidiff", specifier = "~=0.7.5" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "mypy", specifier = "~=1.17.1" },
|
||||
{ name = "pytest", specifier = "~=8.3.4" },
|
||||
{ name = "pytest-asyncio", specifier = "~=0.25.2" },
|
||||
{ name = "pytest-cov", specifier = "~=6.0.0" },
|
||||
{ name = "pytest-xdist", specifier = "~=3.6.1" },
|
||||
{ name = "ruff", specifier = "~=0.12.8" },
|
||||
{ name = "types-python-dateutil", specifier = "~=2.9.0.20241206" },
|
||||
]
|
||||
provides-extras = ["tests"]
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
@@ -1167,17 +1146,19 @@ dependencies = [
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "common", editable = "../common" },
|
||||
{ name = "protobuf", specifier = ">=3.20,<=3.20.3" },
|
||||
{ name = "protobuf", specifier = "==3.20.3" },
|
||||
{ name = "rapidfuzz", specifier = "~=3.12.2" },
|
||||
{ name = "tree-sitter", specifier = ">=0.24.0" },
|
||||
{ name = "tree-sitter-language-pack", specifier = ">=0.4.0" },
|
||||
{ name = "tree-sitter", specifier = "~=0.24.0" },
|
||||
{ name = "tree-sitter-language-pack", specifier = "~=0.9.0" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "mypy", specifier = ">=1.15.0" },
|
||||
{ name = "pytest", specifier = ">=8.3.4" },
|
||||
{ name = "ruff", specifier = ">=0.9.2" },
|
||||
{ name = "mypy", specifier = "~=1.17.1" },
|
||||
{ name = "pytest", specifier = "~=8.3.4" },
|
||||
{ name = "pytest-cov", specifier = "~=6.0.0" },
|
||||
{ name = "ruff", specifier = "~=0.12.8" },
|
||||
{ name = "types-redis", specifier = "~=4.6.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1214,15 +1195,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/14/619e24a4c70df2901e1f4dbc50a6291eb63a759172558df326347dce1f0d/protobuf-3.20.3-py2.py3-none-any.whl", hash = "sha256:a7ca6d488aa8ff7f329d4c545b2dbad8ac31464f1d8b1c87ad1346717731e4db", size = 162128, upload-time = "2022-09-29T22:39:44.547Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycodestyle"
|
||||
version = "2.14.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/11/e0/abfd2a0d2efe47670df87f3e3a0e2edda42f055053c85361f19c0e2c1ca8/pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783", size = 39472, upload-time = "2025-06-20T18:49:48.75Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d", size = 31594, upload-time = "2025-06-20T18:49:47.491Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "2.22"
|
||||
@@ -1274,118 +1246,88 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-settings"
|
||||
version = "2.10.1"
|
||||
version = "2.7.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "python-dotenv" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/68/85/1ea668bbab3c50071ca613c6ab30047fb36ab0da1b92fa8f17bbc38fd36c/pydantic_settings-2.10.1.tar.gz", hash = "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee", size = 172583, upload-time = "2025-06-24T13:26:46.841Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/73/7b/c58a586cd7d9ac66d2ee4ba60ca2d241fa837c02bca9bea80a9a8c3d22a9/pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93", size = 79920, upload-time = "2024-12-31T11:27:44.632Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl", hash = "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796", size = 45235, upload-time = "2025-06-24T13:26:45.485Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyflakes"
|
||||
version = "3.4.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/45/dc/fd034dc20b4b264b3d015808458391acbf9df40b1e54750ef175d39180b1/pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58", size = 64669, upload-time = "2025-06-20T18:45:27.834Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f", size = 63551, upload-time = "2025-06-20T18:45:26.937Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.19.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyjwt"
|
||||
version = "2.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fb/68/ce067f09fca4abeca8771fe667d89cc347d1e99da3e093112ac329c6020e/pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c", size = 78825, upload-time = "2024-08-01T15:01:08.445Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/79/84/0fdf9b18ba31d69877bd39c9cd6052b47f3761e9910c15de788e519f079f/PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850", size = 22344, upload-time = "2024-08-01T15:01:06.481Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/46/93416fdae86d40879714f72956ac14df9c7b76f7d41a4d68aa9f71a0028b/pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd", size = 29718, upload-time = "2024-12-31T11:27:43.201Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pymongo"
|
||||
version = "4.13.2"
|
||||
version = "4.10.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "dnspython" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4b/5a/d664298bf54762f0c89b8aa2c276868070e06afb853b4a8837de5741e5f9/pymongo-4.13.2.tar.gz", hash = "sha256:0f64c6469c2362962e6ce97258ae1391abba1566a953a492562d2924b44815c2", size = 2167844, upload-time = "2025-06-16T18:16:30.685Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1a/35/b62a3139f908c68b69aac6a6a3f8cc146869de0a7929b994600e2c587c77/pymongo-4.10.1.tar.gz", hash = "sha256:a9de02be53b6bb98efe0b9eda84ffa1ec027fcb23a2de62c4f941d9a2f2f3330", size = 1903902, upload-time = "2024-10-01T23:07:58.525Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/03/e0/0e187750e23eed4227282fcf568fdb61f2b53bbcf8cbe3a71dde2a860d12/pymongo-4.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ec89516622dfc8b0fdff499612c0bd235aa45eeb176c9e311bcc0af44bf952b6", size = 912004, upload-time = "2025-06-16T18:15:14.299Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/c2/9b79795382daaf41e5f7379bffdef1880d68160adea352b796d6948cb5be/pymongo-4.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f30eab4d4326df54fee54f31f93e532dc2918962f733ee8e115b33e6fe151d92", size = 911698, upload-time = "2025-06-16T18:15:16.334Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/e4/f04dc9ed5d1d9dbc539dc2d8758dd359c5373b0e06fcf25418b2c366737c/pymongo-4.13.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cce9428d12ba396ea245fc4c51f20228cead01119fcc959e1c80791ea45f820", size = 1690357, upload-time = "2025-06-16T18:15:18.358Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/de/41478a7d527d38f1b98b084f4a78bbb805439a6ebd8689fbbee0a3dfacba/pymongo-4.13.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac9241b727a69c39117c12ac1e52d817ea472260dadc66262c3fdca0bab0709b", size = 1754593, upload-time = "2025-06-16T18:15:20.096Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/d9/8fa2eb110291e154f4312779b1a5b815090b8b05a59ecb4f4a32427db1df/pymongo-4.13.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3efc4c515b371a9fa1d198b6e03340985bfe1a55ae2d2b599a714934e7bc61ab", size = 1723637, upload-time = "2025-06-16T18:15:22.048Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/7b/9863fa60a4a51ea09f5e3cd6ceb231af804e723671230f2daf3bd1b59c2b/pymongo-4.13.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f57a664aa74610eb7a52fa93f2cf794a1491f4f76098343485dd7da5b3bcff06", size = 1693613, upload-time = "2025-06-16T18:15:24.866Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/89/a42efa07820a59089836f409a63c96e7a74e33313e50dc39c554db99ac42/pymongo-4.13.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3dcb0b8cdd499636017a53f63ef64cf9b6bd3fd9355796c5a1d228e4be4a4c94", size = 1652745, upload-time = "2025-06-16T18:15:27.078Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/cf/2c77d1acda61d281edd3e3f00d5017d3fac0c29042c769efd3b8018cb469/pymongo-4.13.2-cp312-cp312-win32.whl", hash = "sha256:bf43ae07804d7762b509f68e5ec73450bb8824e960b03b861143ce588b41f467", size = 883232, upload-time = "2025-06-16T18:15:29.169Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/4f/727f59156e3798850c3c2901f106804053cb0e057ed1bd9883f5fa5aa8fa/pymongo-4.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:812a473d584bcb02ab819d379cd5e752995026a2bb0d7713e78462b6650d3f3a", size = 903304, upload-time = "2025-06-16T18:15:31.346Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/d1/60ad99fe3f64d45e6c71ac0e3078e88d9b64112b1bae571fc3707344d6d1/pymongo-4.10.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fbedc4617faa0edf423621bb0b3b8707836687161210d470e69a4184be9ca011", size = 943356, upload-time = "2024-10-01T23:06:50.9Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/9b/21d4c6b4ee9c1fa9691c68dc2a52565e0acb644b9e95148569b4736a4ebd/pymongo-4.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7bd26b2aec8ceeb95a5d948d5cc0f62b0eb6d66f3f4230705c1e3d3d2c04ec76", size = 943142, upload-time = "2024-10-01T23:06:52.146Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/af/691b7454e219a8eb2d1641aecedd607e3a94b93650c2011ad8a8fd74ef9f/pymongo-4.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb104c3c2a78d9d85571c8ac90ec4f95bca9b297c6eee5ada71fabf1129e1674", size = 1909129, upload-time = "2024-10-01T23:06:53.551Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/74/fd75d5ad4181d6e71ce0fca32404fb71b5046ac84d9a1a2f0862262dd032/pymongo-4.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4924355245a9c79f77b5cda2db36e0f75ece5faf9f84d16014c0a297f6d66786", size = 1987763, upload-time = "2024-10-01T23:06:55.304Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/56/6d3d0ef63c6d8cb98c7c653a3a2e617675f77a95f3853851d17a7664876a/pymongo-4.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:11280809e5dacaef4971113f0b4ff4696ee94cfdb720019ff4fa4f9635138252", size = 1950821, upload-time = "2024-10-01T23:06:57.541Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/ed/1603fa0c0e51444752c3fa91f16c3a97e6d92eb9fe5e553dae4f18df16f6/pymongo-4.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5d55f2a82e5eb23795f724991cac2bffbb1c0f219c0ba3bf73a835f97f1bb2e", size = 1912247, upload-time = "2024-10-01T23:06:59.023Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/66/e98b2308971d45667cb8179d4d66deca47336c90663a7e0527589f1038b7/pymongo-4.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e974ab16a60be71a8dfad4e5afccf8dd05d41c758060f5d5bda9a758605d9a5d", size = 1862230, upload-time = "2024-10-01T23:07:01.407Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/80/ba9b7ed212a5f8cf8ad7037ed5bbebc1c587fc09242108f153776e4a338b/pymongo-4.10.1-cp312-cp312-win32.whl", hash = "sha256:544890085d9641f271d4f7a47684450ed4a7344d6b72d5968bfae32203b1bb7c", size = 903045, upload-time = "2024-10-01T23:07:02.973Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/8b/5afce891d78159912c43726fab32641e3f9718f14be40f978c148ea8db48/pymongo-4.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:dcc07b1277e8b4bf4d7382ca133850e323b7ab048b8353af496d050671c7ac52", size = 926686, upload-time = "2024-10-01T23:07:04.403Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "8.4.1"
|
||||
version = "8.3.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "iniconfig" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pluggy" },
|
||||
{ name = "pygments" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-asyncio"
|
||||
version = "1.0.0"
|
||||
version = "0.25.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d0/d4/14f53324cb1a6381bef29d698987625d80052bb33932d8e7cbf9b337b17c/pytest_asyncio-1.0.0.tar.gz", hash = "sha256:d15463d13f4456e1ead2594520216b225a16f781e144f8fdf6c5bb4667c48b3f", size = 46960, upload-time = "2025-05-26T04:54:40.484Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f2/a8/ecbc8ede70921dd2f544ab1cadd3ff3bf842af27f87bbdea774c7baa1d38/pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a", size = 54239, upload-time = "2025-01-28T18:37:58.729Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/30/05/ce271016e351fddc8399e546f6e23761967ee09c8c568bbfbecb0c150171/pytest_asyncio-1.0.0-py3-none-any.whl", hash = "sha256:4f024da9f1ef945e680dc68610b52550e36590a67fd31bb3b4943979a1f90ef3", size = 15976, upload-time = "2025-05-26T04:54:39.035Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/17/3493c5624e48fd97156ebaec380dcaafee9506d7e2c46218ceebbb57d7de/pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3", size = 19467, upload-time = "2025-01-28T18:37:56.798Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-cov"
|
||||
version = "6.2.1"
|
||||
version = "6.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "coverage" },
|
||||
{ name = "pluggy" },
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/18/99/668cade231f434aaa59bbfbf49469068d2ddd945000621d3d165d2e7dd7b/pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", size = 69432, upload-time = "2025-06-12T10:47:47.684Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945, upload-time = "2024-10-29T20:13:35.363Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/16/4ea354101abb1287856baa4af2732be351c7bee728065aed451b678153fd/pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5", size = 24644, upload-time = "2025-06-12T10:47:45.932Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949, upload-time = "2024-10-29T20:13:33.215Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-xdist"
|
||||
version = "3.8.0"
|
||||
version = "3.6.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "execnet" },
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/41/c4/3c310a19bc1f1e9ef50075582652673ef2bfc8cd62afef9585683821902f/pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d", size = 84060, upload-time = "2024-04-28T19:29:54.414Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/82/1d96bf03ee4c0fdc3c0cbe61470070e659ca78dc0086fb88b66c185e2449/pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7", size = 46108, upload-time = "2024-04-28T19:29:52.813Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1402,11 +1344,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.1.1"
|
||||
version = "1.0.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115, upload-time = "2024-01-23T06:33:00.505Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863, upload-time = "2024-01-23T06:32:58.246Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1451,14 +1393,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "redis"
|
||||
version = "5.3.0"
|
||||
version = "5.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pyjwt" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/71/dd/2b37032f4119dff2a2f9bbcaade03221b100ba26051bb96e275de3e5db7a/redis-5.3.0.tar.gz", hash = "sha256:8d69d2dde11a12dc85d0dbf5c45577a5af048e2456f7077d87ad35c1c81c310e", size = 4626288, upload-time = "2025-04-30T14:54:40.634Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/47/da/d283a37303a995cd36f8b92db85135153dc4f7a8e4441aa827721b442cfb/redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f", size = 4608355, upload-time = "2024-12-06T09:50:41.956Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/45/b0/aa601efe12180ba492b02e270554877e68467e66bda5d73e51eaa8ecc78a/redis-5.3.0-py3-none-any.whl", hash = "sha256:f1deeca1ea2ef25c1e4e46b07f4ea1275140526b1feea4c6459c0ec27a10ef83", size = 272836, upload-time = "2025-04-30T14:54:30.744Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/5f/fa26b9b2672cbe30e07d9a5bdf39cf16e3b80b42916757c5f92bca88e4ba/redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4", size = 261502, upload-time = "2024-12-06T09:50:39.656Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1513,27 +1452,28 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.12.2"
|
||||
version = "0.12.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4a/45/2e403fa7007816b5fbb324cb4f8ed3c7402a927a0a0cb2b6279879a8bfdc/ruff-0.12.9.tar.gz", hash = "sha256:fbd94b2e3c623f659962934e52c2bea6fc6da11f667a427a368adaf3af2c866a", size = 5254702, upload-time = "2025-08-14T16:08:55.2Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/20/53bf098537adb7b6a97d98fcdebf6e916fcd11b2e21d15f8c171507909cc/ruff-0.12.9-py3-none-linux_armv6l.whl", hash = "sha256:fcebc6c79fcae3f220d05585229463621f5dbf24d79fdc4936d9302e177cfa3e", size = 11759705, upload-time = "2025-08-14T16:08:12.968Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/4d/c764ee423002aac1ec66b9d541285dd29d2c0640a8086c87de59ebbe80d5/ruff-0.12.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aed9d15f8c5755c0e74467731a007fcad41f19bcce41cd75f768bbd687f8535f", size = 12527042, upload-time = "2025-08-14T16:08:16.54Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/45/cfcdf6d3eb5fc78a5b419e7e616d6ccba0013dc5b180522920af2897e1be/ruff-0.12.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5b15ea354c6ff0d7423814ba6d44be2807644d0c05e9ed60caca87e963e93f70", size = 11724457, upload-time = "2025-08-14T16:08:18.686Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/e6/44615c754b55662200c48bebb02196dbb14111b6e266ab071b7e7297b4ec/ruff-0.12.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d596c2d0393c2502eaabfef723bd74ca35348a8dac4267d18a94910087807c53", size = 11949446, upload-time = "2025-08-14T16:08:21.059Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/d1/9b7d46625d617c7df520d40d5ac6cdcdf20cbccb88fad4b5ecd476a6bb8d/ruff-0.12.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b15599931a1a7a03c388b9c5df1bfa62be7ede6eb7ef753b272381f39c3d0ff", size = 11566350, upload-time = "2025-08-14T16:08:23.433Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/20/b73132f66f2856bc29d2d263c6ca457f8476b0bbbe064dac3ac3337a270f/ruff-0.12.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3d02faa2977fb6f3f32ddb7828e212b7dd499c59eb896ae6c03ea5c303575756", size = 13270430, upload-time = "2025-08-14T16:08:25.837Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/21/eaf3806f0a3d4c6be0a69d435646fba775b65f3f2097d54898b0fd4bb12e/ruff-0.12.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:17d5b6b0b3a25259b69ebcba87908496e6830e03acfb929ef9fd4c58675fa2ea", size = 14264717, upload-time = "2025-08-14T16:08:27.907Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/82/1d0c53bd37dcb582b2c521d352fbf4876b1e28bc0d8894344198f6c9950d/ruff-0.12.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:72db7521860e246adbb43f6ef464dd2a532ef2ef1f5dd0d470455b8d9f1773e0", size = 13684331, upload-time = "2025-08-14T16:08:30.352Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/2f/1c5cf6d8f656306d42a686f1e207f71d7cebdcbe7b2aa18e4e8a0cb74da3/ruff-0.12.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a03242c1522b4e0885af63320ad754d53983c9599157ee33e77d748363c561ce", size = 12739151, upload-time = "2025-08-14T16:08:32.55Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/09/25033198bff89b24d734e6479e39b1968e4c992e82262d61cdccaf11afb9/ruff-0.12.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fc83e4e9751e6c13b5046d7162f205d0a7bac5840183c5beebf824b08a27340", size = 12954992, upload-time = "2025-08-14T16:08:34.816Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/8e/d0dbf2f9dca66c2d7131feefc386523404014968cd6d22f057763935ab32/ruff-0.12.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:881465ed56ba4dd26a691954650de6ad389a2d1fdb130fe51ff18a25639fe4bb", size = 12899569, upload-time = "2025-08-14T16:08:36.852Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/bd/b614d7c08515b1428ed4d3f1d4e3d687deffb2479703b90237682586fa66/ruff-0.12.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:43f07a3ccfc62cdb4d3a3348bf0588358a66da756aa113e071b8ca8c3b9826af", size = 11751983, upload-time = "2025-08-14T16:08:39.314Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/d6/383e9f818a2441b1a0ed898d7875f11273f10882f997388b2b51cb2ae8b5/ruff-0.12.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:07adb221c54b6bba24387911e5734357f042e5669fa5718920ee728aba3cbadc", size = 11538635, upload-time = "2025-08-14T16:08:41.297Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/9c/56f869d314edaa9fc1f491706d1d8a47747b9d714130368fbd69ce9024e9/ruff-0.12.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f5cd34fabfdea3933ab85d72359f118035882a01bff15bd1d2b15261d85d5f66", size = 12534346, upload-time = "2025-08-14T16:08:43.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/4b/d8b95c6795a6c93b439bc913ee7a94fda42bb30a79285d47b80074003ee7/ruff-0.12.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f6be1d2ca0686c54564da8e7ee9e25f93bdd6868263805f8c0b8fc6a449db6d7", size = 13017021, upload-time = "2025-08-14T16:08:45.889Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/c1/5f9a839a697ce1acd7af44836f7c2181cdae5accd17a5cb85fcbd694075e/ruff-0.12.9-py3-none-win32.whl", hash = "sha256:cc7a37bd2509974379d0115cc5608a1a4a6c4bff1b452ea69db83c8855d53f93", size = 11734785, upload-time = "2025-08-14T16:08:48.062Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/66/cdddc2d1d9a9f677520b7cfc490d234336f523d4b429c1298de359a3be08/ruff-0.12.9-py3-none-win_amd64.whl", hash = "sha256:6fb15b1977309741d7d098c8a3cb7a30bc112760a00fb6efb7abc85f00ba5908", size = 12840654, upload-time = "2025-08-14T16:08:50.158Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/fd/669816bc6b5b93b9586f3c1d87cd6bc05028470b3ecfebb5938252c47a35/ruff-0.12.9-py3-none-win_arm64.whl", hash = "sha256:63c8c819739d86b96d500cce885956a1a48ab056bbcbc61b747ad494b2485089", size = 11949623, upload-time = "2025-08-14T16:08:52.233Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
ARG BASE_IMAGE=ubuntu:24.04
|
||||
|
||||
FROM $BASE_IMAGE AS base
|
||||
RUN apt-get update && apt-get install -y software-properties-common
|
||||
RUN add-apt-repository ppa:deadsnakes/ppa
|
||||
RUN apt-get update && apt-get install -y python3.10 curl
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y software-properties-common \
|
||||
&& add-apt-repository ppa:deadsnakes/ppa \
|
||||
&& apt-get update && apt-get install -y python3.12 curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
RUN curl -fsSL https://get.docker.com | sh
|
||||
|
||||
FROM base AS builder
|
||||
@@ -12,7 +13,7 @@ COPY --from=ghcr.io/astral-sh/uv:0.5.20 /uv /uvx /bin/
|
||||
ENV UV_LINK_MODE=copy \
|
||||
UV_COMPILE_BYTECODE=1 \
|
||||
UV_PYTHON_DOWNLOADS=never \
|
||||
UV_PYTHON=python3.10
|
||||
UV_PYTHON=python3.12
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -32,7 +33,8 @@ RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv sync --frozen --no-editable
|
||||
|
||||
FROM base AS cscope-builder
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y autoconf gcc make bison flex libncurses-dev
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y autoconf gcc make bison flex libncurses-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
COPY external/buttercup-cscope /cscope
|
||||
RUN cd /cscope && autoreconf -i -s && ./configure && make && make install
|
||||
|
||||
|
||||
@@ -3,14 +3,15 @@ name = "program-model"
|
||||
version = "0.1.0"
|
||||
description = "Buttercup contextualizer"
|
||||
readme = "README.md"
|
||||
authors = [{ name = "Trail of Bits", email = "opensource@trailofbits" }]
|
||||
requires-python = ">=3.10,<3.13"
|
||||
authors = [{ name = "Trail of Bits", email = "opensource@trailofbits.com" }]
|
||||
license = "AGPL-3.0-only"
|
||||
requires-python = ">=3.12,<3.13"
|
||||
dependencies = [
|
||||
"common",
|
||||
"protobuf (>=3.20, <=3.20.3)",
|
||||
"tree-sitter>=0.24.0",
|
||||
"tree-sitter-language-pack>=0.4.0",
|
||||
"rapidfuzz ~= 3.12.2",
|
||||
"protobuf ==3.20.3", # Pin exactly for stability
|
||||
"tree-sitter ~=0.24.0",
|
||||
"tree-sitter-language-pack ~=0.9.0",
|
||||
"rapidfuzz ~=3.12.2",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
@@ -27,8 +28,45 @@ requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/trailofbits/buttercup"
|
||||
Issues = "https://github.com/trailofbits/buttercup/issues"
|
||||
|
||||
[dependency-groups]
|
||||
dev = ["pytest>=8.3.4", "ruff>=0.9.2", "mypy>=1.15.0"]
|
||||
dev = [
|
||||
# Testing tools
|
||||
"pytest ~=8.3.4",
|
||||
"pytest-cov ~=6.0.0",
|
||||
# Linting and type checking
|
||||
"ruff ~=0.12.8",
|
||||
"mypy ~=1.17.1",
|
||||
# Type stubs
|
||||
"types-redis ~=4.6.0",
|
||||
]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
target-version = "py312"
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "I", "W", "UP"]
|
||||
ignore = [
|
||||
"COM812",
|
||||
"ISC001", # Formatter conflicts
|
||||
# Temporarily disabled for standardization PR - re-enable after refactoring:
|
||||
"I001", # Import block is un-sorted or un-formatted
|
||||
"E501", # Line too long
|
||||
"W291", # Trailing whitespace
|
||||
"UP006", # Use built-in collection types for type annotations
|
||||
"UP015", # Unnecessary mode argument
|
||||
"UP032", # Use f-string instead of format call
|
||||
"UP035", # Import from modern locations instead of deprecated typing
|
||||
"UP045", # Use X | None for type annotations
|
||||
"UP046", # Use modern generic class syntax
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"tests/**/*.py" = ["S101", "D"] # Allow asserts, no docstrings in tests
|
||||
|
||||
[tool.mypy]
|
||||
plugins = ["pydantic.mypy"]
|
||||
|
||||
@@ -26,9 +26,7 @@ def prepare_task(command: ProcessCommand) -> IndexRequest:
|
||||
def main() -> None:
|
||||
settings = Settings()
|
||||
command = get_subcommand(settings)
|
||||
setup_package_logger(
|
||||
"program-model", __name__, settings.log_level, settings.log_max_line_length
|
||||
)
|
||||
setup_package_logger("program-model", __name__, settings.log_level, settings.log_max_line_length)
|
||||
if isinstance(command, ServeCommand):
|
||||
init_telemetry("program-model") # type: ignore[unreachable]
|
||||
redis = Redis.from_url(command.redis_url, decode_responses=False)
|
||||
|
||||
@@ -48,9 +48,7 @@ class FuzzyCImportsResolver:
|
||||
path = (self.root_dir / path).resolve()
|
||||
return path
|
||||
|
||||
def _find_file_in_codebase(
|
||||
self, import_name: str, origin_file: Path
|
||||
) -> Optional[Path]:
|
||||
def _find_file_in_codebase(self, import_name: str, origin_file: Path) -> Optional[Path]:
|
||||
"""
|
||||
Find the actual file path for an imported file name.
|
||||
This method handles different include styles:
|
||||
@@ -120,9 +118,7 @@ class FuzzyCImportsResolver:
|
||||
import_files_candidates = [import_name, import_name + ".in"]
|
||||
|
||||
for file_candidate in import_files_candidates:
|
||||
resolved_path = self._find_file_in_codebase(
|
||||
file_candidate, file_path
|
||||
)
|
||||
resolved_path = self._find_file_in_codebase(file_candidate, file_path)
|
||||
if resolved_path:
|
||||
imports.add(resolved_path)
|
||||
break
|
||||
@@ -134,9 +130,7 @@ class FuzzyCImportsResolver:
|
||||
print(f"Error parsing {file_path}: {e}")
|
||||
return set()
|
||||
|
||||
def get_all_imports(
|
||||
self, file_path: Path, depth: Optional[int] = None
|
||||
) -> Set[Path]:
|
||||
def get_all_imports(self, file_path: Path, depth: Optional[int] = None) -> Set[Path]:
|
||||
"""
|
||||
Recursively get all files imported by a given file.
|
||||
|
||||
@@ -156,9 +150,7 @@ class FuzzyCImportsResolver:
|
||||
self.all_imports_cache[file_path] = self._tmp_imports
|
||||
return self._tmp_imports
|
||||
|
||||
def _get_all_imports_recursive(
|
||||
self, file_path: Path, depth: Optional[int], current_depth: int = 0
|
||||
) -> None:
|
||||
def _get_all_imports_recursive(self, file_path: Path, depth: Optional[int], current_depth: int = 0) -> None:
|
||||
"""
|
||||
Recursive helper for get_all_imports.
|
||||
|
||||
@@ -192,9 +184,7 @@ class FuzzyCImportsResolver:
|
||||
all_imports = self.get_all_imports(self._normalize_path(file_path))
|
||||
return self._normalize_path(imported_file_path) in all_imports
|
||||
|
||||
def filter_callees(
|
||||
self, caller_function: Function, callees: list[Function]
|
||||
) -> list[Function]:
|
||||
def filter_callees(self, caller_function: Function, callees: list[Function]) -> list[Function]:
|
||||
"""This filters callees found for a given function. This function is used to deduplicate
|
||||
callees when several are found with identical names. This happens because Codequery does a
|
||||
syntactic search only and can't resolve which function is actually imported and called
|
||||
@@ -235,9 +225,7 @@ class FuzzyCImportsResolver:
|
||||
]
|
||||
# For each potential declaration file, see whether it is imported by the caller
|
||||
for decl_file in possible_decl_files:
|
||||
if self.is_file_imported_by(
|
||||
decl_file, caller_function.file_path
|
||||
):
|
||||
if self.is_file_imported_by(decl_file, caller_function.file_path):
|
||||
res.append(callee)
|
||||
added = True
|
||||
break
|
||||
@@ -290,13 +278,9 @@ class FuzzyJavaImportsResolver:
|
||||
# Path where the challenge source is mounted in the ossfuzz repo
|
||||
# according to docker file
|
||||
if challenge:
|
||||
self.container_code_path = Path(
|
||||
str(challenge.workdir_from_dockerfile())[1:]
|
||||
)
|
||||
self.container_code_path = Path(str(challenge.workdir_from_dockerfile())[1:])
|
||||
# Path where the challenge source is on the local machine
|
||||
self.local_code_path = (
|
||||
challenge.task_dir / "container_src_dir" / "src" / challenge.focus
|
||||
)
|
||||
self.local_code_path = challenge.task_dir / "container_src_dir" / "src" / challenge.focus
|
||||
self.codequery = codequery
|
||||
|
||||
def get_package_from_file(self, file_path: Path) -> str | None:
|
||||
@@ -335,9 +319,7 @@ class FuzzyJavaImportsResolver:
|
||||
# Get path of file from where the import is made
|
||||
# TODO(boyan): make sure we can assume files end with .java here
|
||||
# First transform import statement to corresponding file in the code base
|
||||
imported_file = (
|
||||
"../" * (file_package.count(".") + 1) + imp.replace(".", "/") + ".java"
|
||||
)
|
||||
imported_file = "../" * (file_package.count(".") + 1) + imp.replace(".", "/") + ".java"
|
||||
imported_file = (file_path.parent / imported_file).resolve()
|
||||
# Then try to get type from that file and return it
|
||||
return self.get_type_from_file(imported_file, dotexpr)
|
||||
@@ -361,14 +343,10 @@ class FuzzyJavaImportsResolver:
|
||||
return res
|
||||
elif expr_type == "method":
|
||||
# TODO(boyan): resolve class methods, here we assume it's a method
|
||||
method_return_type_name = self.get_method_return_type_name(
|
||||
prefix_type, suffix
|
||||
)
|
||||
method_return_type_name = self.get_method_return_type_name(prefix_type, suffix)
|
||||
if method_return_type_name is None:
|
||||
return None
|
||||
res = self.get_dotexpr_type(
|
||||
method_return_type_name, prefix_type.file_path
|
||||
)
|
||||
res = self.get_dotexpr_type(method_return_type_name, prefix_type.file_path)
|
||||
return res
|
||||
else:
|
||||
# Should not happen
|
||||
@@ -424,21 +402,15 @@ class FuzzyJavaImportsResolver:
|
||||
type_name = self.codequery.ts.get_field_type_name(type_body, field_name)
|
||||
return type_name # type: ignore[no-any-return]
|
||||
|
||||
def get_method_return_type_name(
|
||||
self, t: TypeDefinition, method_name: str
|
||||
) -> str | None:
|
||||
def get_method_return_type_name(self, t: TypeDefinition, method_name: str) -> str | None:
|
||||
"""
|
||||
Parse the type definition to find the method return type name
|
||||
"""
|
||||
type_body = t.definition.encode("utf-8")
|
||||
type_name = self.codequery.ts.get_method_return_type_name(
|
||||
type_body, method_name
|
||||
)
|
||||
type_name = self.codequery.ts.get_method_return_type_name(type_body, method_name)
|
||||
return type_name # type: ignore[no-any-return]
|
||||
|
||||
def get_type_from_file(
|
||||
self, file_path: Path, type_name: str
|
||||
) -> TypeDefinition | None:
|
||||
def get_type_from_file(self, file_path: Path, type_name: str) -> TypeDefinition | None:
|
||||
"""
|
||||
Get the type definition given a type name and a file path
|
||||
file_path must a container path (e.g. /src/log4j-core/...)
|
||||
@@ -452,9 +424,7 @@ class FuzzyJavaImportsResolver:
|
||||
# Return first type found
|
||||
return types[0] # type: ignore[no-any-return]
|
||||
|
||||
def filter_callees(
|
||||
self, caller_function: Function, callees: List[Function]
|
||||
) -> List[Function]:
|
||||
def filter_callees(self, caller_function: Function, callees: List[Function]) -> List[Function]:
|
||||
callee_groups = defaultdict(list)
|
||||
for callee in callees:
|
||||
callee_groups[callee.name].append(callee)
|
||||
@@ -472,17 +442,12 @@ class FuzzyJavaImportsResolver:
|
||||
# Get call "prefixes". If a method is called with a.b.c.d() the prefix
|
||||
# is a.b.c. We use this to determine which class or file the d() method
|
||||
# belongs to
|
||||
prefixes = self.try_extract_call_expr_prefix(
|
||||
caller_function, callee_name
|
||||
)
|
||||
prefixes = self.try_extract_call_expr_prefix(caller_function, callee_name)
|
||||
if not prefixes:
|
||||
continue
|
||||
|
||||
# Get all types for prefixes found
|
||||
prefixes_types = [
|
||||
self.get_dotexpr_type(prefix, caller_function.file_path)
|
||||
for prefix in prefixes
|
||||
]
|
||||
prefixes_types = [self.get_dotexpr_type(prefix, caller_function.file_path) for prefix in prefixes]
|
||||
# Filter out None types (couldn't find the type)
|
||||
prefixes_types = [t for t in prefixes_types if t is not None]
|
||||
if not prefixes_types:
|
||||
@@ -507,9 +472,7 @@ class FuzzyJavaImportsResolver:
|
||||
|
||||
return res
|
||||
|
||||
def filter_callees2(
|
||||
self, caller_function: Function, callees: List[Function]
|
||||
) -> List[Function]:
|
||||
def filter_callees2(self, caller_function: Function, callees: List[Function]) -> List[Function]:
|
||||
callee_groups = defaultdict(list)
|
||||
for callee in callees:
|
||||
callee_groups[callee.name].append(callee)
|
||||
@@ -524,15 +487,11 @@ class FuzzyJavaImportsResolver:
|
||||
# Multiple callees with same name, check which ones are actually imported
|
||||
# Do only once per name...
|
||||
# Get imports from the caller file
|
||||
imports = self.parse_imports_in_file(
|
||||
self._normalize_path(caller_function.file_path)
|
||||
)
|
||||
imports = self.parse_imports_in_file(self._normalize_path(caller_function.file_path))
|
||||
# Get call "prefixes". If a method is called with a.b.c.d() the prefix
|
||||
# is a.b.c. We use this to determine which class or file the d() method
|
||||
# belongs to
|
||||
prefixes = self.try_extract_call_expr_prefix(
|
||||
caller_function, callee_name
|
||||
)
|
||||
prefixes = self.try_extract_call_expr_prefix(caller_function, callee_name)
|
||||
if not prefixes or not imports:
|
||||
continue
|
||||
# Keep only imports that match prefixes for that function name
|
||||
@@ -541,11 +500,7 @@ class FuzzyJavaImportsResolver:
|
||||
|
||||
# TODO(boyan): need to refactor this when we support recursively
|
||||
# exploring the prefixes with multiple dots
|
||||
imports = [
|
||||
imp
|
||||
for imp in imports
|
||||
if any(pref for pref in prefixes if imp.endswith(f".{pref}"))
|
||||
]
|
||||
imports = [imp for imp in imports if any(pref for pref in prefixes if imp.endswith(f".{pref}"))]
|
||||
|
||||
# At this point we have only imports that match with the prefix of a called
|
||||
# function with name callee_name in the caller body, we now proceed to add any callee
|
||||
@@ -553,13 +508,8 @@ class FuzzyJavaImportsResolver:
|
||||
for imp in imports:
|
||||
# TODO(boyan): make sure we can assume files end with .java here
|
||||
# First transform import statement to corresponding file in the code base
|
||||
imported_file = (
|
||||
"../" * (imp.count(".") + 1) + imp.replace(".", "/") + ".java"
|
||||
)
|
||||
imported_file = (
|
||||
self._normalize_path(caller_function.file_path.parent)
|
||||
/ imported_file
|
||||
)
|
||||
imported_file = "../" * (imp.count(".") + 1) + imp.replace(".", "/") + ".java"
|
||||
imported_file = self._normalize_path(caller_function.file_path.parent) / imported_file
|
||||
imported_file = imported_file.resolve()
|
||||
for callee in group:
|
||||
added = False
|
||||
@@ -583,9 +533,7 @@ class FuzzyJavaImportsResolver:
|
||||
res += group
|
||||
return res
|
||||
|
||||
def try_extract_call_expr_prefix(
|
||||
self, caller: Function, callee_name: str
|
||||
) -> list[str]:
|
||||
def try_extract_call_expr_prefix(self, caller: Function, callee_name: str) -> list[str]:
|
||||
"""
|
||||
Try to extract all call prefixes of a function called in the caller body.
|
||||
If the caller is:
|
||||
|
||||
@@ -228,9 +228,7 @@ class CodeTS:
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
"""Initialize the CodeTS object."""
|
||||
self.project_yaml = ProjectYaml(
|
||||
self.challenge_task, self.challenge_task.task_meta.project_name
|
||||
)
|
||||
self.project_yaml = ProjectYaml(self.challenge_task, self.challenge_task.task_meta.project_name)
|
||||
if self.project_yaml.unified_language == Language.C:
|
||||
self.parser = get_parser("c")
|
||||
self.language = get_language("c")
|
||||
@@ -252,18 +250,12 @@ class CodeTS:
|
||||
try:
|
||||
self.query = self.language.query(query_str)
|
||||
self.query_types = self.language.query(types_query_str)
|
||||
self.query_class_members = (
|
||||
self.language.query(query_class_members)
|
||||
if query_class_members
|
||||
else None
|
||||
)
|
||||
self.query_class_members = self.language.query(query_class_members) if query_class_members else None
|
||||
except Exception:
|
||||
raise ValueError("Query string is invalid")
|
||||
|
||||
self.preprocess_keywords = ["ifdef", "ifndef", "if", "else", "elif", "endif"]
|
||||
self.preprocess_regex = [
|
||||
r"^#\s*{kw}\s*".format(kw=kw) for kw in self.preprocess_keywords
|
||||
]
|
||||
self.preprocess_regex = [r"^#\s*{kw}\s*".format(kw=kw) for kw in self.preprocess_keywords]
|
||||
|
||||
def get_functions(self, file_path: Path) -> dict[str, Function]:
|
||||
"""Parse the functions in a file and return a dictionary of function names/body"""
|
||||
@@ -274,18 +266,12 @@ class CodeTS:
|
||||
"""Remove preprocessor directives from the code"""
|
||||
return (b"\n").join(
|
||||
[
|
||||
x
|
||||
if not any(
|
||||
re.match(pattern, x.decode()) for pattern in self.preprocess_regex
|
||||
)
|
||||
else b"/" * len(x)
|
||||
x if not any(re.match(pattern, x.decode()) for pattern in self.preprocess_regex) else b"/" * len(x)
|
||||
for x in code.splitlines()
|
||||
]
|
||||
)
|
||||
|
||||
def get_functions_in_code(
|
||||
self, code: bytes, file_path: Path
|
||||
) -> dict[str, Function]:
|
||||
def get_functions_in_code(self, code: bytes, file_path: Path) -> dict[str, Function]:
|
||||
"""Parse the functions in a piece of code and return a dictionary of function names/body"""
|
||||
if self.project_yaml.unified_language == Language.C:
|
||||
code_no_preproc = self._get_code_no_preproc(code)
|
||||
@@ -314,16 +300,11 @@ class CodeTS:
|
||||
function_name = code[name_node.start_byte : name_node.end_byte]
|
||||
function_definition = definition_node
|
||||
start_body = function_definition
|
||||
if (
|
||||
start_body.prev_named_sibling
|
||||
and start_body.prev_named_sibling.type == "comment"
|
||||
):
|
||||
if start_body.prev_named_sibling and start_body.prev_named_sibling.type == "comment":
|
||||
start_body = start_body.prev_named_sibling
|
||||
|
||||
function_body_start = start_body.start_byte
|
||||
while function_body_start > 0 and code[function_body_start - 1] != ord(
|
||||
"\n"
|
||||
):
|
||||
while function_body_start > 0 and code[function_body_start - 1] != ord("\n"):
|
||||
function_body_start -= 1
|
||||
|
||||
function_body_end = function_definition.end_byte
|
||||
@@ -331,9 +312,7 @@ class CodeTS:
|
||||
function_body_end = body_node.end_byte
|
||||
|
||||
# find the end of the line for the function body
|
||||
while function_body_end < len(code) and code[function_body_end] != ord(
|
||||
"\n"
|
||||
):
|
||||
while function_body_end < len(code) and code[function_body_end] != ord("\n"):
|
||||
function_body_end += 1
|
||||
|
||||
# Convert start and end points to 1-based line numbers.
|
||||
@@ -443,9 +422,7 @@ class CodeTS:
|
||||
elif definition_node.type == "interface_declaration":
|
||||
type_def_type = TypeDefinitionType.CLASS
|
||||
else:
|
||||
logger.debug(
|
||||
f"Unknown type definition node type: {definition_node.type}"
|
||||
)
|
||||
logger.debug(f"Unknown type definition node type: {definition_node.type}")
|
||||
continue # Skip this define as it doesn't look like a type
|
||||
|
||||
res[name] = TypeDefinition(
|
||||
@@ -496,9 +473,7 @@ class CodeTS:
|
||||
# Print grandparent's siblings
|
||||
siblings = grandparent.parent.children
|
||||
for sibling in siblings:
|
||||
logger.debug(
|
||||
"Sibling : %s - %s", sibling.type, sibling.text.decode()
|
||||
)
|
||||
logger.debug("Sibling : %s - %s", sibling.type, sibling.text.decode())
|
||||
# Print sibling's children
|
||||
for child in sibling.children:
|
||||
logger.debug(
|
||||
@@ -539,9 +514,7 @@ class CodeTS:
|
||||
|
||||
walk(root_node)
|
||||
|
||||
def get_field_type_name(
|
||||
self, type_definition: bytes, field_name: str
|
||||
) -> str | None:
|
||||
def get_field_type_name(self, type_definition: bytes, field_name: str) -> str | None:
|
||||
"""
|
||||
Get the type of a field of a type definition
|
||||
"""
|
||||
@@ -561,9 +534,7 @@ class CodeTS:
|
||||
continue
|
||||
return None
|
||||
|
||||
def get_method_return_type_name(
|
||||
self, type_definition: bytes, method_name: str
|
||||
) -> str | None:
|
||||
def get_method_return_type_name(self, type_definition: bytes, method_name: str) -> str | None:
|
||||
"""
|
||||
Get the return type of a method of a type definition
|
||||
"""
|
||||
|
||||
@@ -130,9 +130,7 @@ class CodeQuery:
|
||||
|
||||
challenge: ChallengeTask
|
||||
ts: CodeTS = field(init=False)
|
||||
imports_resolver: Optional[FuzzyCImportsResolver | FuzzyJavaImportsResolver] = (
|
||||
field(init=False)
|
||||
)
|
||||
imports_resolver: Optional[FuzzyCImportsResolver | FuzzyJavaImportsResolver] = field(init=False)
|
||||
|
||||
CSCOPE_FILES: ClassVar[str] = "cscope.files"
|
||||
CSCOPE_OUT: ClassVar[str] = "cscope.out"
|
||||
@@ -156,9 +154,7 @@ class CodeQuery:
|
||||
return
|
||||
|
||||
if self.challenge.local_task_dir is None:
|
||||
raise ValueError(
|
||||
"Challenge Task is read-only, cannot perform this operation"
|
||||
)
|
||||
raise ValueError("Challenge Task is read-only, cannot perform this operation")
|
||||
|
||||
self._create_codequery_db()
|
||||
logger.debug("CodeQuery DB created successfully.")
|
||||
@@ -180,9 +176,7 @@ class CodeQuery:
|
||||
raise RuntimeError("No code query package")
|
||||
|
||||
def _get_project_language(self) -> Language:
|
||||
project_yaml = ProjectYaml(
|
||||
self.challenge, self.challenge.task_meta.project_name
|
||||
)
|
||||
project_yaml = ProjectYaml(self.challenge, self.challenge.task_meta.project_name)
|
||||
return project_yaml.unified_language
|
||||
|
||||
def _is_already_indexed(self) -> bool:
|
||||
@@ -232,9 +226,7 @@ class CodeQuery:
|
||||
self._copy_src_from_container()
|
||||
|
||||
with self._get_container_src_dir().joinpath(self.CSCOPE_FILES).open("w") as f:
|
||||
project_yaml = ProjectYaml(
|
||||
self.challenge, self.challenge.task_meta.project_name
|
||||
)
|
||||
project_yaml = ProjectYaml(self.challenge, self.challenge.task_meta.project_name)
|
||||
if project_yaml.unified_language == Language.C:
|
||||
extensions = C_CPP_EXTENSIONS
|
||||
elif project_yaml.unified_language == Language.JAVA:
|
||||
@@ -332,9 +324,7 @@ class CodeQuery:
|
||||
for function in functions
|
||||
]
|
||||
|
||||
def _rebase_types_file_paths(
|
||||
self, types: list[TypeDefinition]
|
||||
) -> list[TypeDefinition]:
|
||||
def _rebase_types_file_paths(self, types: list[TypeDefinition]) -> list[TypeDefinition]:
|
||||
"""Rebase the file paths of the types to the challenge task container structure."""
|
||||
return [
|
||||
TypeDefinition(
|
||||
@@ -347,9 +337,7 @@ class CodeQuery:
|
||||
for td in types
|
||||
]
|
||||
|
||||
def _rebase_type_usages_file_paths(
|
||||
self, type_usages: list[TypeUsageInfo]
|
||||
) -> list[TypeUsageInfo]:
|
||||
def _rebase_type_usages_file_paths(self, type_usages: list[TypeUsageInfo]) -> list[TypeUsageInfo]:
|
||||
"""Rebase the file paths of the types to the challenge task container structure."""
|
||||
return [
|
||||
TypeUsageInfo(
|
||||
@@ -362,21 +350,11 @@ class CodeQuery:
|
||||
|
||||
def _get_all_functions(self) -> list[CQSearchResult]:
|
||||
"""Get all functions in the codebase."""
|
||||
return [
|
||||
f
|
||||
for f in self._run_cqsearch(
|
||||
"-s", self.CODEQUERY_DB, "-p", "2", "-t", "*", "-u"
|
||||
)
|
||||
]
|
||||
return [f for f in self._run_cqsearch("-s", self.CODEQUERY_DB, "-p", "2", "-t", "*", "-u")]
|
||||
|
||||
def _get_all_types(self) -> list[CQSearchResult]:
|
||||
"""Get all symbols in the codebase."""
|
||||
return [
|
||||
t
|
||||
for t in self._run_cqsearch(
|
||||
"-s", self.CODEQUERY_DB, "-p", "1", "-t", "*", "-u"
|
||||
)
|
||||
]
|
||||
return [t for t in self._run_cqsearch("-s", self.CODEQUERY_DB, "-p", "1", "-t", "*", "-u")]
|
||||
|
||||
def get_functions(
|
||||
self,
|
||||
@@ -443,8 +421,7 @@ class CodeQuery:
|
||||
[
|
||||
(f, rapidfuzz.fuzz.ratio(function_name, f.value))
|
||||
for f in self._get_all_functions()
|
||||
if f.value
|
||||
and rapidfuzz.fuzz.ratio(function_name, f.value) > fuzzy_threshold
|
||||
if f.value and rapidfuzz.fuzz.ratio(function_name, f.value) > fuzzy_threshold
|
||||
],
|
||||
key=lambda x: x[1],
|
||||
reverse=True,
|
||||
@@ -479,11 +456,7 @@ class CodeQuery:
|
||||
# NOTE(boyan): We check whether the supplied line to look up for the function
|
||||
# is contained within at least one of the function bodies found by
|
||||
# tree-sitter
|
||||
if any(
|
||||
True
|
||||
for start_line, end_line in lines
|
||||
if start_line <= line_number <= end_line
|
||||
):
|
||||
if any(True for start_line, end_line in lines if start_line <= line_number <= end_line):
|
||||
res.add(f)
|
||||
else:
|
||||
res.add(f)
|
||||
@@ -498,15 +471,11 @@ class CodeQuery:
|
||||
|
||||
# Sort in same order as results
|
||||
results_value = [r.value for r in results]
|
||||
res_sorted: list[Function] = sorted(
|
||||
res, key=lambda x: results_value.index(x.name)
|
||||
)
|
||||
res_sorted: list[Function] = sorted(res, key=lambda x: results_value.index(x.name))
|
||||
|
||||
return self._rebase_functions_file_paths(res_sorted)
|
||||
|
||||
def _filter_callees(
|
||||
self, caller_function: Function, callees: list[Function]
|
||||
) -> list[Function]:
|
||||
def _filter_callees(self, caller_function: Function, callees: list[Function]) -> list[Function]:
|
||||
# If no resolver available, don't filter anything
|
||||
if not self.imports_resolver:
|
||||
return callees
|
||||
@@ -653,9 +622,7 @@ class CodeQuery:
|
||||
# Create a dictionary of file path(s) and line ranges to filter callees by.
|
||||
callee_filter: dict[Path, list[tuple[int, int]]] = {}
|
||||
for function in functions:
|
||||
callee_filter[function.file_path] = [
|
||||
(b.start_line, b.end_line) for b in function.bodies
|
||||
]
|
||||
callee_filter[function.file_path] = [(b.start_line, b.end_line) for b in function.bodies]
|
||||
|
||||
callees: set[Function] = set()
|
||||
for result in results:
|
||||
@@ -669,10 +636,7 @@ class CodeQuery:
|
||||
continue
|
||||
|
||||
# If the callee is called at a line number we're looking for.
|
||||
if not any(
|
||||
line_range[0] <= result.line <= line_range[1]
|
||||
for line_range in callee_filter[rebased_path]
|
||||
):
|
||||
if not any(line_range[0] <= result.line <= line_range[1] for line_range in callee_filter[rebased_path]):
|
||||
continue
|
||||
|
||||
# Now find the function definition of the callee
|
||||
@@ -761,9 +725,7 @@ class CodeQuery:
|
||||
"crs.action.code.file": str(file_path) if file_path else "",
|
||||
"crs.action.code.fuzzy": fuzzy if fuzzy else False,
|
||||
"crs.action.code.type_name": type_name,
|
||||
"crs.action.code.function_name": function_name
|
||||
if function_name
|
||||
else "",
|
||||
"crs.action.code.function_name": function_name if function_name else "",
|
||||
},
|
||||
)
|
||||
results.extend(self._run_cqsearch(*cqsearch_args))
|
||||
@@ -776,8 +738,7 @@ class CodeQuery:
|
||||
[
|
||||
(t, rapidfuzz.fuzz.ratio(type_name, t.value))
|
||||
for t in self._get_all_types()
|
||||
if t.value
|
||||
and rapidfuzz.fuzz.ratio(type_name, t.value) > fuzzy_threshold
|
||||
if t.value and rapidfuzz.fuzz.ratio(type_name, t.value) > fuzzy_threshold
|
||||
],
|
||||
key=lambda x: x[1],
|
||||
reverse=True,
|
||||
@@ -815,11 +776,7 @@ class CodeQuery:
|
||||
for name, typedef in typedefs.items():
|
||||
# Check if the type definition is within the function's scope
|
||||
for body in function.bodies:
|
||||
if (
|
||||
body.start_line
|
||||
<= typedef.definition_line
|
||||
<= body.end_line
|
||||
):
|
||||
if body.start_line <= typedef.definition_line <= body.end_line:
|
||||
filtered_typedefs[name] = typedef
|
||||
break
|
||||
typedefs = filtered_typedefs
|
||||
@@ -837,9 +794,7 @@ class CodeQuery:
|
||||
|
||||
# Sort in same order as results
|
||||
results_value = [r.value for r in results]
|
||||
res_sorted: list[TypeDefinition] = sorted(
|
||||
res, key=lambda x: results_value.index(x.name)
|
||||
)
|
||||
res_sorted: list[TypeDefinition] = sorted(res, key=lambda x: results_value.index(x.name))
|
||||
|
||||
# Rebase the file paths
|
||||
return self._rebase_types_file_paths(res_sorted)
|
||||
@@ -915,9 +870,7 @@ class CodeQueryPersistent(CodeQuery):
|
||||
|
||||
try:
|
||||
persistent_challenge.commit(".cqdb")
|
||||
logger.debug(
|
||||
f"Uploading cqdb {persistent_challenge.local_task_dir} to remote storage"
|
||||
)
|
||||
logger.debug(f"Uploading cqdb {persistent_challenge.local_task_dir} to remote storage")
|
||||
except Exception as e:
|
||||
logger.exception("Failed to commit the cqdb: %s", e)
|
||||
raise e
|
||||
|
||||
@@ -58,9 +58,7 @@ class ProgramModel:
|
||||
def process_task_codequery(self, args: IndexRequest) -> bool:
|
||||
"""Process a single task for indexing a program"""
|
||||
try:
|
||||
logger.info(
|
||||
f"Processing task {args.package_name}/{args.task_id}/{args.task_dir} with codequery"
|
||||
)
|
||||
logger.info(f"Processing task {args.package_name}/{args.task_id}/{args.task_dir} with codequery")
|
||||
challenge = ChallengeTask(
|
||||
read_only_task_dir=args.task_dir,
|
||||
python_path=self.python,
|
||||
@@ -97,9 +95,7 @@ class ProgramModel:
|
||||
|
||||
def process_task(self, args: IndexRequest) -> bool:
|
||||
"""Process a single task for indexing a program"""
|
||||
logger.info(
|
||||
f"Processing task {args.package_name}/{args.task_id}/{args.task_dir}"
|
||||
)
|
||||
logger.info(f"Processing task {args.package_name}/{args.task_id}/{args.task_dir}")
|
||||
return self.process_task_codequery(args)
|
||||
|
||||
def serve_item(self) -> bool:
|
||||
@@ -112,9 +108,7 @@ class ProgramModel:
|
||||
task_index: IndexRequest = rq_item.deserialized
|
||||
|
||||
# Check if task should be processed or skipped
|
||||
if self.registry is not None and self.registry.should_stop_processing(
|
||||
task_index.task_id
|
||||
):
|
||||
if self.registry is not None and self.registry.should_stop_processing(task_index.task_id):
|
||||
logger.debug(f"Task {task_index.task_id} is cancelled or expired, skipping")
|
||||
self.task_queue.ack_item(rq_item.item_id)
|
||||
return True
|
||||
|
||||
@@ -13,12 +13,8 @@ class BuilderSettings(BaseModel):
|
||||
|
||||
|
||||
class WorkerSettings(BaseModel):
|
||||
redis_url: Annotated[
|
||||
str, Field(default="redis://localhost:6379", description="Redis URL")
|
||||
]
|
||||
sleep_time: Annotated[
|
||||
float, Field(default=1.0, description="Sleep time between checks in seconds")
|
||||
]
|
||||
redis_url: Annotated[str, Field(default="redis://localhost:6379", description="Redis URL")]
|
||||
sleep_time: Annotated[float, Field(default=1.0, description="Sleep time between checks in seconds")]
|
||||
python: Annotated[str, Field(default="python", description="Python path")]
|
||||
|
||||
|
||||
@@ -32,13 +28,9 @@ class ProcessCommand(WorkerSettings, BuilderSettings):
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
scratch_dir: Annotated[
|
||||
Path, Field(default="/tmp/scratch", description="Directory for scratch space")
|
||||
]
|
||||
scratch_dir: Annotated[Path, Field(default="/tmp/scratch", description="Directory for scratch space")]
|
||||
log_level: Annotated[str, Field(default="info", description="Log level")]
|
||||
log_max_line_length: Annotated[
|
||||
int | None, Field(default=None, description="Log max line length")
|
||||
]
|
||||
log_max_line_length: Annotated[int | None, Field(default=None, description="Log max line length")]
|
||||
|
||||
serve: CliSubCommand[ServeCommand]
|
||||
process: CliSubCommand[ProcessCommand]
|
||||
|
||||
@@ -24,11 +24,7 @@ class FunctionBody:
|
||||
"""Two function bodies are equal if they have the same body and start and end lines."""
|
||||
if not isinstance(other, FunctionBody):
|
||||
return NotImplemented
|
||||
return (
|
||||
self.body == other.body
|
||||
and self.start_line == other.start_line
|
||||
and self.end_line == other.end_line
|
||||
)
|
||||
return self.body == other.body and self.start_line == other.start_line and self.end_line == other.end_line
|
||||
|
||||
def __hash__(self) -> int:
|
||||
"""Hash based on body and start and end lines."""
|
||||
@@ -159,11 +155,7 @@ class TypeUsageInfo:
|
||||
"""Two type usages are equal if they have the same name, file path, and line number."""
|
||||
if not isinstance(other, TypeUsageInfo):
|
||||
return NotImplemented
|
||||
return (
|
||||
self.name == other.name
|
||||
and self.file_path == other.file_path
|
||||
and self.line_number == other.line_number
|
||||
)
|
||||
return self.name == other.name and self.file_path == other.file_path and self.line_number == other.line_number
|
||||
|
||||
def __hash__(self) -> int:
|
||||
"""Hash based on name, file path, and line number."""
|
||||
|
||||
@@ -38,13 +38,9 @@ from ..common import (
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_get_functions(
|
||||
dropbear_oss_fuzz_cq: CodeQuery, function_name, file_path, function_info
|
||||
):
|
||||
def test_get_functions(dropbear_oss_fuzz_cq: CodeQuery, function_name, file_path, function_info):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
dropbear_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(dropbear_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -50,9 +50,7 @@ def test_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
freerdp_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(freerdp_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -239,9 +237,7 @@ def test_get_type_definitions(
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip(
|
||||
reason="Problem with codequery. Doesn't consider rdpAssistanceFile as being used"
|
||||
)
|
||||
@pytest.mark.skip(reason="Problem with codequery. Doesn't consider rdpAssistanceFile as being used")
|
||||
@pytest.mark.integration
|
||||
def test_get_type_usages(
|
||||
freerdp_oss_fuzz_task: ChallengeTask,
|
||||
|
||||
@@ -3,27 +3,18 @@ import pytest
|
||||
from buttercup.common.challenge_task import ChallengeTask
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"file_path,expected_imports", [("src/md5/md5.c", {"src/md5/md5.h"})]
|
||||
)
|
||||
@pytest.mark.parametrize("file_path,expected_imports", [("src/md5/md5.c", {"src/md5/md5.h"})])
|
||||
@pytest.mark.integration
|
||||
def test_list_direct_imports(
|
||||
libjpeg_main_oss_fuzz_task: ChallengeTask, file_path, expected_imports
|
||||
):
|
||||
def test_list_direct_imports(libjpeg_main_oss_fuzz_task: ChallengeTask, file_path, expected_imports):
|
||||
# Unit test for the get_direct_imports() function
|
||||
# We just check whether we can get imports in a single file properly
|
||||
resolver = FuzzyCImportsResolver(
|
||||
libjpeg_main_oss_fuzz_task.task_dir / "src/libjpeg-turbo"
|
||||
)
|
||||
resolver = FuzzyCImportsResolver(libjpeg_main_oss_fuzz_task.task_dir / "src/libjpeg-turbo")
|
||||
path_prefix = libjpeg_main_oss_fuzz_task.task_dir / "src/libjpeg-turbo"
|
||||
full_path = (path_prefix / file_path).resolve()
|
||||
direct_imports = resolver.get_direct_imports(full_path)
|
||||
# Check resolved imports. We make found imports relative to
|
||||
# the task dir because the imports resolver returns full paths
|
||||
assert (
|
||||
set(map(lambda x: str(x.relative_to(path_prefix)), direct_imports))
|
||||
== expected_imports
|
||||
)
|
||||
assert set(map(lambda x: str(x.relative_to(path_prefix)), direct_imports)) == expected_imports
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -76,13 +67,9 @@ def test_list_direct_imports(
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_import_checker(
|
||||
libjpeg_main_oss_fuzz_task: ChallengeTask, file_path, expected_imports
|
||||
):
|
||||
def test_import_checker(libjpeg_main_oss_fuzz_task: ChallengeTask, file_path, expected_imports):
|
||||
# Create resolver
|
||||
resolver = FuzzyCImportsResolver(
|
||||
libjpeg_main_oss_fuzz_task.task_dir / "src/libjpeg-turbo"
|
||||
)
|
||||
resolver = FuzzyCImportsResolver(libjpeg_main_oss_fuzz_task.task_dir / "src/libjpeg-turbo")
|
||||
# Check expected imports
|
||||
for expected in expected_imports:
|
||||
assert resolver.is_file_imported_by(expected, file_path)
|
||||
|
||||
@@ -65,9 +65,7 @@ from buttercup.program_model.utils.common import TypeDefinitionType
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_hdf5_get_functions(
|
||||
hdf5_oss_fuzz_cq: CodeQuery, function_name, file_path, function_info
|
||||
):
|
||||
def test_hdf5_get_functions(hdf5_oss_fuzz_cq: CodeQuery, function_name, file_path, function_info):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(hdf5_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@@ -97,9 +97,7 @@ def test_libjpeg_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
libjpeg_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(libjpeg_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -53,9 +53,7 @@ def test_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
libpng_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(libpng_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -46,9 +46,7 @@ def test_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
libxml2_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(libxml2_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -59,9 +59,7 @@ def test_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
sqlite_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(sqlite_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -44,9 +44,7 @@ class TestFunctionInfo:
|
||||
TestFunctionInfo.__test__ = False
|
||||
|
||||
|
||||
def common_test_get_functions(
|
||||
codequery: CodeQuery, function_name, file_path, function_info
|
||||
):
|
||||
def common_test_get_functions(codequery: CodeQuery, function_name, file_path, function_info):
|
||||
"""Generic function for testing get_functions() in C codebases"""
|
||||
if file_path:
|
||||
file_path = Path(file_path)
|
||||
@@ -90,17 +88,13 @@ def common_test_get_callers(
|
||||
)[0]
|
||||
|
||||
callers = codequery.get_callers(function)
|
||||
callers = filter_project_context(
|
||||
fuzz_task.container_src_dir(), callers, codequery._get_project_language()
|
||||
)
|
||||
callers = filter_project_context(fuzz_task.container_src_dir(), callers, codequery._get_project_language())
|
||||
|
||||
# Output for debugging
|
||||
if not callers:
|
||||
logger.info(f"No callers found for {function_name} in {file_path}")
|
||||
for c in callers:
|
||||
logger.info(
|
||||
f"Caller: {c.name} {c.file_path} {[b.start_line for b in c.bodies]}"
|
||||
)
|
||||
logger.info(f"Caller: {c.name} {c.file_path} {[b.start_line for b in c.bodies]}")
|
||||
|
||||
# Validate each caller
|
||||
for expected_caller in expected_callers:
|
||||
@@ -109,11 +103,7 @@ def common_test_get_callers(
|
||||
for c in callers
|
||||
if c.name == expected_caller.name
|
||||
and c.file_path == Path(expected_caller.file_path)
|
||||
and any(
|
||||
True
|
||||
for b in c.bodies
|
||||
if b.start_line <= expected_caller.start_line <= b.end_line
|
||||
)
|
||||
and any(True for b in c.bodies if b.start_line <= expected_caller.start_line <= b.end_line)
|
||||
]
|
||||
if len(caller_info) == 0:
|
||||
pytest.fail(f"Couldn't find expected caller: {expected_caller}")
|
||||
@@ -158,17 +148,13 @@ def common_test_get_callees(
|
||||
)[0]
|
||||
|
||||
callees = codequery.get_callees(function)
|
||||
callees = filter_project_context(
|
||||
fuzz_task.container_src_dir(), callees, codequery._get_project_language()
|
||||
)
|
||||
callees = filter_project_context(fuzz_task.container_src_dir(), callees, codequery._get_project_language())
|
||||
|
||||
# Output for debugging
|
||||
if not callees:
|
||||
logger.info(f"No callees found for {function_name} in {file_path}")
|
||||
for c in callees:
|
||||
logger.info(
|
||||
f"Callee: {c.name} {c.file_path} {[b.start_line for b in c.bodies]}"
|
||||
)
|
||||
logger.info(f"Callee: {c.name} {c.file_path} {[b.start_line for b in c.bodies]}")
|
||||
|
||||
# Validate each callee
|
||||
for expected_callee in expected_callees:
|
||||
@@ -177,11 +163,7 @@ def common_test_get_callees(
|
||||
for c in callees
|
||||
if c.name == expected_callee.name
|
||||
and c.file_path == Path(expected_callee.file_path)
|
||||
and any(
|
||||
True
|
||||
for b in c.bodies
|
||||
if b.start_line <= expected_callee.start_line <= b.end_line
|
||||
)
|
||||
and any(True for b in c.bodies if b.start_line <= expected_callee.start_line <= b.end_line)
|
||||
]
|
||||
if len(callee_info) == 0:
|
||||
pytest.fail(f"Couldn't find expected callee: {expected_callee}")
|
||||
@@ -228,9 +210,7 @@ def common_test_get_type_definitions(
|
||||
|
||||
# Output for debugging
|
||||
for c in type_definitions:
|
||||
logger.info(
|
||||
f"Type definition: {c.name} {c.type} {c.file_path} {c.definition_line}"
|
||||
)
|
||||
logger.info(f"Type definition: {c.name} {c.type} {c.file_path} {c.definition_line}")
|
||||
|
||||
found = [
|
||||
c
|
||||
@@ -244,9 +224,7 @@ def common_test_get_type_definitions(
|
||||
if len(found) == 0:
|
||||
pytest.fail(f"Couldn't find expected type definition: {type_definition_info}")
|
||||
elif len(found) > 1:
|
||||
pytest.fail(
|
||||
f"Found multiple identical type definitions for: {type_definition_info}"
|
||||
)
|
||||
pytest.fail(f"Found multiple identical type definitions for: {type_definition_info}")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -276,9 +254,7 @@ def common_test_get_type_usages(
|
||||
)[0]
|
||||
|
||||
call_sites = codequery.get_type_calls(type_definition)
|
||||
call_sites = filter_project_context(
|
||||
fuzz_task.container_src_dir(), call_sites, codequery._get_project_language()
|
||||
)
|
||||
call_sites = filter_project_context(fuzz_task.container_src_dir(), call_sites, codequery._get_project_language())
|
||||
|
||||
# Output for debugging
|
||||
for c in call_sites:
|
||||
|
||||
@@ -113,9 +113,7 @@ def test_get_callers(
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip(
|
||||
reason="Skipping callee test for now. It's not working because it gets filtered out from imports."
|
||||
)
|
||||
@pytest.mark.skip(reason="Skipping callee test for now. It's not working because it gets filtered out from imports.")
|
||||
@pytest.mark.integration
|
||||
def test_get_callees(
|
||||
bc_oss_fuzz_task: ChallengeTask,
|
||||
@@ -195,9 +193,7 @@ def test_get_type_definitions(
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip(
|
||||
reason="Skipping type usage test for now. Class is directly imported and used."
|
||||
)
|
||||
@pytest.mark.skip(reason="Skipping type usage test for now. Class is directly imported and used.")
|
||||
@pytest.mark.integration
|
||||
def test_get_type_usages(
|
||||
bc_oss_fuzz_task: ChallengeTask,
|
||||
|
||||
@@ -54,9 +54,7 @@ def test_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
checkstyle_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(checkstyle_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -78,9 +76,7 @@ def test_get_functions(
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip(
|
||||
reason="Skipping callers test for now. It's failing for this example."
|
||||
)
|
||||
@pytest.mark.skip(reason="Skipping callers test for now. It's failing for this example.")
|
||||
@pytest.mark.integration
|
||||
def test_get_callers(
|
||||
checkstyle_oss_fuzz_task: ChallengeTask,
|
||||
@@ -203,9 +199,7 @@ def test_get_type_definitions(
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip(
|
||||
reason="Skipping type usage test for now. It's failing for this example."
|
||||
)
|
||||
@pytest.mark.skip(reason="Skipping type usage test for now. It's failing for this example.")
|
||||
@pytest.mark.integration
|
||||
def test_get_type_usages(
|
||||
checkstyle_oss_fuzz_task: ChallengeTask,
|
||||
|
||||
@@ -53,9 +53,7 @@ def test_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions"""
|
||||
common_test_get_functions(
|
||||
commons_codec_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(commons_codec_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
# From: https://github.com/apache/commons-codec/blob/44e4c4d778c3ab87db09c00e9d1c3260fd42dad5/src/main/java/org/apache/commons/codec/language/bm/PhoneticEngine.java#L206
|
||||
|
||||
@@ -52,9 +52,7 @@ def test_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
commons_compress_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(commons_compress_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -76,9 +74,7 @@ def test_get_functions(
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip(
|
||||
reason="Issue with codequery thinking the caller is bsGetBit on line 778"
|
||||
)
|
||||
@pytest.mark.skip(reason="Issue with codequery thinking the caller is bsGetBit on line 778")
|
||||
@pytest.mark.integration
|
||||
def test_get_callers(
|
||||
commons_compress_oss_fuzz_task: ChallengeTask,
|
||||
|
||||
@@ -42,9 +42,7 @@ def test_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
graphql_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(graphql_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -30,6 +30,4 @@ def test_split_rightmost_component(input_expr, expected):
|
||||
"""Test the split_rightmost_component function with various test cases."""
|
||||
resolver = FuzzyJavaImportsResolver(None, None)
|
||||
result = resolver.split_rightmost_dotexpr(input_expr)
|
||||
assert result == expected, (
|
||||
f"Failed on: {input_expr}\nExpected: {expected}\nGot: {result}"
|
||||
)
|
||||
assert result == expected, f"Failed on: {input_expr}\nExpected: {expected}\nGot: {result}"
|
||||
|
||||
@@ -45,9 +45,7 @@ from pathlib import Path
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip(
|
||||
reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc"
|
||||
)
|
||||
@pytest.mark.skip(reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc")
|
||||
@pytest.mark.integration
|
||||
def test_get_functions(
|
||||
log4j2_oss_fuzz_task: ChallengeTask,
|
||||
@@ -57,9 +55,7 @@ def test_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
log4j2_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(log4j2_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -83,9 +79,7 @@ def test_get_functions(
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip(
|
||||
reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc"
|
||||
)
|
||||
@pytest.mark.skip(reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc")
|
||||
@pytest.mark.integration
|
||||
def test_get_callers(
|
||||
log4j2_oss_fuzz_task: ChallengeTask,
|
||||
@@ -177,9 +171,7 @@ def test_get_callers(
|
||||
# ),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip(
|
||||
reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc"
|
||||
)
|
||||
@pytest.mark.skip(reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc")
|
||||
@pytest.mark.integration
|
||||
def test_get_callees(
|
||||
log4j2_oss_fuzz_task: ChallengeTask,
|
||||
@@ -245,9 +237,7 @@ def test_get_callees(
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip(
|
||||
reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc"
|
||||
)
|
||||
@pytest.mark.skip(reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc")
|
||||
@pytest.mark.integration
|
||||
def test_get_type_definitions(
|
||||
log4j2_oss_fuzz_task: ChallengeTask,
|
||||
@@ -285,9 +275,7 @@ def test_get_type_definitions(
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip(
|
||||
reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc"
|
||||
)
|
||||
@pytest.mark.skip(reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc")
|
||||
@pytest.mark.integration
|
||||
def test_get_type_usages(
|
||||
log4j2_oss_fuzz_task: ChallengeTask,
|
||||
@@ -310,9 +298,7 @@ def test_get_type_usages(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skip(
|
||||
reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc"
|
||||
)
|
||||
@pytest.mark.skip(reason="Skipping for now, as the image build routine doesn't work with oss-fuzz-aixcc")
|
||||
@pytest.mark.integration
|
||||
def test_java_resolver(log4j2_oss_fuzz_task: ChallengeTask):
|
||||
codequery = CodeQuery(log4j2_oss_fuzz_task)
|
||||
@@ -321,72 +307,48 @@ def test_java_resolver(log4j2_oss_fuzz_task: ChallengeTask):
|
||||
# Simple expr with only one type (no dots)
|
||||
t = resolver.get_dotexpr_type(
|
||||
"NetUtils",
|
||||
Path(
|
||||
"/src/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java"
|
||||
),
|
||||
Path("/src/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java"),
|
||||
)
|
||||
assert t is not None
|
||||
assert t.name == "NetUtils"
|
||||
assert t.file_path == Path(
|
||||
"/src/log4j-core/src/main/java/org/apache/logging/log4j/core/util/NetUtils.java"
|
||||
)
|
||||
assert t.file_path == Path("/src/log4j-core/src/main/java/org/apache/logging/log4j/core/util/NetUtils.java")
|
||||
|
||||
t = resolver.get_dotexpr_type(
|
||||
"Category.aai",
|
||||
Path(
|
||||
"/src/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java"
|
||||
),
|
||||
Path("/src/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java"),
|
||||
)
|
||||
assert t is not None
|
||||
assert t.name == "AppenderAttachableImpl"
|
||||
assert t.file_path == Path(
|
||||
"/src/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/AppenderAttachableImpl.java"
|
||||
)
|
||||
assert t.file_path == Path("/src/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/AppenderAttachableImpl.java")
|
||||
|
||||
t = resolver.get_dotexpr_type(
|
||||
"Category.getDefaultHierarchy()",
|
||||
Path(
|
||||
"/src/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java"
|
||||
),
|
||||
Path("/src/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java"),
|
||||
)
|
||||
assert t is not None
|
||||
assert t.name == "LoggerRepository"
|
||||
assert t.file_path == Path(
|
||||
"/src/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LoggerRepository.java"
|
||||
)
|
||||
assert t.file_path == Path("/src/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LoggerRepository.java")
|
||||
|
||||
t = resolver.get_dotexpr_type(
|
||||
"Category.getDefaultHierarchy().getLogger().getRootLogger()",
|
||||
Path(
|
||||
"/src/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java"
|
||||
),
|
||||
Path("/src/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java"),
|
||||
)
|
||||
assert t is not None
|
||||
assert t.name == "Logger"
|
||||
assert t.file_path == Path(
|
||||
"/src/log4j-1.2-api/src/main/java/org/apache/log4j/Logger.java"
|
||||
)
|
||||
assert t.file_path == Path("/src/log4j-1.2-api/src/main/java/org/apache/log4j/Logger.java")
|
||||
|
||||
t = resolver.get_dotexpr_type(
|
||||
"Category.getDefaultHierarchy().exists('test').getRootLogger()",
|
||||
Path(
|
||||
"/src/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java"
|
||||
),
|
||||
Path("/src/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java"),
|
||||
)
|
||||
assert t is not None
|
||||
assert t.name == "Logger"
|
||||
assert t.file_path == Path(
|
||||
"/src/log4j-1.2-api/src/main/java/org/apache/log4j/Logger.java"
|
||||
)
|
||||
assert t.file_path == Path("/src/log4j-1.2-api/src/main/java/org/apache/log4j/Logger.java")
|
||||
|
||||
t = resolver.get_dotexpr_type(
|
||||
"Category.getDefaultHierarchy().getThreshold().TRACE.toLevel(3)",
|
||||
Path(
|
||||
"/src/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java"
|
||||
),
|
||||
Path("/src/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java"),
|
||||
)
|
||||
assert t is not None
|
||||
assert t.name == "Level"
|
||||
assert t.file_path == Path(
|
||||
"/src/log4j-1.2-api/src/main/java/org/apache/log4j/Level.java"
|
||||
)
|
||||
assert t.file_path == Path("/src/log4j-1.2-api/src/main/java/org/apache/log4j/Level.java")
|
||||
|
||||
@@ -51,9 +51,7 @@ def test_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
zookeeper_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(zookeeper_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -182,10 +182,7 @@ def test_get_functions_multiple(mock_c_challenge_task: ChallengeTask):
|
||||
function3 = codequery.get_functions("function3", Path("test3.c"))
|
||||
assert len(function3) == 1
|
||||
assert function3[0].name == "function3"
|
||||
assert (
|
||||
function3[0].bodies[0].body
|
||||
== "int function3(int a, int b) {\n int c = a + b;\n return c;\n}"
|
||||
)
|
||||
assert function3[0].bodies[0].body == "int function3(int a, int b) {\n int c = a + b;\n return c;\n}"
|
||||
|
||||
function4 = codequery.get_functions("function4", Path("test3.c"))
|
||||
assert len(function4) == 1
|
||||
@@ -229,9 +226,7 @@ def test_keep_status(
|
||||
assert mock_c_challenge_task.task_dir.exists()
|
||||
assert mock_c_challenge_task_ro.task_dir.exists()
|
||||
|
||||
with mock_c_challenge_task_ro.get_rw_copy(
|
||||
mock_c_challenge_task_ro.task_dir.parent
|
||||
) as nd_challenge:
|
||||
with mock_c_challenge_task_ro.get_rw_copy(mock_c_challenge_task_ro.task_dir.parent) as nd_challenge:
|
||||
with patch("subprocess.run", side_effect=mock_docker_run(nd_challenge)):
|
||||
codequery3 = CodeQueryPersistent(nd_challenge, work_dir=wdir)
|
||||
assert codequery3.get_functions("main")
|
||||
@@ -239,9 +234,7 @@ def test_keep_status(
|
||||
assert mock_c_challenge_task.task_dir.exists()
|
||||
assert mock_c_challenge_task_ro.task_dir.exists()
|
||||
|
||||
with mock_c_challenge_task.get_rw_copy(
|
||||
mock_c_challenge_task.task_dir.parent
|
||||
) as nd_challenge:
|
||||
with mock_c_challenge_task.get_rw_copy(mock_c_challenge_task.task_dir.parent) as nd_challenge:
|
||||
with patch("subprocess.run", side_effect=mock_docker_run(nd_challenge)):
|
||||
codequery4 = CodeQueryPersistent(nd_challenge, work_dir=wdir)
|
||||
assert codequery4.get_functions("main")
|
||||
@@ -266,9 +259,7 @@ def test_get_types(mock_c_challenge_task: ChallengeTask):
|
||||
assert types[0].definition_line == 1
|
||||
types = codequery.get_types("myInt", Path("test4.c"), function_name="function5")
|
||||
assert len(types) == 0
|
||||
types = codequery.get_types(
|
||||
"myOtherInt", Path("test4.c"), function_name="function5"
|
||||
)
|
||||
types = codequery.get_types("myOtherInt", Path("test4.c"), function_name="function5")
|
||||
assert len(types) == 1
|
||||
assert types[0].name == "myOtherInt"
|
||||
assert types[0].type == TypeDefinitionType.TYPEDEF
|
||||
@@ -310,10 +301,7 @@ def test_libjpeg_indexing(libjpeg_oss_fuzz_task: ChallengeTask):
|
||||
assert parse_switches[0].file_path == Path("/src/libjpeg-turbo/cjpeg.c")
|
||||
assert parse_switches[0].file_path.name == "cjpeg.c"
|
||||
assert len(parse_switches[0].bodies) == 1
|
||||
assert (
|
||||
"parse_switches(j_compress_ptr cinfo, int argc, char **argv,"
|
||||
in parse_switches[0].bodies[0].body
|
||||
)
|
||||
assert "parse_switches(j_compress_ptr cinfo, int argc, char **argv," in parse_switches[0].bodies[0].body
|
||||
|
||||
assert parse_switches[1].file_path.name == "djpeg.c"
|
||||
assert parse_switches[1].name == "parse_switches"
|
||||
@@ -326,20 +314,14 @@ parse_switches(j_decompress_ptr cinfo, int argc, char **argv,
|
||||
"""
|
||||
in parse_switches[1].bodies[0].body
|
||||
)
|
||||
assert ' } else if (keymatch(arg, "crop", 2)) {' in parse_switches[1].bodies[0].body
|
||||
assert (
|
||||
' } else if (keymatch(arg, "crop", 2)) {' in parse_switches[1].bodies[0].body
|
||||
)
|
||||
assert (
|
||||
"return argn; /* return index of next arg (file name) */"
|
||||
in parse_switches[1].bodies[0].body
|
||||
"return argn; /* return index of next arg (file name) */" in parse_switches[1].bodies[0].body
|
||||
)
|
||||
|
||||
assert parse_switches[2].file_path.name == "jpegtran.c"
|
||||
assert len(parse_switches[2].bodies) == 1
|
||||
assert (
|
||||
"parse_switches(j_compress_ptr cinfo, int argc, char **argv,"
|
||||
in parse_switches[2].bodies[0].body
|
||||
)
|
||||
assert "parse_switches(j_compress_ptr cinfo, int argc, char **argv," in parse_switches[2].bodies[0].body
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@@ -351,10 +333,7 @@ def test_selinux_indexing(selinux_oss_fuzz_task: ChallengeTask):
|
||||
assert functions[0].name == "mls_semantic_level_expand"
|
||||
assert functions[0].file_path == Path("/src/selinux/libsepol/src/expand.c")
|
||||
assert len(functions[0].bodies) == 1
|
||||
assert (
|
||||
"""cat->low > 0 ? p->p_cat_val_to_name[cat->low - 1] : "Invalid","""
|
||||
in functions[0].bodies[0].body
|
||||
)
|
||||
assert """cat->low > 0 ? p->p_cat_val_to_name[cat->low - 1] : "Invalid",""" in functions[0].bodies[0].body
|
||||
|
||||
|
||||
def setup_java_dirs(tmp_path: Path) -> Path:
|
||||
|
||||
@@ -19,13 +19,9 @@ from buttercup.program_model.codequery import CodeQuery
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_libpng_get_functions_fuzzy(
|
||||
libpng_oss_fuzz_task: ChallengeTask, search_string, match_string, threshold
|
||||
):
|
||||
def test_libpng_get_functions_fuzzy(libpng_oss_fuzz_task: ChallengeTask, search_string, match_string, threshold):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
codequery = CodeQuery(libpng_oss_fuzz_task)
|
||||
functions = codequery.get_functions(
|
||||
search_string, fuzzy=True, fuzzy_threshold=threshold
|
||||
)
|
||||
functions = codequery.get_functions(search_string, fuzzy=True, fuzzy_threshold=threshold)
|
||||
assert len(functions) > 0
|
||||
assert any(f.name == match_string for f in functions)
|
||||
|
||||
@@ -37,9 +37,7 @@ from .common import (
|
||||
"/src/libpng/png.c",
|
||||
TestFunctionInfo(
|
||||
num_bodies=1,
|
||||
body_excerpts=[
|
||||
"""info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr,"""
|
||||
],
|
||||
body_excerpts=["""info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr,"""],
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -53,9 +51,7 @@ def test_libpng_get_functions(
|
||||
function_info,
|
||||
):
|
||||
"""Test that we can get functions in challenge task code"""
|
||||
common_test_get_functions(
|
||||
libpng_oss_fuzz_cq, function_name, file_path, function_info
|
||||
)
|
||||
common_test_get_functions(libpng_oss_fuzz_cq, function_name, file_path, function_info)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -80,9 +80,7 @@ def test_serve_item_process_normal_task(program_model):
|
||||
|
||||
# Verify the task was processed and acknowledged
|
||||
assert result is True
|
||||
program_model.registry.should_stop_processing.assert_called_once_with(
|
||||
mock_task_id
|
||||
)
|
||||
program_model.registry.should_stop_processing.assert_called_once_with(mock_task_id)
|
||||
program_model.process_task.assert_called_once_with(mock_request)
|
||||
program_model.task_queue.ack_item.assert_called_once_with(mock_item.item_id)
|
||||
program_model.output_queue.push.assert_called_once()
|
||||
|
||||
Generated
+189
-799
File diff suppressed because it is too large
Load Diff
+36
-14
@@ -6,16 +6,17 @@ readme = "README.md"
|
||||
authors = [
|
||||
{ name = "Trail of Bits", email = "opensource@trailofbits.com" },
|
||||
]
|
||||
license = "AGPL-3.0-only"
|
||||
dependencies = [
|
||||
"redis ~= 5.2.1",
|
||||
"redis ~=5.2.1",
|
||||
"common",
|
||||
"wasmtime ~= 29.0.0",
|
||||
"wasmtime ~=29.0.0",
|
||||
"program-model",
|
||||
"numpy ~= 2.2.3",
|
||||
"rapidfuzz ~= 3.12.2",
|
||||
"langgraph ~= 0.5.2",
|
||||
"langchain ~= 0.3.20",
|
||||
"python-dotenv>=1.0.1",
|
||||
"numpy ~=2.2.3",
|
||||
"rapidfuzz ~=3.12.2",
|
||||
"langgraph ~=0.5.2",
|
||||
"langchain ~=0.3.20",
|
||||
"python-dotenv ~=1.0.1",
|
||||
]
|
||||
requires-python = ">=3.12,<3.13"
|
||||
|
||||
@@ -30,15 +31,25 @@ packages = ["src/buttercup"]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project.optional-dependencies]
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"mypy ~= 1.15.0",
|
||||
"pytest ~= 8.3.4",
|
||||
"ruff ~= 0.6.2",
|
||||
"tqdm ~= 4.67.1",
|
||||
"types-redis",
|
||||
# Testing tools
|
||||
"pytest ~=8.3.4",
|
||||
"pytest-cov ~=6.0.0",
|
||||
"pytest-asyncio ~=0.25.2",
|
||||
# Linting and type checking
|
||||
"ruff ~=0.12.8",
|
||||
"mypy ~=1.17.1",
|
||||
# Type stubs
|
||||
"types-redis ~=4.6.0",
|
||||
# Additional tools
|
||||
"tqdm ~=4.67.1",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/trailofbits/buttercup"
|
||||
Issues = "https://github.com/trailofbits/buttercup/issues"
|
||||
|
||||
[project.scripts]
|
||||
"seed-gen" = "buttercup.seed_gen._cli:main"
|
||||
|
||||
@@ -75,7 +86,18 @@ select = ["E", "F", "I", "W", "UP"]
|
||||
# D203 and D213 are incompatible with D211 and D212 respectively.
|
||||
# COM812 and ISC001 can cause conflicts when using ruff as a formatter.
|
||||
# See https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules.
|
||||
ignore = ["D203", "D213", "COM812", "ISC001"]
|
||||
ignore = [
|
||||
"D203", "D213", "COM812", "ISC001",
|
||||
# Temporarily disabled for standardization PR - re-enable after refactoring:
|
||||
"I001", # Import block is un-sorted or un-formatted
|
||||
"E501", # Line too long
|
||||
"W291", # Trailing whitespace
|
||||
"UP006", # Use built-in collection types for type annotations
|
||||
"UP015", # Unnecessary mode argument
|
||||
"UP035", # Import from modern locations instead of deprecated typing
|
||||
"UP045", # Use X | None for type annotations
|
||||
"UP046", # Use modern generic class syntax
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"src/seed_gen/_cli.py" = [
|
||||
|
||||
@@ -110,7 +110,7 @@ def test_extract_code_libpng_partial_codeblock():
|
||||
|
||||
|
||||
def test_extract_code_partial_block_with_no_functions():
|
||||
message = AIMessage(content=("Here's some code:\n" "```python\n" "print('hello')\n" "x = 1"))
|
||||
message = AIMessage(content=("Here's some code:\n```python\nprint('hello')\nx = 1"))
|
||||
with pytest.raises(OutputParserException):
|
||||
extract_code(message)
|
||||
|
||||
|
||||
@@ -201,9 +201,9 @@ def test_do_task_no_valid_povs(
|
||||
|
||||
for i in range(vuln_discovery_task.MAX_POV_ITERATIONS):
|
||||
iter_pov_files = list(out_dir.glob(f"iter{i}_*.seed"))
|
||||
assert (
|
||||
len(iter_pov_files) == 2
|
||||
), f"Expected 2 seeds for iter{i}, found {len(iter_pov_files)}: {iter_pov_files}"
|
||||
assert len(iter_pov_files) == 2, (
|
||||
f"Expected 2 seeds for iter{i}, found {len(iter_pov_files)}: {iter_pov_files}"
|
||||
)
|
||||
|
||||
# Check the content of the PoV files
|
||||
iter_pov1_file = next(f for f in iter_pov_files if "gen_seed_1" in f.name)
|
||||
|
||||
@@ -188,9 +188,9 @@ def test_do_task_valid_pov(
|
||||
|
||||
for i in range(2):
|
||||
iter_pov_files = list(out_dir.glob(f"iter{i}_*.seed"))
|
||||
assert (
|
||||
len(iter_pov_files) == 2
|
||||
), f"Expected 2 seeds for iter{i}, found {len(iter_pov_files)}: {iter_pov_files}"
|
||||
assert len(iter_pov_files) == 2, (
|
||||
f"Expected 2 seeds for iter{i}, found {len(iter_pov_files)}: {iter_pov_files}"
|
||||
)
|
||||
|
||||
iter_pov1_file = next(f for f in iter_pov_files if "gen_seed_1" in f.name)
|
||||
iter_pov2_file = next(f for f in iter_pov_files if "gen_seed_2" in f.name)
|
||||
@@ -210,6 +210,6 @@ def test_do_task_valid_pov(
|
||||
assert crash_call.stacktrace == "Stack trace for crash"
|
||||
|
||||
iter_pov_files_skipped = list(out_dir.glob("iter2_*.seed"))
|
||||
assert (
|
||||
len(iter_pov_files_skipped) == 0
|
||||
), f"Expected skipping 3rd iter, but there are {len(iter_pov_files_skipped)} seeds"
|
||||
assert len(iter_pov_files_skipped) == 0, (
|
||||
f"Expected skipping 3rd iter, but there are {len(iter_pov_files_skipped)} seeds"
|
||||
)
|
||||
|
||||
Generated
+136
-84
@@ -1,5 +1,5 @@
|
||||
version = 1
|
||||
revision = 2
|
||||
revision = 3
|
||||
requires-python = "==3.12.*"
|
||||
|
||||
[[package]]
|
||||
@@ -235,22 +235,43 @@ requires-dist = [
|
||||
{ name = "langchain-text-splitters", specifier = "~=0.3.7" },
|
||||
{ name = "langfuse", specifier = "~=2.59.2" },
|
||||
{ name = "openlit", specifier = "==1.32.12" },
|
||||
{ name = "protobuf", specifier = ">=3.20,<=3.20.3" },
|
||||
{ name = "pydantic-settings", specifier = ">=2.7.1" },
|
||||
{ name = "pymongo", specifier = ">=4.10.1" },
|
||||
{ name = "redis", specifier = ">=5.2.1,<6.0.0" },
|
||||
{ name = "six", specifier = ">=1.17.0" },
|
||||
{ name = "protobuf", specifier = "==3.20.3" },
|
||||
{ name = "pydantic-settings", specifier = "~=2.7.1" },
|
||||
{ name = "pymongo", specifier = "~=4.10.1" },
|
||||
{ name = "redis", specifier = "~=5.2.1" },
|
||||
{ name = "six", specifier = "~=1.17.0" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "dirty-equals", specifier = ">=0.9.0" },
|
||||
{ name = "mypy", specifier = ">=1.15.0" },
|
||||
{ name = "pytest", specifier = ">=8.3.4" },
|
||||
{ name = "ruff", specifier = ">=0.9.2" },
|
||||
{ name = "dirty-equals", specifier = "~=0.9.0" },
|
||||
{ name = "mypy", specifier = "~=1.17.1" },
|
||||
{ name = "pytest", specifier = "~=8.3.4" },
|
||||
{ name = "pytest-cov", specifier = "~=6.0.0" },
|
||||
{ name = "ruff", specifier = "~=0.12.8" },
|
||||
{ name = "types-pyyaml" },
|
||||
{ name = "types-redis" },
|
||||
{ name = "types-requests" },
|
||||
{ name = "types-redis", specifier = "~=4.6.0" },
|
||||
{ name = "types-requests", specifier = "~=2.32.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "coverage"
|
||||
version = "7.10.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f4/2c/253cc41cd0f40b84c1c34c5363e0407d73d4a1cae005fed6db3b823175bd/coverage-7.10.3.tar.gz", hash = "sha256:812ba9250532e4a823b070b0420a36499859542335af3dca8f47fc6aa1a05619", size = 822936, upload-time = "2025-08-10T21:27:39.968Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/62/13c0b66e966c43d7aa64dadc8cd2afa1f5a2bf9bb863bdabc21fb94e8b63/coverage-7.10.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:449c1e2d3a84d18bd204258a897a87bc57380072eb2aded6a5b5226046207b42", size = 216262, upload-time = "2025-08-10T21:25:55.367Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/f0/59fdf79be7ac2f0206fc739032f482cfd3f66b18f5248108ff192741beae/coverage-7.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d4f9ce50b9261ad196dc2b2e9f1fbbee21651b54c3097a25ad783679fd18294", size = 216496, upload-time = "2025-08-10T21:25:56.759Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/b1/bc83788ba31bde6a0c02eb96bbc14b2d1eb083ee073beda18753fa2c4c66/coverage-7.10.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4dd4564207b160d0d45c36a10bc0a3d12563028e8b48cd6459ea322302a156d7", size = 247989, upload-time = "2025-08-10T21:25:58.067Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/29/f8bdf88357956c844bd872e87cb16748a37234f7f48c721dc7e981145eb7/coverage-7.10.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5ca3c9530ee072b7cb6a6ea7b640bcdff0ad3b334ae9687e521e59f79b1d0437", size = 250738, upload-time = "2025-08-10T21:25:59.406Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/df/6396301d332b71e42bbe624670af9376f63f73a455cc24723656afa95796/coverage-7.10.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b6df359e59fa243c9925ae6507e27f29c46698359f45e568fd51b9315dbbe587", size = 251868, upload-time = "2025-08-10T21:26:00.65Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/21/d760b2df6139b6ef62c9cc03afb9bcdf7d6e36ed4d078baacffa618b4c1c/coverage-7.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a181e4c2c896c2ff64c6312db3bda38e9ade2e1aa67f86a5628ae85873786cea", size = 249790, upload-time = "2025-08-10T21:26:02.009Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/91/5dcaa134568202397fa4023d7066d4318dc852b53b428052cd914faa05e1/coverage-7.10.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a374d4e923814e8b72b205ef6b3d3a647bb50e66f3558582eda074c976923613", size = 247907, upload-time = "2025-08-10T21:26:03.757Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/ed/70c0e871cdfef75f27faceada461206c1cc2510c151e1ef8d60a6fedda39/coverage-7.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:daeefff05993e5e8c6e7499a8508e7bd94502b6b9a9159c84fd1fe6bce3151cb", size = 249344, upload-time = "2025-08-10T21:26:05.11Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/55/c8a273ed503cedc07f8a00dcd843daf28e849f0972e4c6be4c027f418ad6/coverage-7.10.3-cp312-cp312-win32.whl", hash = "sha256:187ecdcac21f9636d570e419773df7bd2fda2e7fa040f812e7f95d0bddf5f79a", size = 218693, upload-time = "2025-08-10T21:26:06.534Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/58/dd3cfb2473b85be0b6eb8c5b6d80b6fc3f8f23611e69ef745cef8cf8bad5/coverage-7.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:4a50ad2524ee7e4c2a95e60d2b0b83283bdfc745fe82359d567e4f15d3823eb5", size = 219501, upload-time = "2025-08-10T21:26:08.195Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/56/af/7cbcbf23d46de6f24246e3f76b30df099d05636b30c53c158a196f7da3ad/coverage-7.10.3-cp312-cp312-win_arm64.whl", hash = "sha256:c112f04e075d3495fa3ed2200f71317da99608cbb2e9345bdb6de8819fc30571", size = 218135, upload-time = "2025-08-10T21:26:09.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/19/e67f4ae24e232c7f713337f3f4f7c9c58afd0c02866fb07c7b9255a19ed7/coverage-7.10.3-py3-none-any.whl", hash = "sha256:416a8d74dc0adfd33944ba2f405897bab87b7e9e84a391e09d241956bd953ce1", size = 207921, upload-time = "2025-08-10T21:27:38.254Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -810,21 +831,22 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "mypy"
|
||||
version = "1.15.0"
|
||||
version = "1.17.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mypy-extensions" },
|
||||
{ name = "pathspec" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717, upload-time = "2025-02-05T03:50:34.655Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8e/22/ea637422dedf0bf36f3ef238eab4e455e2a0dcc3082b5cc067615347ab8e/mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01", size = 3352570, upload-time = "2025-07-31T07:54:19.204Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981, upload-time = "2025-02-05T03:50:28.25Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175, upload-time = "2025-02-05T03:50:13.411Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675, upload-time = "2025-02-05T03:50:31.421Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020, upload-time = "2025-02-05T03:48:48.705Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582, upload-time = "2025-02-05T03:49:03.628Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614, upload-time = "2025-02-05T03:50:00.313Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777, upload-time = "2025-02-05T03:50:08.348Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/a2/7034d0d61af8098ec47902108553122baa0f438df8a713be860f7407c9e6/mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb", size = 11086295, upload-time = "2025-07-31T07:53:28.124Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/1f/19e7e44b594d4b12f6ba8064dbe136505cec813549ca3e5191e40b1d3cc2/mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403", size = 10112355, upload-time = "2025-07-31T07:53:21.121Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/69/baa33927e29e6b4c55d798a9d44db5d394072eef2bdc18c3e2048c9ed1e9/mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056", size = 11875285, upload-time = "2025-07-31T07:53:55.293Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/13/f3a89c76b0a41e19490b01e7069713a30949d9a6c147289ee1521bcea245/mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341", size = 12737895, upload-time = "2025-07-31T07:53:43.623Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/a1/c4ee79ac484241301564072e6476c5a5be2590bc2e7bfd28220033d2ef8f/mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb", size = 12931025, upload-time = "2025-07-31T07:54:17.125Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/b8/7409477be7919a0608900e6320b155c72caab4fef46427c5cc75f85edadd/mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19", size = 9584664, upload-time = "2025-07-31T07:54:12.842Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/f3/8fcd2af0f5b806f6cf463efaffd3c9548a28f84220493ecd38d127b6b66d/mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9", size = 2283411, upload-time = "2025-07-31T07:53:24.664Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1072,6 +1094,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.12.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.6.0"
|
||||
@@ -1096,17 +1127,19 @@ dependencies = [
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "common", editable = "../common" },
|
||||
{ name = "protobuf", specifier = ">=3.20,<=3.20.3" },
|
||||
{ name = "protobuf", specifier = "==3.20.3" },
|
||||
{ name = "rapidfuzz", specifier = "~=3.12.2" },
|
||||
{ name = "tree-sitter", specifier = ">=0.24.0" },
|
||||
{ name = "tree-sitter-language-pack", specifier = ">=0.4.0" },
|
||||
{ name = "tree-sitter", specifier = "~=0.24.0" },
|
||||
{ name = "tree-sitter-language-pack", specifier = "~=0.9.0" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "mypy", specifier = ">=1.15.0" },
|
||||
{ name = "pytest", specifier = ">=8.3.4" },
|
||||
{ name = "ruff", specifier = ">=0.9.2" },
|
||||
{ name = "mypy", specifier = "~=1.17.1" },
|
||||
{ name = "pytest", specifier = "~=8.3.4" },
|
||||
{ name = "pytest-cov", specifier = "~=6.0.0" },
|
||||
{ name = "ruff", specifier = "~=0.12.8" },
|
||||
{ name = "types-redis", specifier = "~=4.6.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1193,36 +1226,35 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-settings"
|
||||
version = "2.10.1"
|
||||
version = "2.7.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "python-dotenv" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/68/85/1ea668bbab3c50071ca613c6ab30047fb36ab0da1b92fa8f17bbc38fd36c/pydantic_settings-2.10.1.tar.gz", hash = "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee", size = 172583, upload-time = "2025-06-24T13:26:46.841Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/73/7b/c58a586cd7d9ac66d2ee4ba60ca2d241fa837c02bca9bea80a9a8c3d22a9/pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93", size = 79920, upload-time = "2024-12-31T11:27:44.632Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl", hash = "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796", size = 45235, upload-time = "2025-06-24T13:26:45.485Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/46/93416fdae86d40879714f72956ac14df9c7b76f7d41a4d68aa9f71a0028b/pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd", size = 29718, upload-time = "2024-12-31T11:27:43.201Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pymongo"
|
||||
version = "4.13.2"
|
||||
version = "4.10.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "dnspython" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4b/5a/d664298bf54762f0c89b8aa2c276868070e06afb853b4a8837de5741e5f9/pymongo-4.13.2.tar.gz", hash = "sha256:0f64c6469c2362962e6ce97258ae1391abba1566a953a492562d2924b44815c2", size = 2167844, upload-time = "2025-06-16T18:16:30.685Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1a/35/b62a3139f908c68b69aac6a6a3f8cc146869de0a7929b994600e2c587c77/pymongo-4.10.1.tar.gz", hash = "sha256:a9de02be53b6bb98efe0b9eda84ffa1ec027fcb23a2de62c4f941d9a2f2f3330", size = 1903902, upload-time = "2024-10-01T23:07:58.525Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/03/e0/0e187750e23eed4227282fcf568fdb61f2b53bbcf8cbe3a71dde2a860d12/pymongo-4.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ec89516622dfc8b0fdff499612c0bd235aa45eeb176c9e311bcc0af44bf952b6", size = 912004, upload-time = "2025-06-16T18:15:14.299Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/c2/9b79795382daaf41e5f7379bffdef1880d68160adea352b796d6948cb5be/pymongo-4.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f30eab4d4326df54fee54f31f93e532dc2918962f733ee8e115b33e6fe151d92", size = 911698, upload-time = "2025-06-16T18:15:16.334Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/e4/f04dc9ed5d1d9dbc539dc2d8758dd359c5373b0e06fcf25418b2c366737c/pymongo-4.13.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cce9428d12ba396ea245fc4c51f20228cead01119fcc959e1c80791ea45f820", size = 1690357, upload-time = "2025-06-16T18:15:18.358Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/de/41478a7d527d38f1b98b084f4a78bbb805439a6ebd8689fbbee0a3dfacba/pymongo-4.13.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac9241b727a69c39117c12ac1e52d817ea472260dadc66262c3fdca0bab0709b", size = 1754593, upload-time = "2025-06-16T18:15:20.096Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/d9/8fa2eb110291e154f4312779b1a5b815090b8b05a59ecb4f4a32427db1df/pymongo-4.13.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3efc4c515b371a9fa1d198b6e03340985bfe1a55ae2d2b599a714934e7bc61ab", size = 1723637, upload-time = "2025-06-16T18:15:22.048Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/7b/9863fa60a4a51ea09f5e3cd6ceb231af804e723671230f2daf3bd1b59c2b/pymongo-4.13.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f57a664aa74610eb7a52fa93f2cf794a1491f4f76098343485dd7da5b3bcff06", size = 1693613, upload-time = "2025-06-16T18:15:24.866Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/89/a42efa07820a59089836f409a63c96e7a74e33313e50dc39c554db99ac42/pymongo-4.13.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3dcb0b8cdd499636017a53f63ef64cf9b6bd3fd9355796c5a1d228e4be4a4c94", size = 1652745, upload-time = "2025-06-16T18:15:27.078Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/cf/2c77d1acda61d281edd3e3f00d5017d3fac0c29042c769efd3b8018cb469/pymongo-4.13.2-cp312-cp312-win32.whl", hash = "sha256:bf43ae07804d7762b509f68e5ec73450bb8824e960b03b861143ce588b41f467", size = 883232, upload-time = "2025-06-16T18:15:29.169Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/4f/727f59156e3798850c3c2901f106804053cb0e057ed1bd9883f5fa5aa8fa/pymongo-4.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:812a473d584bcb02ab819d379cd5e752995026a2bb0d7713e78462b6650d3f3a", size = 903304, upload-time = "2025-06-16T18:15:31.346Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/d1/60ad99fe3f64d45e6c71ac0e3078e88d9b64112b1bae571fc3707344d6d1/pymongo-4.10.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fbedc4617faa0edf423621bb0b3b8707836687161210d470e69a4184be9ca011", size = 943356, upload-time = "2024-10-01T23:06:50.9Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/9b/21d4c6b4ee9c1fa9691c68dc2a52565e0acb644b9e95148569b4736a4ebd/pymongo-4.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7bd26b2aec8ceeb95a5d948d5cc0f62b0eb6d66f3f4230705c1e3d3d2c04ec76", size = 943142, upload-time = "2024-10-01T23:06:52.146Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/af/691b7454e219a8eb2d1641aecedd607e3a94b93650c2011ad8a8fd74ef9f/pymongo-4.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb104c3c2a78d9d85571c8ac90ec4f95bca9b297c6eee5ada71fabf1129e1674", size = 1909129, upload-time = "2024-10-01T23:06:53.551Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/74/fd75d5ad4181d6e71ce0fca32404fb71b5046ac84d9a1a2f0862262dd032/pymongo-4.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4924355245a9c79f77b5cda2db36e0f75ece5faf9f84d16014c0a297f6d66786", size = 1987763, upload-time = "2024-10-01T23:06:55.304Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/56/6d3d0ef63c6d8cb98c7c653a3a2e617675f77a95f3853851d17a7664876a/pymongo-4.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:11280809e5dacaef4971113f0b4ff4696ee94cfdb720019ff4fa4f9635138252", size = 1950821, upload-time = "2024-10-01T23:06:57.541Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/ed/1603fa0c0e51444752c3fa91f16c3a97e6d92eb9fe5e553dae4f18df16f6/pymongo-4.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5d55f2a82e5eb23795f724991cac2bffbb1c0f219c0ba3bf73a835f97f1bb2e", size = 1912247, upload-time = "2024-10-01T23:06:59.023Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/66/e98b2308971d45667cb8179d4d66deca47336c90663a7e0527589f1038b7/pymongo-4.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e974ab16a60be71a8dfad4e5afccf8dd05d41c758060f5d5bda9a758605d9a5d", size = 1862230, upload-time = "2024-10-01T23:07:01.407Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/80/ba9b7ed212a5f8cf8ad7037ed5bbebc1c587fc09242108f153776e4a338b/pymongo-4.10.1-cp312-cp312-win32.whl", hash = "sha256:544890085d9641f271d4f7a47684450ed4a7344d6b72d5968bfae32203b1bb7c", size = 903045, upload-time = "2024-10-01T23:07:02.973Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/8b/5afce891d78159912c43726fab32641e3f9718f14be40f978c148ea8db48/pymongo-4.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:dcc07b1277e8b4bf4d7382ca133850e323b7ab048b8353af496d050671c7ac52", size = 926686, upload-time = "2024-10-01T23:07:04.403Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1240,6 +1272,31 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-asyncio"
|
||||
version = "0.25.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f2/a8/ecbc8ede70921dd2f544ab1cadd3ff3bf842af27f87bbdea774c7baa1d38/pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a", size = 54239, upload-time = "2025-01-28T18:37:58.729Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/67/17/3493c5624e48fd97156ebaec380dcaafee9506d7e2c46218ceebbb57d7de/pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3", size = 19467, upload-time = "2025-01-28T18:37:56.798Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-cov"
|
||||
version = "6.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "coverage" },
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945, upload-time = "2024-10-29T20:13:35.363Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949, upload-time = "2024-10-29T20:13:33.215Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
version = "2.9.0.post0"
|
||||
@@ -1254,11 +1311,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.1.1"
|
||||
version = "1.0.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115, upload-time = "2024-01-23T06:33:00.505Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863, upload-time = "2024-01-23T06:32:58.246Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1362,27 +1419,27 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.6.9"
|
||||
version = "0.12.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/26/0d/6148a48dab5662ca1d5a93b7c0d13c03abd3cc7e2f35db08410e47cef15d/ruff-0.6.9.tar.gz", hash = "sha256:b076ef717a8e5bc819514ee1d602bbdca5b4420ae13a9cf61a0c0a4f53a2baa2", size = 3095355, upload-time = "2024-10-04T13:40:28.594Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4b/da/5bd7565be729e86e1442dad2c9a364ceeff82227c2dece7c29697a9795eb/ruff-0.12.8.tar.gz", hash = "sha256:4cb3a45525176e1009b2b64126acf5f9444ea59066262791febf55e40493a033", size = 5242373, upload-time = "2025-08-07T19:05:47.268Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/8f/f7a0a0ef1818662efb32ed6df16078c95da7a0a3248d64c2410c1e27799f/ruff-0.6.9-py3-none-linux_armv6l.whl", hash = "sha256:064df58d84ccc0ac0fcd63bc3090b251d90e2a372558c0f057c3f75ed73e1ccd", size = 10440526, upload-time = "2024-10-04T13:39:21.747Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/69/b179a5faf936a9e2ab45bb412a668e4661eded964ccfa19d533f29463ef6/ruff-0.6.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:140d4b5c9f5fc7a7b074908a78ab8d384dd7f6510402267bc76c37195c02a7ec", size = 10034612, upload-time = "2024-10-04T13:39:26.301Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/ef/fd1b4be979c579d191eeac37b5cfc0ec906de72c8bcd8595e2c81bb700c1/ruff-0.6.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53fd8ca5e82bdee8da7f506d7b03a261f24cd43d090ea9db9a1dc59d9313914c", size = 9706197, upload-time = "2024-10-04T13:39:29.297Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/61/b376d775deb5851cb48d893c568b511a6d3625ef2c129ad5698b64fb523c/ruff-0.6.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645d7d8761f915e48a00d4ecc3686969761df69fb561dd914a773c1a8266e14e", size = 10751855, upload-time = "2024-10-04T13:39:33.175Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/d7/def9e5f446d75b9a9c19b24231a3a658c075d79163b08582e56fa5dcfa38/ruff-0.6.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eae02b700763e3847595b9d2891488989cac00214da7f845f4bcf2989007d577", size = 10200889, upload-time = "2024-10-04T13:39:36.867Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/d6/7f34160818bcb6e84ce293a5966cba368d9112ff0289b273fbb689046047/ruff-0.6.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d5ccc9e58112441de8ad4b29dcb7a86dc25c5f770e3c06a9d57e0e5eba48829", size = 11038678, upload-time = "2024-10-04T13:39:40.428Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/34/a40ff8ae62fb1b26fb8e6fa7e64bc0e0a834b47317880de22edd6bfb54fb/ruff-0.6.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:417b81aa1c9b60b2f8edc463c58363075412866ae4e2b9ab0f690dc1e87ac1b5", size = 11808682, upload-time = "2024-10-04T13:39:52.141Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/6d/25a4386ae4009fc798bd10ba48c942d1b0b3e459b5403028f1214b6dd161/ruff-0.6.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c866b631f5fbce896a74a6e4383407ba7507b815ccc52bcedabb6810fdb3ef7", size = 11330446, upload-time = "2024-10-04T13:39:55.783Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/f6/bdf891a9200d692c94ebcd06ae5a2fa5894e522f2c66c2a12dd5d8cb2654/ruff-0.6.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b118afbb3202f5911486ad52da86d1d52305b59e7ef2031cea3425142b97d6f", size = 12483048, upload-time = "2024-10-04T13:39:58.845Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/86/96f4252f41840e325b3fa6c48297e661abb9f564bd7dcc0572398c8daa42/ruff-0.6.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67267654edc23c97335586774790cde402fb6bbdb3c2314f1fc087dee320bfa", size = 10936855, upload-time = "2024-10-04T13:40:01.818Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/87/801a52d26c8dbf73424238e9908b9ceac430d903c8ef35eab1b44fcfa2bd/ruff-0.6.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3ef0cc774b00fec123f635ce5c547dac263f6ee9fb9cc83437c5904183b55ceb", size = 10713007, upload-time = "2024-10-04T13:40:05.384Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/27/6f7161d90320a389695e32b6ebdbfbedde28ccbf52451e4b723d7ce744ad/ruff-0.6.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:12edd2af0c60fa61ff31cefb90aef4288ac4d372b4962c2864aeea3a1a2460c0", size = 10274594, upload-time = "2024-10-04T13:40:08.801Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/52/dc311775e7b5f5b19831563cb1572ecce63e62681bccc609867711fae317/ruff-0.6.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:55bb01caeaf3a60b2b2bba07308a02fca6ab56233302406ed5245180a05c5625", size = 10608024, upload-time = "2024-10-04T13:40:11.923Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/b6/be0a1ddcbac65a30c985cf7224c4fce786ba2c51e7efeb5178fe410ed3cf/ruff-0.6.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:925d26471fa24b0ce5a6cdfab1bb526fb4159952385f386bdcc643813d472039", size = 10982085, upload-time = "2024-10-04T13:40:15.539Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/a4/c84bc13d0b573cf7bb7d17b16d6d29f84267c92d79b2f478d4ce322e8e72/ruff-0.6.9-py3-none-win32.whl", hash = "sha256:eb61ec9bdb2506cffd492e05ac40e5bc6284873aceb605503d8494180d6fc84d", size = 8522088, upload-time = "2024-10-04T13:40:19.168Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/be/fc352bd8ca40daae8740b54c1c3e905a7efe470d420a268cd62150248c91/ruff-0.6.9-py3-none-win_amd64.whl", hash = "sha256:785d31851c1ae91f45b3d8fe23b8ae4b5170089021fbb42402d811135f0b7117", size = 9359275, upload-time = "2024-10-04T13:40:22.852Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/14/fd026bc74ded05e2351681545a5f626e78ef831f8edce064d61acd2e6ec7/ruff-0.6.9-py3-none-win_arm64.whl", hash = "sha256:a9641e31476d601f83cd602608739a0840e348bda93fec9f1ee816f8b6798b93", size = 8679879, upload-time = "2024-10-04T13:40:25.797Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/1e/c843bfa8ad1114fab3eb2b78235dda76acd66384c663a4e0415ecc13aa1e/ruff-0.12.8-py3-none-linux_armv6l.whl", hash = "sha256:63cb5a5e933fc913e5823a0dfdc3c99add73f52d139d6cd5cc8639d0e0465513", size = 11675315, upload-time = "2025-08-07T19:05:06.15Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/ee/af6e5c2a8ca3a81676d5480a1025494fd104b8896266502bb4de2a0e8388/ruff-0.12.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9a9bbe28f9f551accf84a24c366c1aa8774d6748438b47174f8e8565ab9dedbc", size = 12456653, upload-time = "2025-08-07T19:05:09.759Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/9d/e91f84dfe3866fa648c10512904991ecc326fd0b66578b324ee6ecb8f725/ruff-0.12.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2fae54e752a3150f7ee0e09bce2e133caf10ce9d971510a9b925392dc98d2fec", size = 11659690, upload-time = "2025-08-07T19:05:12.551Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/ac/a363d25ec53040408ebdd4efcee929d48547665858ede0505d1d8041b2e5/ruff-0.12.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0acbcf01206df963d9331b5838fb31f3b44fa979ee7fa368b9b9057d89f4a53", size = 11896923, upload-time = "2025-08-07T19:05:14.821Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/9f/ea356cd87c395f6ade9bb81365bd909ff60860975ca1bc39f0e59de3da37/ruff-0.12.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae3e7504666ad4c62f9ac8eedb52a93f9ebdeb34742b8b71cd3cccd24912719f", size = 11477612, upload-time = "2025-08-07T19:05:16.712Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/46/92e8fa3c9dcfd49175225c09053916cb97bb7204f9f899c2f2baca69e450/ruff-0.12.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb82efb5d35d07497813a1c5647867390a7d83304562607f3579602fa3d7d46f", size = 13182745, upload-time = "2025-08-07T19:05:18.709Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/c4/f2176a310f26e6160deaf661ef60db6c3bb62b7a35e57ae28f27a09a7d63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dbea798fc0065ad0b84a2947b0aff4233f0cb30f226f00a2c5850ca4393de609", size = 14206885, upload-time = "2025-08-07T19:05:21.025Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/9d/98e162f3eeeb6689acbedbae5050b4b3220754554526c50c292b611d3a63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49ebcaccc2bdad86fd51b7864e3d808aad404aab8df33d469b6e65584656263a", size = 13639381, upload-time = "2025-08-07T19:05:23.423Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/4e/1b7478b072fcde5161b48f64774d6edd59d6d198e4ba8918d9f4702b8043/ruff-0.12.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ac9c570634b98c71c88cb17badd90f13fc076a472ba6ef1d113d8ed3df109fb", size = 12613271, upload-time = "2025-08-07T19:05:25.507Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/67/0c3c9179a3ad19791ef1b8f7138aa27d4578c78700551c60d9260b2c660d/ruff-0.12.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:560e0cd641e45591a3e42cb50ef61ce07162b9c233786663fdce2d8557d99818", size = 12847783, upload-time = "2025-08-07T19:05:28.14Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/2a/0b6ac3dd045acf8aa229b12c9c17bb35508191b71a14904baf99573a21bd/ruff-0.12.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:71c83121512e7743fba5a8848c261dcc454cafb3ef2934a43f1b7a4eb5a447ea", size = 11702672, upload-time = "2025-08-07T19:05:30.413Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/ee/f9fdc9f341b0430110de8b39a6ee5fa68c5706dc7c0aa940817947d6937e/ruff-0.12.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:de4429ef2ba091ecddedd300f4c3f24bca875d3d8b23340728c3cb0da81072c3", size = 11440626, upload-time = "2025-08-07T19:05:32.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/fb/b3aa2d482d05f44e4d197d1de5e3863feb13067b22c571b9561085c999dc/ruff-0.12.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a2cab5f60d5b65b50fba39a8950c8746df1627d54ba1197f970763917184b161", size = 12462162, upload-time = "2025-08-07T19:05:34.449Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/9f/5c5d93e1d00d854d5013c96e1a92c33b703a0332707a7cdbd0a4880a84fb/ruff-0.12.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:45c32487e14f60b88aad6be9fd5da5093dbefb0e3e1224131cb1d441d7cb7d46", size = 12913212, upload-time = "2025-08-07T19:05:36.541Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/13/ab9120add1c0e4604c71bfc2e4ef7d63bebece0cfe617013da289539cef8/ruff-0.12.8-py3-none-win32.whl", hash = "sha256:daf3475060a617fd5bc80638aeaf2f5937f10af3ec44464e280a9d2218e720d3", size = 11694382, upload-time = "2025-08-07T19:05:38.468Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/dc/a2873b7c5001c62f46266685863bee2888caf469d1edac84bf3242074be2/ruff-0.12.8-py3-none-win_amd64.whl", hash = "sha256:7209531f1a1fcfbe8e46bcd7ab30e2f43604d8ba1c49029bb420b103d0b5f76e", size = 12740482, upload-time = "2025-08-07T19:05:40.391Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/5c/799a1efb8b5abab56e8a9f2a0b72d12bd64bb55815e9476c7d0a2887d2f7/ruff-0.12.8-py3-none-win_arm64.whl", hash = "sha256:c90e1a334683ce41b0e7a04f41790c429bf5073b62c1ae701c9dc5b3d14f0749", size = 11884718, upload-time = "2025-08-07T19:05:42.866Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1422,10 +1479,12 @@ dependencies = [
|
||||
{ name = "wasmtime" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "mypy" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-cov" },
|
||||
{ name = "ruff" },
|
||||
{ name = "tqdm" },
|
||||
{ name = "types-redis" },
|
||||
@@ -1436,19 +1495,24 @@ requires-dist = [
|
||||
{ name = "common", editable = "../common" },
|
||||
{ name = "langchain", specifier = "~=0.3.20" },
|
||||
{ name = "langgraph", specifier = "~=0.5.2" },
|
||||
{ name = "mypy", marker = "extra == 'dev'", specifier = "~=1.15.0" },
|
||||
{ name = "numpy", specifier = "~=2.2.3" },
|
||||
{ name = "program-model", editable = "../program-model" },
|
||||
{ name = "pytest", marker = "extra == 'dev'", specifier = "~=8.3.4" },
|
||||
{ name = "python-dotenv", specifier = ">=1.0.1" },
|
||||
{ name = "python-dotenv", specifier = "~=1.0.1" },
|
||||
{ name = "rapidfuzz", specifier = "~=3.12.2" },
|
||||
{ name = "redis", specifier = "~=5.2.1" },
|
||||
{ name = "ruff", marker = "extra == 'dev'", specifier = "~=0.6.2" },
|
||||
{ name = "tqdm", marker = "extra == 'dev'", specifier = "~=4.67.1" },
|
||||
{ name = "types-redis", marker = "extra == 'dev'" },
|
||||
{ name = "wasmtime", specifier = "~=29.0.0" },
|
||||
]
|
||||
provides-extras = ["dev"]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "mypy", specifier = "~=1.17.1" },
|
||||
{ name = "pytest", specifier = "~=8.3.4" },
|
||||
{ name = "pytest-asyncio", specifier = "~=0.25.2" },
|
||||
{ name = "pytest-cov", specifier = "~=6.0.0" },
|
||||
{ name = "ruff", specifier = "~=0.12.8" },
|
||||
{ name = "tqdm", specifier = "~=4.67.1" },
|
||||
{ name = "types-redis", specifier = "~=4.6.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
@@ -1710,18 +1774,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f", size = 8827, upload-time = "2023-05-24T20:25:45.287Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-inspection"
|
||||
version = "0.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.5.0"
|
||||
|
||||
Reference in New Issue
Block a user