Add V3 compatibility (#23)
* Update project configuration and name - Excluded virtual environment folder from module content. - Changed JDK name to "WSL Checker" for clarity. - Updated project name in the configuration file. * Update project configuration and dependencies - Added source folders for `src` and `tests`. - Excluded `.devcontainer` and `.idea` directories. - Updated Black settings in the project configuration. - Changed Ruff version from 0.9.5 to 0.9.6. - Enhanced rule processing by grouping rules before application. - Introduced a new property match mode for better parameter matching. - Removed unused test files and configurations to clean up the codebase. * Shifting to local uv - editing toml * Update CI workflow and project dependencies - Added steps to the CI workflow for better clarity. - Switched from Poetry to pip for dependency management. - Removed poetry.lock file as it's no longer needed. - Updated Python version specification to 3.12. - Adjusted project configuration files for new environment settings. * Update dependencies for pydantic and related packages - Added pydantic version 2.11.0a2 to dependencies. - Updated pydantic-core to version 2.29.0. - Adjusted URLs and hashes for the new package versions in lock file. - Ensured compatibility with existing requirements in project configuration. * Update dependencies to stable versions - Downgraded Pydantic from 2.11.0a2 to 2.10.6 - Updated Pydantic-core version from 2.29.0 to 2.27.2 - Adjusted URLs and hashes for the new package versions in lock file * Update dependencies to latest versions - Upgraded Pydantic from 2.10.6 to 2.11.0a2 - Updated Pydantic Core from 2.27.2 to 2.29.0 - Adjusted source URLs and hashes for new package versions * Update dependencies to stable versions - Downgraded Pydantic from 2.11.0a2 to 2.10.6 - Updated Pydantic-core version from 2.29.0 to 2.27.2 - Adjusted URLs and hashes for the new package versions in lock file * Add pre-commit hook and setup script - Introduced a pre-commit hook to manage dependencies. - Automatically installs and exports requirements before commits. - Added a setup script to copy the hook and set permissions. * Update project config and clean up unused files - Removed Black configuration options from the project settings. - Changed Ruff to run on save instead of reformat. - Deleted example function inputs JSON file. - Removed flatten helper module as it's no longer needed. - Updated pyproject.toml with new line length and ignore rules. - Cleaned up import statements in local test file. * Update line length and tidy up code comments - Increased the maximum line length from 100 to 120. - Cleaned up import statements for better readability. - Improved docstrings for clarity and consistency. - Removed unnecessary blank lines and commented-out code. * Refactor rules handling and improve documentation - Updated class names from `RevitRules` to `PropertyRules`. - Adjusted method calls to reflect the new class structure. - Cleaned up code formatting for better readability. - Enhanced developer README with clearer setup instructions. * Add filtering and rule processing features - Introduced a new filter function to sort objects by category. - Created a predicates module for mapping spreadsheet predicates to rule methods. - Refactored rules handling, simplifying parameter checks and value retrievals. - Enhanced the main automation function with improved input handling and context management. * Past WIP rules for processing Speckle parameters - Introduced a new class to manage parameter rules. - Added methods to check and retrieve display values from Speckle objects. - Implemented filtering for displayable objects based on defined criteria. - Created functions to handle Revit parameter checks and value retrievals. - Included various utility methods for comparing parameter values against thresholds, ranges, and lists. * Add new JSON test data for building elements - Introduced a new JSON file containing detailed specifications for various building elements. - Included parameters such as ID, type, level details, and multiple attributes related to structural components. - Added information on dimensions, materials, and classifications relevant to the construction context. * Rename test files and add new parameter tests - Renamed localtest.py to test_function.py for clarity. - Added a new test file for parameter checks, covering: - Object deserialization structure - Parameter existence and value retrieval in v2 and v3 objects - Numeric comparisons and pattern matching on parameters - List-based and boolean parameter checks * Enhance helper functions and add rule processing - Updated helper functions for better item retrieval and checks. - Added new functions to evaluate conditions and process rules against Speckle objects. - Improved logging with a dedicated print function. - Streamlined flattening logic in existing methods. * Add test runner config and new web resources - Added pytest as the project test runner. - Created a new XML file for web resource paths. - Included pytest-assertcount in development dependencies. * Add robust value comparison methods - Introduced new static methods for comparing values: - `is_equal_value`: Compares two values with type handling and optional case sensitivity. - `is_not_equal_value`: Checks if two values are not equal. - `is_identical_value`: Verifies if two values are exactly identical, considering case sensitivity and no tolerance for floats. - `is_not_identical_value`: Checks if two values are not identical. - Enhanced handling of strings that represent numbers. * Refactor rules and parameter handling - Commented out large sections of code for clarity * Update predicates and enhance tests - Renamed equality-related methods for clarity. - Added new methods for "not equal" and "not identical" checks. - Updated test to return specific objects instead of walls. - Changed property access in tests to use `.keys()`. - Introduced multiple tests for stringified number comparisons, case sensitivity, and floating-point precision. * Add tests for severity level conversion Created a new test file to validate the `get_severity` function. - Added parameterised tests for various input cases including valid and invalid severity strings, empty inputs, and non-string types. - Ensured that all edge cases default to the correct enum value. * Refactor parameter tests for clarity and efficiency - Simplified assertions in parameter existence tests. - Added parameterisation to reduce redundancy across tests. - Enhanced error messages for better debugging. - Consolidated similar test cases for v2 and v3 objects. - Improved structure of boolean and numeric comparison tests. * Enhance spreadsheet data handling - Added a function to convert mixed column types. - Updated the main reading function to use this new conversion. - Improved error handling for reading TSV files. * Update version handling in automation function - Added a global VERSION variable for tracking. - Updated comments to reflect changes from 'version' to 'VERSION'. - Adjusted logic to retrieve the version from the root object. - Enhanced success message to include the current version. * Improve boolean handling and property search - Added None handling in boolean conversion. - Enhanced `find_property` to return raw values if needed. - Updated traversal logic to avoid revisiting objects. - Refined comparison methods for better type handling and tolerance. - Introduced new methods for strict value comparisons with detailed arguments. * Update predicate method mappings Switched from string references to actual method names in the predicate mapping. This improves clarity and reduces errors by directly linking predicates to their corresponding methods in PropertyRules. Adjusted some predicate phrases for consistency as well. * Enhance rule evaluation with severity handling - Added optional parameters for rule and case numbers in condition evaluation. - Introduced an Enum for severity levels to standardise reporting. - Created a function to convert string severities into the SeverityLevel enum, handling various input formats. - Refactored metadata generation to use the new severity function.
This commit is contained in:
committed by
GitHub
parent
f2e06f165e
commit
8582444e56
+18
-11
@@ -11,26 +11,33 @@ jobs:
|
||||
FUNCTION_SCHEMA_FILE_NAME: functionSchema.json
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/setup-python@v5
|
||||
# Step 1: Checkout the repository
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4.2.2
|
||||
|
||||
# Step 2: Set up Python
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Install poetry
|
||||
|
||||
# Step 3: Install dependencies using pip
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
pip install poetry==1.8.4 &&
|
||||
poetry config virtualenvs.create false &&
|
||||
poetry config virtualenvs.in-project false &&
|
||||
poetry config installer.parallel true
|
||||
- name: Restore dependencies
|
||||
run: poetry install --no-root
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Step 4: Generate the schema
|
||||
- name: Extract functionInputSchema
|
||||
id: extract_schema
|
||||
run: |
|
||||
python main.py generate_schema ${HOME}/${{ env.FUNCTION_SCHEMA_FILE_NAME }}
|
||||
python main.py generate_schema "${{ env.FUNCTION_SCHEMA_FILE_NAME }}"
|
||||
|
||||
# Step 5: Build and publish the Speckle function
|
||||
- name: Speckle Automate Function - Build and Publish
|
||||
uses: specklesystems/speckle-automate-github-composite-action@0.9.0
|
||||
with:
|
||||
speckle_automate_url: ${{ env.SPECKLE_AUTOMATE_URL || vars.SPECKLE_AUTOMATE_URL || 'https://automate.speckle.dev' }}
|
||||
speckle_automate_url: ${{ env.SPECKLE_AUTOMATE_URL || 'https://automate.speckle.dev' }}
|
||||
speckle_token: ${{ secrets.SPECKLE_FUNCTION_TOKEN }}
|
||||
speckle_function_id: ${{ secrets.SPECKLE_FUNCTION_ID }}
|
||||
speckle_function_input_schema_file_path: ${{ env.FUNCTION_SCHEMA_FILE_NAME }}
|
||||
|
||||
Generated
+9
-2
@@ -1,12 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.11.4 WSL (UbuntuDev): (/home/jsdbroughton/.virtualenvs/speckle_automate-mesh_density_checker/bin/python)" jdkType="Python SDK" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="uv (Checker)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PyDocumentationSettings">
|
||||
<option name="format" value="GOOGLE" />
|
||||
<option name="myDocStringFormat" value="Google" />
|
||||
</component>
|
||||
<component name="TestRunnerService">
|
||||
<option name="PROJECT_TEST_RUNNER" value="py.test" />
|
||||
</component>
|
||||
</module>
|
||||
Generated
+2
-2
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.11.4 WSL (UbuntuDev): (/home/jsdbroughton/.virtualenvs/speckle_automate-mesh_density_checker/bin/python)" />
|
||||
<option name="sdkName" value="WSL Checker" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11.4 WSL (UbuntuDev): (/home/jsdbroughton/.virtualenvs/speckle_automate-mesh_density_checker/bin/python)" project-jdk-type="Python SDK" />
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="uv (Checker)" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
Generated
+2
@@ -1,7 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RuffConfigService">
|
||||
<option name="enableLsp" value="false" />
|
||||
<option name="runRuffOnSave" value="true" />
|
||||
<option name="useRuffFormat" value="true" />
|
||||
<option name="useRuffServer" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+14
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="WebResourcesPaths">
|
||||
<contentEntries>
|
||||
<entry url="file://$PROJECT_DIR$">
|
||||
<entryData>
|
||||
<resourceRoots>
|
||||
<path value="file://$PROJECT_DIR$/test_data" />
|
||||
</resourceRoots>
|
||||
</entryData>
|
||||
</entry>
|
||||
</contentEntries>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1 @@
|
||||
3.12
|
||||
+3
-1
@@ -3,11 +3,13 @@
|
||||
## Setup
|
||||
|
||||
1. Install dependencies:
|
||||
|
||||
```bash
|
||||
poetry shell && poetry install
|
||||
```
|
||||
|
||||
2. Configure `.env`:
|
||||
|
||||
```
|
||||
SPECKLE_TOKEN=your_speckle_token
|
||||
SPECKLE_SERVER_URL=app.speckle.systems
|
||||
@@ -32,7 +34,7 @@ poetry run pytest
|
||||
## Extending Rules
|
||||
|
||||
1. Add new predicate to `input_predicate_mapping` in `rules.py`
|
||||
2. Create corresponding method in `RevitRules` class
|
||||
2. Create corresponding method in `PropertyRules` class
|
||||
3. Update tests
|
||||
|
||||
## Building
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"speckleToken": "YOUR SPEKCLE TOKEN",
|
||||
"functionInputs": {
|
||||
"whisperMessage": "you are doing something weird",
|
||||
"forbiddenSpeckleType": "wall"
|
||||
},
|
||||
"automationRunData": {
|
||||
"project_id": "project id",
|
||||
"speckle_server_url": "https://latest.speckle.systems",
|
||||
"automation_id": "automation id",
|
||||
"automation_run_id": "automation run id",
|
||||
"function_run_id": "function run id",
|
||||
"triggers": [
|
||||
{
|
||||
"payload": { "modelId": "model id", "versionId": "version id" },
|
||||
"triggerType": "versionCreation"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
"""Helper module for a simple speckle object tree flattening."""
|
||||
|
||||
from collections.abc import Iterable
|
||||
|
||||
from specklepy.objects import Base
|
||||
|
||||
|
||||
def flatten_base(base: Base) -> Iterable[Base]:
|
||||
"""Flatten a base object into an iterable of bases.
|
||||
|
||||
This function recursively traverses the `elements` or `@elements` attribute of the
|
||||
base object, yielding each nested base object.
|
||||
|
||||
Args:
|
||||
base (Base): The base object to flatten.
|
||||
|
||||
Yields:
|
||||
Base: Each nested base object in the hierarchy.
|
||||
"""
|
||||
# Attempt to get the elements attribute, fallback to @elements if necessary
|
||||
elements = getattr(base, "elements", getattr(base, "@elements", None))
|
||||
|
||||
if elements is not None:
|
||||
for element in elements:
|
||||
yield from flatten_base(element)
|
||||
|
||||
yield base
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
echo "Running pre-commit hook..."
|
||||
|
||||
# Ensure dependencies are installed with uv
|
||||
uv pip install --requirement requirements.txt
|
||||
|
||||
# Export dependencies with uv (and overwrite requirements.txt)
|
||||
uv pip freeze > requirements.txt
|
||||
|
||||
# Add generated requirements.txt to git
|
||||
git add requirements.txt
|
||||
|
||||
echo "Pre-commit hook completed successfully!"
|
||||
Generated
-1797
File diff suppressed because it is too large
Load Diff
+22
-20
@@ -1,30 +1,30 @@
|
||||
[tool.poetry]
|
||||
name = "speckle-automate-py"
|
||||
[project]
|
||||
name = "speckle-automate-checker"
|
||||
version = "0.1.0"
|
||||
description = "Allows for QAQC property checking with Speckle"
|
||||
authors = ["Jonathon Broughton <jonathon@speckle.systems>"]
|
||||
readme = "README.md"
|
||||
package-mode = false
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"more-itertools>=10.6.0",
|
||||
"pandas>=2.2.3",
|
||||
"pydantic==2.10.6",
|
||||
"python-dotenv>=1.0.1",
|
||||
"python-levenshtein>=0.26.1",
|
||||
"specklepy>=2.21.2",
|
||||
]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
more-itertools = "^10.6.0"
|
||||
pandas = "^2.2.3"
|
||||
python = "^3.11"
|
||||
python-dotenv = "^1.0.1"
|
||||
python-levenshtein = "^0.26.1"
|
||||
specklepy = "^2.21.0"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
black = "^25.0.0"
|
||||
mypy = "^1.3.0"
|
||||
pydantic-settings = "^2.3.0"
|
||||
pytest = "^8.0.0"
|
||||
ruff = "^0.9.5"
|
||||
# specklepy = { path = "../specklepy", develop = true }
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest-assertcount>=1.0.0",
|
||||
"black>=25.1.0",
|
||||
"mypy>=1.15.0",
|
||||
"pydantic-settings>=2.7.1",
|
||||
"pytest>=8.3.4",
|
||||
"ruff>=0.9.6",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.ruff]
|
||||
select = [
|
||||
@@ -34,6 +34,8 @@ select = [
|
||||
"D", # pydocstyle
|
||||
"I", # isort
|
||||
]
|
||||
line-length = 120
|
||||
ignore = ["F401", "F403"]
|
||||
|
||||
[tool.ruff.pydocstyle]
|
||||
convention = "google"
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
annotated-types==0.7.0
|
||||
anyio==4.8.0
|
||||
appdirs==1.4.4
|
||||
attrs==23.2.0
|
||||
backoff==2.2.1
|
||||
black==25.1.0
|
||||
certifi==2025.1.31
|
||||
charset-normalizer==3.4.1
|
||||
click==8.1.8
|
||||
colorama==0.4.6
|
||||
deprecated==1.2.18
|
||||
gql==3.5.0
|
||||
graphql-core==3.2.6
|
||||
h11==0.14.0
|
||||
httpcore==1.0.7
|
||||
httpx==0.25.2
|
||||
idna==3.10
|
||||
iniconfig==2.0.0
|
||||
levenshtein==0.26.1
|
||||
more-itertools==10.6.0
|
||||
multidict==6.1.0
|
||||
mypy==1.15.0
|
||||
mypy-extensions==1.0.0
|
||||
numpy==2.2.2
|
||||
packaging==24.2
|
||||
pandas==2.2.3
|
||||
pathspec==0.12.1
|
||||
platformdirs==4.3.6
|
||||
pluggy==1.5.0
|
||||
propcache==0.2.1
|
||||
pydantic==2.10.6
|
||||
pydantic-core==2.27.2
|
||||
pydantic-settings==2.7.1
|
||||
pytest==8.3.4
|
||||
pytest-assertcount==1.0.0
|
||||
python-dateutil==2.9.0.post0
|
||||
python-dotenv==1.0.1
|
||||
python-levenshtein==0.26.1
|
||||
pytz==2025.1
|
||||
rapidfuzz==3.12.1
|
||||
requests==2.32.3
|
||||
requests-toolbelt==1.0.0
|
||||
ruff==0.9.6
|
||||
six==1.17.0
|
||||
sniffio==1.3.1
|
||||
specklepy==2.21.2
|
||||
stringcase==1.2.0
|
||||
typing-extensions==4.12.2
|
||||
tzdata==2025.1
|
||||
ujson==5.10.0
|
||||
urllib3==2.3.0
|
||||
websockets==11.0.3
|
||||
wrapt==1.17.2
|
||||
yarl==1.18.3
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copy the pre-commit hook to the .git/hooks/ directory
|
||||
cp hooks/pre-commit .git/hooks/pre-commit
|
||||
|
||||
# Ensure the hook is executable
|
||||
chmod +x .git/hooks/pre-commit
|
||||
|
||||
echo "Git hooks have been set up!"
|
||||
@@ -0,0 +1,31 @@
|
||||
from specklepy.objects.base import Base
|
||||
|
||||
from src.rules import PropertyRules
|
||||
|
||||
|
||||
def filter_objects_by_category(speckle_objects: list[Base], category_input: str) -> tuple[list[Base], list[Base]]:
|
||||
"""Filters objects by category value and test.
|
||||
|
||||
This function takes a list of Speckle objects, filters out the objects
|
||||
with a matching category value and satisfies the test, and returns
|
||||
both the matching and non-matching objects.
|
||||
|
||||
Args:
|
||||
speckle_objects (List[Base]): The list of Speckle objects to filter.
|
||||
category_input (str): The category value to match against.
|
||||
|
||||
Returns:
|
||||
Tuple[List[Base], List[Base]]: A tuple containing two lists:
|
||||
- The first list contains objects with matching category and test.
|
||||
- The second list contains objects without matching category or test.
|
||||
"""
|
||||
matching_objects = []
|
||||
non_matching_objects = []
|
||||
|
||||
for obj in speckle_objects:
|
||||
if PropertyRules.is_category(obj, category_input):
|
||||
matching_objects.append(obj)
|
||||
else:
|
||||
non_matching_objects.append(obj)
|
||||
|
||||
return matching_objects, non_matching_objects
|
||||
+27
-15
@@ -1,21 +1,24 @@
|
||||
"""This module contains the function's business logic.
|
||||
# This is the main function that will be executed when the automation is triggered.
|
||||
# It will receive the inputs from the user, and the context of the run.
|
||||
# It will then apply the rules to the objects in the model, and report back the results.
|
||||
|
||||
Use the automation_context module to wrap your function in an Automate context helper.
|
||||
"""
|
||||
from pandas import DataFrame
|
||||
from speckle_automate import AutomationContext
|
||||
from specklepy.objects.base import Base
|
||||
|
||||
from speckle_automate import AutomationContext, AutomateBase
|
||||
|
||||
from src.rules import apply_rules_to_objects
|
||||
from src.inputs import FunctionInputs
|
||||
from src.helpers import flatten_base
|
||||
from src.inputs import FunctionInputs
|
||||
from src.rule_processor import apply_rules_to_objects
|
||||
from src.spreadsheet import read_rules_from_spreadsheet
|
||||
|
||||
VERSION: int = 2
|
||||
|
||||
|
||||
def automate_function(
|
||||
automate_context: AutomationContext,
|
||||
function_inputs: FunctionInputs,
|
||||
) -> None:
|
||||
"""This version of the function will add a check for the new provide inputs.
|
||||
"""This VERSION of the function will add a check for the new provide inputs.
|
||||
|
||||
Args:
|
||||
automate_context: A context helper object, that carries relevant information
|
||||
@@ -24,23 +27,32 @@ def automate_function(
|
||||
It also has convenience methods attach result data to the Speckle model.
|
||||
function_inputs: An instance object matching the defined schema.
|
||||
"""
|
||||
|
||||
# the context provides a convenient way, to receive the triggering version
|
||||
version_root_object = automate_context.receive_version()
|
||||
# the context provides a convenient way, to receive the triggering VERSION
|
||||
version_root_object: Base = automate_context.receive_version()
|
||||
|
||||
# We can continue to work with a flattened list of objects.
|
||||
flat_list_of_objects = list(flatten_base(version_root_object))
|
||||
|
||||
# If it is a next_gen model, we can get the VERSION from the root object
|
||||
# This function's rules don't make use of this check, but it is here for reference if you want to.
|
||||
global VERSION
|
||||
VERSION = getattr(version_root_object, "version", 2) # noqa: F841SION = getattr(version_root_object,"version", 2) # noqa: F841 # noqa: F841
|
||||
|
||||
# read the rules from the spreadsheet
|
||||
rules = read_rules_from_spreadsheet(function_inputs.spreadsheet_url)
|
||||
rules: DataFrame = read_rules_from_spreadsheet(function_inputs.spreadsheet_url)
|
||||
|
||||
if (rules is None) or (len(rules) == 0):
|
||||
automate_context.mark_run_exception("No rules defined")
|
||||
|
||||
grouped_rules = rules.groupby("Rule Number")
|
||||
|
||||
# apply the rules to the objects
|
||||
apply_rules_to_objects(flat_list_of_objects, rules, automate_context)
|
||||
apply_rules_to_objects(flat_list_of_objects, grouped_rules, automate_context)
|
||||
|
||||
# set the automation context view, to the original model / version view
|
||||
# set the automation context view, to the original model / VERSION view
|
||||
automate_context.set_context_view()
|
||||
|
||||
# report success
|
||||
automate_context.mark_run_success(
|
||||
f"Successfully applied rules to {len(flat_list_of_objects)} objects."
|
||||
f"Successfully applied {len(grouped_rules)} rules to {len(flat_list_of_objects)} version {VERSION} objects."
|
||||
)
|
||||
|
||||
+32
-20
@@ -1,14 +1,14 @@
|
||||
"""Helper module for a speckle object tree flattening."""
|
||||
|
||||
from collections.abc import Iterable
|
||||
from typing import Optional, Tuple, List
|
||||
from collections.abc import Generator, Iterable
|
||||
from typing import Any
|
||||
|
||||
from specklepy.objects import Base
|
||||
from specklepy.objects.other import Instance, Transform
|
||||
|
||||
|
||||
def speckle_print(log_string: str = "banana") -> None:
|
||||
|
||||
"""Print a string to the console with a green color."""
|
||||
print("\033[92m" + str(log_string) + "\033[0m")
|
||||
|
||||
|
||||
@@ -21,6 +21,24 @@ def flatten_base(base: Base) -> Iterable[Base]:
|
||||
yield base
|
||||
|
||||
|
||||
def get_item(obj: Base | dict[str, Any], key, default=None):
|
||||
"""Get an item from a dictionary or an object with a default value."""
|
||||
if isinstance(obj, dict): # If it's a dictionary
|
||||
return obj.get(key, default)
|
||||
elif hasattr(obj, key): # If it's an object with the attribute
|
||||
return getattr(obj, key, default)
|
||||
return default # Return default if it's neither a dict nor an object with the attribute
|
||||
|
||||
|
||||
def has_item(obj: Base | dict[str, Any], key: str) -> bool:
|
||||
"""Check if an object has a key or an attribute."""
|
||||
if isinstance(obj, dict):
|
||||
return key in obj
|
||||
elif hasattr(obj, key):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def flatten_base_thorough(base: Base, parent_type: str = None) -> Iterable[Base]:
|
||||
"""Take a base and flatten it to an iterable of bases.
|
||||
|
||||
@@ -51,9 +69,7 @@ def flatten_base_thorough(base: Base, parent_type: str = None) -> Iterable[Base]
|
||||
print(category)
|
||||
if category.startswith("@"):
|
||||
category_object: Base = getattr(base, category)[0]
|
||||
yield from flatten_base_thorough(
|
||||
category_object, category_object.speckle_type
|
||||
)
|
||||
yield from flatten_base_thorough(category_object, category_object.speckle_type)
|
||||
|
||||
except KeyError:
|
||||
pass
|
||||
@@ -63,11 +79,13 @@ def flatten_base_thorough(base: Base, parent_type: str = None) -> Iterable[Base]
|
||||
|
||||
def extract_base_and_transform(
|
||||
base: Base,
|
||||
inherited_instance_id: Optional[str] = None,
|
||||
transform_list: Optional[List[Transform]] = None,
|
||||
) -> Tuple[Base, str, Optional[List[Transform]]]:
|
||||
"""
|
||||
Traverses Speckle object hierarchies to yield `Base` objects and their transformations.
|
||||
inherited_instance_id: str | None = None,
|
||||
transform_list: list[Transform] | None = None,
|
||||
) -> Generator[
|
||||
Base | str | list[Transform] | None | tuple[Base, Any | None, list[Transform] | None | list[Any]], Any | None, None
|
||||
]:
|
||||
"""Traverses Speckle object hierarchies to yield `Base` objects and their transformations.
|
||||
|
||||
Tailored to Speckle's AEC data structures, it covers the newer hierarchical structures
|
||||
with Collections and also with patterns found in older Revit specific data.
|
||||
|
||||
@@ -91,9 +109,7 @@ def extract_base_and_transform(
|
||||
if base.transform:
|
||||
transform_list.append(base.transform)
|
||||
if base.definition:
|
||||
yield from extract_base_and_transform(
|
||||
base.definition, current_id, transform_list.copy()
|
||||
)
|
||||
yield from extract_base_and_transform(base.definition, current_id, transform_list.copy())
|
||||
else:
|
||||
# Initial yield for the current `Base` object.
|
||||
yield base, current_id, transform_list
|
||||
@@ -103,9 +119,7 @@ def extract_base_and_transform(
|
||||
for element in elements_attr:
|
||||
if isinstance(element, Base):
|
||||
# Recurse into each `Base` object within 'elements' or '@elements'.
|
||||
yield from extract_base_and_transform(
|
||||
element, current_id, transform_list.copy()
|
||||
)
|
||||
yield from extract_base_and_transform(element, current_id, transform_list.copy())
|
||||
|
||||
# Recursively process '@'-prefixed properties that are Base objects with 'elements'.
|
||||
# This is a common pattern in older Speckle data models, such as those used for Revit commits.
|
||||
@@ -114,6 +128,4 @@ def extract_base_and_transform(
|
||||
attr_value = getattr(base, attr_name)
|
||||
# If the attribute is a Base object containing 'elements', recurse into it.
|
||||
if isinstance(attr_value, Base) and hasattr(attr_value, "elements"):
|
||||
yield from extract_base_and_transform(
|
||||
attr_value, current_id, transform_list.copy()
|
||||
)
|
||||
yield from extract_base_and_transform(attr_value, current_id, transform_list.copy())
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import Field
|
||||
from speckle_automate import AutomateBase
|
||||
|
||||
|
||||
class PropertyMatchMode(Enum):
|
||||
STRICT = "strict" # Exact parameter path match
|
||||
FUZZY = "fuzzy" # Search all parameters ignoring hierarchy
|
||||
MIXED = "mixed" # Exact match first, fuzzy fallback
|
||||
|
||||
class FunctionInputs(AutomateBase):
|
||||
"""These are function author defined values.
|
||||
|
||||
@@ -10,8 +17,23 @@ class FunctionInputs(AutomateBase):
|
||||
https://docs.pydantic.dev/latest/usage/models/
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# In this exercise, we will move rules to an external source so not to hardcode them.
|
||||
spreadsheet_url: str = Field(
|
||||
title="Spreadsheet URL",
|
||||
description="This is the URL of the spreadsheet to check. It should be a TSV format data source.",
|
||||
)
|
||||
|
||||
property_match_mode: PropertyMatchMode = Field(
|
||||
default=PropertyMatchMode.MIXED,
|
||||
title="Property Match Mode",
|
||||
description='Controls how strictly parameter names must match. ' +
|
||||
'STRICT will only match exact parameter paths, ' +
|
||||
'FUZZY will search all parameters ignoring hierarchy, ' +
|
||||
'MIXED will exact match first, fuzzy fallback.'
|
||||
)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
"""Configuration module defining mappings between spreadsheet predicates and rule methods."""
|
||||
|
||||
from src.rules import PropertyRules
|
||||
|
||||
# Mapping of input predicates to the corresponding methods in PropertyRules
|
||||
PREDICATE_METHOD_MAP = {
|
||||
"exists": PropertyRules.has_parameter.__name__,
|
||||
"matches": PropertyRules.is_parameter_value.__name__,
|
||||
"greater than": PropertyRules.is_parameter_value_greater_than.__name__,
|
||||
"less than": PropertyRules.is_parameter_value_less_than.__name__,
|
||||
"in range": PropertyRules.is_parameter_value_in_range.__name__,
|
||||
"in list": PropertyRules.is_parameter_value_in_list.__name__,
|
||||
"equal to": PropertyRules.is_equal_value.__name__,
|
||||
"is true": PropertyRules.is_parameter_value_true.__name__,
|
||||
"is false": PropertyRules.is_parameter_value_false.__name__,
|
||||
"is like": PropertyRules.is_parameter_value_like.__name__,
|
||||
"identical to": PropertyRules.is_identical_value.__name__,
|
||||
"not equal": PropertyRules.is_not_equal_value.__name__,
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
|
||||
import pandas as pd
|
||||
from pandas.core.groupby import DataFrameGroupBy
|
||||
from speckle_automate import AutomationContext, ObjectResultLevel
|
||||
from specklepy.objects.base import Base
|
||||
|
||||
from src.helpers import speckle_print
|
||||
from src.predicates import PREDICATE_METHOD_MAP
|
||||
from src.rules import PropertyRules
|
||||
|
||||
|
||||
def evaluate_condition(
|
||||
speckle_object: Base, condition: pd.Series, rule_number: str | None = None, case_number: int | None = None
|
||||
) -> bool:
|
||||
"""Given a Speckle object and a condition, evaluates the condition and returns a boolean value.
|
||||
|
||||
A condition is a pandas Series object with the following keys:
|
||||
- 'Property Name': The name of the property to evaluate.
|
||||
- 'Predicate': The predicate to use for evaluation.
|
||||
- 'Value': The value to compare against.
|
||||
|
||||
Args:
|
||||
rule_number (string): For information the rule number.
|
||||
case_number (int): For information the rule clause number.
|
||||
speckle_object (Base): The Speckle object to evaluate.
|
||||
condition (pd.Series): The condition to evaluate.
|
||||
|
||||
Returns:
|
||||
bool: The result of the evaluation. True if the condition is met, False otherwise.
|
||||
"""
|
||||
property_name = condition["Property Name"]
|
||||
predicate_key = condition["Predicate"]
|
||||
value = condition["Value"]
|
||||
|
||||
_ = rule_number
|
||||
_ = case_number
|
||||
|
||||
if predicate_key in PREDICATE_METHOD_MAP:
|
||||
method_name = PREDICATE_METHOD_MAP[predicate_key]
|
||||
method = getattr(PropertyRules, method_name, None)
|
||||
|
||||
if method:
|
||||
check_answer = method(speckle_object, property_name, value)
|
||||
|
||||
return check_answer
|
||||
return False
|
||||
|
||||
|
||||
def process_rule(
|
||||
speckle_objects: list[Base], rule_group: pd.DataFrame
|
||||
) -> tuple[list[Any], list[Any]] | tuple[list[Base], list[Base]]:
|
||||
"""Processes a set of rules against Speckle objects, returning those that pass and fail.
|
||||
|
||||
The first rule is used as a filter ('WHERE'), and subsequent rules as conditions ('AND').
|
||||
|
||||
Args:
|
||||
speckle_objects: List of Speckle objects to be processed.
|
||||
rule_group: DataFrame defining the filter and conditions.
|
||||
|
||||
Returns:
|
||||
A tuple of lists containing objects that passed and failed the rule.
|
||||
"""
|
||||
# Extract the 'WHERE' condition and subsequent 'AND' conditions
|
||||
filter_condition = rule_group.iloc[0]
|
||||
subsequent_conditions = rule_group.iloc[1:]
|
||||
|
||||
# get the last row of the rule_group and get the Message and Report Severity
|
||||
rule_info = rule_group.iloc[-1]
|
||||
rule_number = rule_info["Rule Number"]
|
||||
|
||||
# Filter objects based on the 'WHERE' condition
|
||||
filtered_objects = [
|
||||
speckle_object for speckle_object in speckle_objects if evaluate_condition(speckle_object, filter_condition)
|
||||
]
|
||||
|
||||
if not filtered_objects or len(list(filtered_objects)) == 0:
|
||||
return [], []
|
||||
|
||||
# Initialize lists for passed and failed objects
|
||||
pass_objects, fail_objects = [], []
|
||||
|
||||
# Evaluate each filtered object against the 'AND' conditions
|
||||
for speckle_object in filtered_objects:
|
||||
if all(
|
||||
evaluate_condition(
|
||||
speckle_object=speckle_object, condition=condition, rule_number=rule_number, case_number=index
|
||||
)
|
||||
for index, condition in subsequent_conditions.iterrows()
|
||||
):
|
||||
pass_objects.append(speckle_object)
|
||||
else:
|
||||
fail_objects.append(speckle_object)
|
||||
|
||||
return pass_objects, fail_objects
|
||||
|
||||
|
||||
def apply_rules_to_objects(
|
||||
speckle_objects: list[Base],
|
||||
grouped_rules: DataFrameGroupBy,
|
||||
automate_context: AutomationContext,
|
||||
) -> dict[str, tuple[list[Base], list[Base]]]:
|
||||
"""Applies defined rules to a list of objects and updates the automate context based on the results.
|
||||
|
||||
Args:
|
||||
speckle_objects (List[Base]): The list of objects to which rules are applied.
|
||||
grouped_rules (pd.DataFrameGroupBy): The DataFrame containing rule definitions.
|
||||
automate_context (Any): Context manager for attaching rule results.
|
||||
"""
|
||||
grouped_results = {}
|
||||
|
||||
rules_processed = 0
|
||||
|
||||
for rule_id, rule_group in grouped_rules:
|
||||
rule_id_str = str(rule_id) # Convert rule_id to string
|
||||
|
||||
rules_processed += 1
|
||||
|
||||
# Ensure rule_group has necessary columns
|
||||
if "Message" not in rule_group.columns or "Report Severity" not in rule_group.columns:
|
||||
continue # Or raise an exception if these columns are mandatory
|
||||
|
||||
pass_objects, fail_objects = process_rule(speckle_objects, rule_group)
|
||||
|
||||
attach_results(pass_objects, rule_group.iloc[-1], rule_id_str, automate_context, True)
|
||||
attach_results(fail_objects, rule_group.iloc[-1], rule_id_str, automate_context, False)
|
||||
|
||||
if len(pass_objects) == 0 and len(fail_objects) == 0:
|
||||
automate_context.attach_info_to_objects(
|
||||
category=f"Rule {rule_id_str} Skipped",
|
||||
object_ids=["0"], # This is a hack to get a rule to report with no valid objects
|
||||
message=f"No objects found for rule {rule_id_str}",
|
||||
metadata={},
|
||||
)
|
||||
# pass
|
||||
|
||||
grouped_results[rule_id_str] = (pass_objects, fail_objects)
|
||||
|
||||
# return pass_objects, fail_objects for each rule
|
||||
return grouped_results
|
||||
|
||||
|
||||
class SeverityLevel(Enum):
|
||||
"""Enum for severity levels."""
|
||||
|
||||
INFO = "Info"
|
||||
WARNING = "Warning"
|
||||
ERROR = "Error"
|
||||
|
||||
|
||||
def get_severity(rule_info: pd.Series) -> SeverityLevel:
|
||||
"""Convert a string severity level to the corresponding SeverityLevel enum.
|
||||
|
||||
This function normalizes input strings (because processing user entered dead is hard), handling:
|
||||
- Case insensitivity (e.g., "info", "WARNING" → "Info", "Warning")
|
||||
- Shorthand mappings (e.g., "WARN" → "Warning")
|
||||
- Stripping whitespace
|
||||
- Defaults to SeverityLevel.ERROR if the input is invalid
|
||||
"""
|
||||
severity = rule_info.get("Report Severity") # Extract severity from input data
|
||||
|
||||
# If severity is None or not a string (e.g., numeric input), default to ERROR
|
||||
if not isinstance(severity, str):
|
||||
return SeverityLevel.ERROR
|
||||
|
||||
severity = severity.strip().upper() # Remove leading/trailing spaces & normalize case
|
||||
|
||||
# Define a mapping for shorthand or alternate spellings
|
||||
alias_map = {
|
||||
"WARN": "WARNING", # Treat "WARN" as "WARNING"
|
||||
}
|
||||
|
||||
# Replace shorthand values if applicable
|
||||
severity = alias_map.get(severity, severity)
|
||||
|
||||
# Attempt to match with an existing SeverityLevel enum value (case-insensitive)
|
||||
return next(
|
||||
(level for level in SeverityLevel if level.value.upper() == severity),
|
||||
SeverityLevel.ERROR, # Default to ERROR if no match is found
|
||||
)
|
||||
|
||||
|
||||
def get_metadata(
|
||||
rule_id: str, rule_info: pd.Series, passed: bool, speckle_objects: list[Base]
|
||||
) -> dict[str, str | int | Any]:
|
||||
"""Function that generates metadata with severity validation."""
|
||||
metadata = {
|
||||
"rule_id": rule_id,
|
||||
"status": "PASS" if passed else "FAIL",
|
||||
"severity": get_severity(rule_info).value, # Keep proper casing
|
||||
"rule_message": rule_info["Message"],
|
||||
"object_count": len(speckle_objects),
|
||||
}
|
||||
return metadata
|
||||
|
||||
|
||||
def attach_results(
|
||||
speckle_objects: list[Base],
|
||||
rule_info: pd.Series,
|
||||
rule_id: str,
|
||||
context: AutomationContext,
|
||||
passed: bool,
|
||||
) -> None:
|
||||
"""Attaches the results of a rule to the objects in the context.
|
||||
|
||||
Args:
|
||||
speckle_objects (List[Base]): The list of objects to which the rule was applied.
|
||||
rule_info (pd.Series): The information about the rule.
|
||||
rule_id (str): The ID of the rule.
|
||||
context (AutomationContext): The context manager for attaching results.
|
||||
passed (bool): Whether the rule passed or failed.
|
||||
"""
|
||||
if not speckle_objects:
|
||||
return
|
||||
|
||||
# Create structured metadata for onward data analysis uses
|
||||
|
||||
metadata = get_metadata(rule_id, rule_info, passed, speckle_objects)
|
||||
|
||||
message = f"{rule_info['Message']}"
|
||||
|
||||
if not passed:
|
||||
speckle_print(rule_info["Report Severity"])
|
||||
|
||||
severity = (
|
||||
ObjectResultLevel.WARNING
|
||||
if rule_info["Report Severity"].capitalize() in ["Warning", "Warn"]
|
||||
else ObjectResultLevel.ERROR
|
||||
)
|
||||
context.attach_result_to_objects(
|
||||
category=f"Rule {rule_id}",
|
||||
object_ids=[speckle_object.id for speckle_object in speckle_objects],
|
||||
message=message,
|
||||
level=severity,
|
||||
metadata=metadata,
|
||||
)
|
||||
else:
|
||||
context.attach_info_to_objects(
|
||||
category=f"Rule {rule_id}",
|
||||
object_ids=[speckle_object.id for speckle_object in speckle_objects],
|
||||
message=message,
|
||||
metadata=metadata,
|
||||
)
|
||||
+359
-583
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,756 @@
|
||||
# import re
|
||||
# from typing import Any
|
||||
#
|
||||
# from Levenshtein import ratio
|
||||
# from specklepy.objects.base import Base
|
||||
#
|
||||
# from src.helpers import get_item, has_item, speckle_print
|
||||
# from src.inputs import PropertyMatchMode
|
||||
|
||||
# We're going to define a set of rules that will allow us to filter and
|
||||
# process parameters in our Speckle objects. These rules will be encapsulated
|
||||
# in a class called `ParameterRules`.
|
||||
|
||||
|
||||
# class Rules:
|
||||
# """A collection of rules for processing properties in Speckle objects.
|
||||
#
|
||||
# Simple rules can be straightforwardly implemented as static methods that
|
||||
# return boolean value to be used either as a filter or a condition.
|
||||
# These can then be abstracted into returning lambda functions that we can
|
||||
# use in our main processing logic. By encapsulating these rules, we can easily
|
||||
# extend or modify them in the future.
|
||||
# """
|
||||
#
|
||||
# @staticmethod
|
||||
# def try_get_display_value(
|
||||
# speckle_object: Base,
|
||||
# ) -> list[Base] | None:
|
||||
# """Try fetching the display value from a Speckle object.
|
||||
#
|
||||
# This method encapsulates the logic for attempting to retrieve the display value from a
|
||||
# Speckle object. It returns a list containing the display values if found,
|
||||
# otherwise it returns None.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to extract the display value from.
|
||||
#
|
||||
# Returns:
|
||||
# Optional[List[Base]]: A list containing the display values.
|
||||
# If no display value is found, returns None.
|
||||
# """
|
||||
# # Attempt to get the display value from the speckle_object
|
||||
# raw_display_value = getattr(speckle_object, "displayValue", None) or getattr(
|
||||
# speckle_object, "@displayValue", None
|
||||
# )
|
||||
#
|
||||
# # If no display value found, return None
|
||||
# if raw_display_value is None:
|
||||
# return None
|
||||
#
|
||||
# # If display value found, filter out non-Base objects
|
||||
# display_values = [value for value in raw_display_value if isinstance(value, Base)]
|
||||
#
|
||||
# # If no valid display values found, return None
|
||||
# if not display_values:
|
||||
# return None
|
||||
#
|
||||
# return display_values
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_displayable_object(speckle_object: Base) -> bool:
|
||||
# """Determines if a given Speckle object is displayable.
|
||||
#
|
||||
# This method encapsulates the logic for determining if a Speckle object is displayable.
|
||||
# It checks if the speckle_object has a display value and returns True if it does, otherwise it returns False.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to check.
|
||||
#
|
||||
# Returns:
|
||||
# bool: True if the object has a display value, False otherwise.
|
||||
# """
|
||||
# # Check for direct displayable state using try_get_display_value
|
||||
# display_values = Rules.try_get_display_value(speckle_object)
|
||||
# if display_values and getattr(speckle_object, "id", None) is not None:
|
||||
# return True
|
||||
#
|
||||
# # Check for displayable state via definition, using try_get_display_value on the definition object
|
||||
# definition = getattr(speckle_object, "definition", None)
|
||||
# if definition:
|
||||
# definition_display_values = Rules.try_get_display_value(definition)
|
||||
# if definition_display_values and getattr(definition, "id", None) is not None:
|
||||
# return True
|
||||
#
|
||||
# return False
|
||||
#
|
||||
# @staticmethod
|
||||
# def get_displayable_objects(flat_list_of_objects: list[Base]) -> list[Base]:
|
||||
# """Filters a list of Speckle objects to only include displayable objects.
|
||||
#
|
||||
# This function takes a list of Speckle objects and filters out the objects that are displayable.
|
||||
# It returns a list containing only the displayable objects.
|
||||
#
|
||||
# Args:
|
||||
# flat_list_of_objects (List[Base]): The list of Speckle objects to filter.
|
||||
# """
|
||||
# return [
|
||||
# speckle_object
|
||||
# for speckle_object in flat_list_of_objects
|
||||
# if Rules.is_displayable_object(speckle_object) and getattr(speckle_object, "id", None)
|
||||
# ]
|
||||
#
|
||||
#
|
||||
# class PropertyRules:
|
||||
# """A collection of rules for processing Revit parameters in Speckle objects."""
|
||||
#
|
||||
# @staticmethod
|
||||
# def has_parameter(speckle_object: Base, parameter_name: str, *_args, **_kwargs) -> bool:
|
||||
# """Checks if the speckle_object has a parameter with the given name."""
|
||||
# found, _ = ParameterSearch.lookup_parameter(speckle_object, parameter_name)
|
||||
# return found
|
||||
#
|
||||
# @staticmethod
|
||||
# def get_parameter_value(
|
||||
# speckle_object: Base,
|
||||
# parameter_name: str,
|
||||
# match_mode: PropertyMatchMode = PropertyMatchMode.MIXED,
|
||||
# default_value: Any = None,
|
||||
# ) -> Any:
|
||||
# """Gets the value of a parameter if it exists."""
|
||||
# found, value = ParameterSearch.lookup_parameter(speckle_object, parameter_name, match_mode)
|
||||
# return value if found else default_value
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_v3(speckle_object: Base) -> bool:
|
||||
# """Determines if a Speckle object uses v3 parameter structure.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to check
|
||||
#
|
||||
# Returns:
|
||||
# bool: True if object uses v3 structure, False otherwise
|
||||
# """
|
||||
# properties = get_item(speckle_object, "properties")
|
||||
# return bool(properties and has_item(properties, "Parameters"))
|
||||
#
|
||||
# # @staticmethod
|
||||
# # def has_parameter(speckle_object: Base, parameter_name: str, *_args, **_kwargs) -> bool:
|
||||
# # """Checks if the speckle_object has a Revit parameter with the given name.
|
||||
# #
|
||||
# # First checks direct properties, then determines if it's a v2 or v3 object structure
|
||||
# # and searches in the appropriate parameter hierarchy.
|
||||
# #
|
||||
# # Args:
|
||||
# # speckle_object (Base): The Speckle object to check.
|
||||
# # parameter_name (str): The name of the parameter to check for.
|
||||
# # *_args: Extra positional arguments which are ignored.
|
||||
# # **_kwargs: Extra keyword arguments which are ignored.
|
||||
# #
|
||||
# # Returns:
|
||||
# # bool: True if the object has the parameter, False otherwise.
|
||||
# # """
|
||||
# # # Check direct property first regardless of version
|
||||
# # if has_item(speckle_object, parameter_name):
|
||||
# # return True
|
||||
# #
|
||||
# # if PropertyRules.is_v3(speckle_object):
|
||||
# # properties = get_item(speckle_object, "properties")
|
||||
# # parameters = get_item(properties, "Parameters")
|
||||
# # if parameters:
|
||||
# #
|
||||
# # def search_v3_params(params: dict, search_name: str) -> bool:
|
||||
# # for key, value in params.items():
|
||||
# # if isinstance(value, dict):
|
||||
# # # Check direct name match
|
||||
# # if key.lower() == search_name.lower():
|
||||
# # return True
|
||||
# # # Check nested parameters
|
||||
# # if search_v3_params(value, search_name):
|
||||
# # return True
|
||||
# # return False
|
||||
# #
|
||||
# # return search_v3_params(parameters, parameter_name)
|
||||
# # else:
|
||||
# # # Handle v2 structure
|
||||
# # parameters = get_item(speckle_object, "parameters")
|
||||
# # if not parameters:
|
||||
# # return False
|
||||
# #
|
||||
# # # Check direct parameter name match
|
||||
# # if has_item(parameters, parameter_name):
|
||||
# # return True
|
||||
# #
|
||||
# # # Check nested parameters with name property
|
||||
# # def check_nested_name(value: Any) -> bool:
|
||||
# # if isinstance(value, dict):
|
||||
# # return get_item(value, "name") == parameter_name
|
||||
# # return get_item(value, "name") == parameter_name if hasattr(value, "name") else False
|
||||
# #
|
||||
# # return any(check_nested_name(param_value) for param_value in parameters.values() if param_value is not None)
|
||||
# #
|
||||
# # return False
|
||||
# #
|
||||
# # @staticmethod
|
||||
# # def get_parameter_value(
|
||||
# # speckle_object: Base,
|
||||
# # parameter_name: str,
|
||||
# # match_mode: PropertyMatchMode = PropertyMatchMode.MIXED,
|
||||
# # default_value: Any = None,
|
||||
# # ) -> Any | None:
|
||||
# # """Retrieves the value of the specified parameter from the speckle_object.
|
||||
# #
|
||||
# # First checks direct properties, then determines if it's a v2 or v3 object structure
|
||||
# # and retrieves from the appropriate parameter hierarchy.
|
||||
# #
|
||||
# # Args:
|
||||
# # speckle_object (Base): The Speckle object to retrieve the parameter value from.
|
||||
# # parameter_name (str): The name of the parameter to retrieve the value for.
|
||||
# # match_mode (PropertyMatchMode): The matching mode to use for parameter lookup
|
||||
# # default_value: The default value to return if parameter not found.
|
||||
# #
|
||||
# # Returns:
|
||||
# # The value of the parameter if found, else default_value.
|
||||
# # """
|
||||
# # # Check direct property first regardless of version
|
||||
# # if has_item(speckle_object, parameter_name):
|
||||
# # value = get_item(speckle_object, parameter_name)
|
||||
# # return value if value is not None else default_value
|
||||
# #
|
||||
# # if PropertyRules.is_v3(speckle_object):
|
||||
# # return PropertyRules.get_v3_parameter(speckle_object, parameter_name, match_mode, default_value)
|
||||
# # else:
|
||||
# # return PropertyRules.get_v2_parameter(speckle_object, parameter_name, match_mode, default_value)
|
||||
#
|
||||
# # @staticmethod
|
||||
# # def get_v2_parameter(obj: Base, name: str, mode: PropertyMatchMode, default: Any) -> Any:
|
||||
# # """Get parameter value from v2 Speckle object structure.
|
||||
# #
|
||||
# # Args:
|
||||
# # obj: Speckle object to get parameter from
|
||||
# # name: Parameter name to retrieve
|
||||
# # mode: Match mode for parameter lookup
|
||||
# # default: Default value if parameter not found
|
||||
# #
|
||||
# # Returns:
|
||||
# # Parameter value if found, else default
|
||||
# # """
|
||||
# # parameters = get_item(obj, "parameters")
|
||||
# # if not parameters:
|
||||
# # return default
|
||||
# #
|
||||
# # if mode == PropertyMatchMode.STRICT:
|
||||
# # return PropertyRules.strict_parameter_lookup(name, parameters, default)
|
||||
# #
|
||||
# # def search_params(param_dict: dict, search_name: str, fuzzy: bool) -> Any:
|
||||
# # for key, value in param_dict.items():
|
||||
# # key_match = (key.lower() == search_name.lower()) or (fuzzy and search_name.lower() in key.lower())
|
||||
# # if key_match:
|
||||
# # # Handle both direct values and nested parameter objects
|
||||
# # return get_item(value, "value", value)
|
||||
# # return None
|
||||
# #
|
||||
# # result = search_params(parameters, name, mode == PropertyMatchMode.FUZZY)
|
||||
# # return result if result is not None else default
|
||||
# #
|
||||
# # @staticmethod
|
||||
# # def get_v3_parameter(obj: Base, name: str, mode: PropertyMatchMode, default: Any) -> Any:
|
||||
# # """Get parameter value from v3 Speckle object structure.
|
||||
# #
|
||||
# # Args:
|
||||
# # obj: Speckle object to get parameter from
|
||||
# # name: Parameter name to retrieve
|
||||
# # mode: Match mode for parameter lookup
|
||||
# # default: Default value if parameter not found
|
||||
# #
|
||||
# # Returns:
|
||||
# # Parameter value if found, else default
|
||||
# # """
|
||||
# # properties = get_item(obj, "properties")
|
||||
# # if not properties or not has_item(properties, "Parameters"):
|
||||
# # return default
|
||||
# #
|
||||
# # parameters = get_item(properties, "Parameters")
|
||||
# # if not parameters:
|
||||
# # return default
|
||||
# #
|
||||
# # if mode == PropertyMatchMode.STRICT:
|
||||
# # return PropertyRules.strict_parameter_lookup(name, parameters, default)
|
||||
# #
|
||||
# # def search_nested(data: dict, search_name: str, fuzzy: bool) -> Any:
|
||||
# # for nested_key, value in data.items():
|
||||
# # if isinstance(value, dict):
|
||||
# # key_match = (nested_key.lower() == search_name.lower()) or (
|
||||
# # fuzzy and search_name.lower() in nested_key.lower()
|
||||
# # )
|
||||
# #
|
||||
# # if key_match and has_item(value, "value"):
|
||||
# # return get_item(value, "value")
|
||||
# #
|
||||
# # nested_result = search_nested(value, search_name, fuzzy)
|
||||
# # if nested_result is not None:
|
||||
# # return nested_result
|
||||
# # return None
|
||||
# #
|
||||
# # result = search_nested(parameters, name, mode == PropertyMatchMode.FUZZY)
|
||||
# # return result if result is not None else default
|
||||
# #
|
||||
# # @staticmethod
|
||||
# # def strict_parameter_lookup(name: str, parameters: dict, default: Any) -> Any:
|
||||
# # """Perform strict parameter lookup following exact path.
|
||||
# #
|
||||
# # Args:
|
||||
# # name: Parameter path (dot separated)
|
||||
# # parameters: Parameters dictionary
|
||||
# # default: Default value if not found
|
||||
# #
|
||||
# # Returns:
|
||||
# # Parameter value if found, else default
|
||||
# # """
|
||||
# # path_parts = name.split(".")
|
||||
# # current = parameters
|
||||
# #
|
||||
# # for part in path_parts:
|
||||
# # if not current or not isinstance(current, dict):
|
||||
# # return default
|
||||
# #
|
||||
# # # Find exact case-insensitive match
|
||||
# # key = next((k for k in current.keys() if k.lower() == part.lower()), None)
|
||||
# # if not key:
|
||||
# # return default
|
||||
# #
|
||||
# # current = get_item(current, key)
|
||||
# #
|
||||
# # # Handle both direct values and parameter objects
|
||||
# # if isinstance(current, dict):
|
||||
# # return get_item(current, "value", current)
|
||||
# # return current
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_parameter_value(speckle_object: Base, parameter_name: str, value_to_match: Any) -> bool:
|
||||
# """Checks if the value of the specified parameter matches the given value.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to check.
|
||||
# parameter_name (str): The name of the parameter to check.
|
||||
# value_to_match (Any): The value to match against.
|
||||
#
|
||||
# Returns:
|
||||
# bool: True if the parameter value matches the given value, False otherwise.
|
||||
# """
|
||||
# parameter_value = PropertyRules.get_parameter_value(speckle_object, parameter_name)
|
||||
# return parameter_value == value_to_match
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_parameter_value_like(
|
||||
# speckle_object: Base,
|
||||
# parameter_name: str,
|
||||
# pattern: str,
|
||||
# fuzzy: bool = False,
|
||||
# threshold: float = 0.8,
|
||||
# ) -> bool:
|
||||
# """Checks if the value of the specified parameter matches the given pattern.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to check.
|
||||
# parameter_name (str): The name of the parameter to check.
|
||||
# pattern (str): The pattern to match against.
|
||||
# fuzzy (bool): If True, performs fuzzy matching using Levenshtein distance.
|
||||
# If False (default), performs exact pattern matching using regular expressions.
|
||||
# threshold (float): The similarity threshold for fuzzy matching (default: 0.8).
|
||||
# Only applicable when fuzzy=True.
|
||||
#
|
||||
# Returns:
|
||||
# bool: True if the parameter value matches the pattern (exact or fuzzy), False otherwise.
|
||||
# """
|
||||
# parameter_value = PropertyRules.get_parameter_value(speckle_object, parameter_name)
|
||||
# if parameter_value is None:
|
||||
# return False
|
||||
#
|
||||
# if fuzzy:
|
||||
# similarity = ratio(str(parameter_value), pattern)
|
||||
# return similarity >= threshold
|
||||
# else:
|
||||
# return bool(re.match(pattern, str(parameter_value)))
|
||||
#
|
||||
# @staticmethod
|
||||
# def parse_number_from_string(input_string: str):
|
||||
# """Attempts to parse an integer or float from a given string.
|
||||
#
|
||||
# Args:
|
||||
# input_string (str): The string containing the number to be parsed.
|
||||
#
|
||||
# Returns:
|
||||
# int or float: The parsed number, or raises ValueError if parsing is not possible.
|
||||
# """
|
||||
# try:
|
||||
# # First try to convert it to an integer
|
||||
# return int(input_string)
|
||||
# except ValueError:
|
||||
# # If it fails to convert to an integer, try to convert to a float
|
||||
# try:
|
||||
# return float(input_string)
|
||||
# except ValueError:
|
||||
# # Raise an error if neither conversion is possible
|
||||
# raise ValueError("Input string is not a valid integer or float")
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_parameter_value_greater_than(speckle_object: Base, parameter_name: str, threshold: str) -> bool:
|
||||
# """Checks if the value of the specified parameter is greater than the given threshold.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to check.
|
||||
# parameter_name (str): The name of the parameter to check.
|
||||
# threshold (Union[int, float]): The threshold value to compare against.
|
||||
#
|
||||
# Returns:
|
||||
# bool: True if the parameter value is greater than the threshold, False otherwise.
|
||||
# """
|
||||
# parameter_value = PropertyRules.get_parameter_value(speckle_object, parameter_name)
|
||||
# if parameter_value is None:
|
||||
# return False
|
||||
#
|
||||
# if not isinstance(parameter_value, int | float):
|
||||
# raise ValueError(f"Parameter value must be a number, got {type(parameter_value)}")
|
||||
# return parameter_value > PropertyRules.parse_number_from_string(threshold)
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_parameter_value_less_than(speckle_object: Base, parameter_name: str, threshold: str) -> bool:
|
||||
# """Checks if the value of the specified parameter is less than the given threshold.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to check.
|
||||
# parameter_name (str): The name of the parameter to check.
|
||||
# threshold (Union[int, float]): The threshold value to compare against.
|
||||
#
|
||||
# Returns:
|
||||
# bool: True if the parameter value is less than the threshold, False otherwise.
|
||||
# """
|
||||
# parameter_value = PropertyRules.get_parameter_value(speckle_object, parameter_name)
|
||||
# if parameter_value is None:
|
||||
# return False
|
||||
# if not isinstance(parameter_value, int | float):
|
||||
# raise ValueError(f"Parameter value must be a number, got {type(parameter_value)}")
|
||||
# return parameter_value < PropertyRules.parse_number_from_string(threshold)
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_parameter_value_in_range(speckle_object: Base, parameter_name: str, value_range: str) -> bool:
|
||||
# """Checks if the value of the specified parameter falls within the given range.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to check.
|
||||
# parameter_name (str): The name of the parameter to check.
|
||||
# value_range (str): The range to check against, in the format "min_value, max_value".
|
||||
#
|
||||
# Returns:
|
||||
# bool: True if the parameter value falls within the range (inclusive), False otherwise.
|
||||
# """
|
||||
# min_value, max_value = value_range.split(",")
|
||||
# min_value = PropertyRules.parse_number_from_string(min_value)
|
||||
# max_value = PropertyRules.parse_number_from_string(max_value)
|
||||
#
|
||||
# parameter_value = PropertyRules.get_parameter_value(speckle_object, parameter_name)
|
||||
# if parameter_value is None:
|
||||
# return False
|
||||
# if not isinstance(parameter_value, int | float):
|
||||
# raise ValueError(f"Parameter value must be a number, got {type(parameter_value)}")
|
||||
#
|
||||
# return min_value <= parameter_value <= max_value
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_parameter_value_in_range_expanded(
|
||||
# speckle_object: Base,
|
||||
# parameter_name: str,
|
||||
# min_value: int | float,
|
||||
# max_value: int | float,
|
||||
# inclusive: bool = True,
|
||||
# ) -> bool:
|
||||
# """Checks if the value of the specified parameter falls within the given range.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to check.
|
||||
# parameter_name (str): The name of the parameter to check.
|
||||
# min_value (Union[int, float]): The minimum value of the range.
|
||||
# max_value (Union[int, float]): The maximum value of the range.
|
||||
# inclusive (bool): If True (default), the range is inclusive (min <= value <= max).
|
||||
# If False, the range is exclusive (min < value < max).
|
||||
#
|
||||
# Returns:
|
||||
# bool: True if the parameter value falls within the range (inclusive), False otherwise.
|
||||
# """
|
||||
# parameter_value = PropertyRules.get_parameter_value(speckle_object, parameter_name)
|
||||
# if parameter_value is None:
|
||||
# return False
|
||||
# if not isinstance(parameter_value, int | float):
|
||||
# raise ValueError(f"Parameter value must be a number, got {type(parameter_value)}")
|
||||
#
|
||||
# return min_value <= parameter_value <= max_value if inclusive else min_value < parameter_value < max_value
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_parameter_value_in_list(speckle_object: Base, parameter_name: str, value_list: list[Any] | str) -> bool:
|
||||
# """Checks if the value of the specified parameter is present in the given list of values.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to check.
|
||||
# parameter_name (str): The name of the parameter to check.
|
||||
# value_list (List[Any]): The list of values to check against.
|
||||
#
|
||||
# Returns:
|
||||
# bool: True if the parameter value is found in the list, False otherwise.
|
||||
# """
|
||||
# parameter_value = PropertyRules.get_parameter_value(speckle_object, parameter_name)
|
||||
#
|
||||
# if isinstance(value_list, str):
|
||||
# value_list = [value.strip() for value in value_list.split(",")]
|
||||
#
|
||||
# # parameter_value is effectively Any type, so to find its value in the value_list
|
||||
# def is_value_in_list(value: Any, my_list: Any) -> bool:
|
||||
# # Ensure that my_list is actually a list
|
||||
# if isinstance(my_list, list):
|
||||
# return value in my_list or str(value) in my_list
|
||||
# else:
|
||||
# speckle_print(f"Expected a list, got {type(my_list)} instead.")
|
||||
# return False
|
||||
#
|
||||
# return is_value_in_list(parameter_value, value_list)
|
||||
#
|
||||
# @staticmethod
|
||||
# def _check_boolean_value(value: Any, values_to_match: tuple[str, ...]) -> bool:
|
||||
# """Check if a value matches any target value in expected format."""
|
||||
# if isinstance(value, bool):
|
||||
# return value is (True if "true" in values_to_match else False)
|
||||
#
|
||||
# if isinstance(value, str):
|
||||
# return value.lower() in values_to_match
|
||||
#
|
||||
# return False
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_parameter_value_true(speckle_object: Base, parameter_name: str) -> bool:
|
||||
# """Check if parameter value represents true (boolean True, 'yes', 'true', '1')."""
|
||||
# parameter_value = PropertyRules.get_parameter_value(speckle_object, parameter_name)
|
||||
# return PropertyRules._check_boolean_value(parameter_value, ("yes", "true", "1"))
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_parameter_value_false(speckle_object: Base, parameter_name: str) -> bool:
|
||||
# """Check if parameter value represents false (boolean False, 'no', 'false', '0')."""
|
||||
# parameter_value = PropertyRules.get_parameter_value(speckle_object, parameter_name)
|
||||
# return PropertyRules._check_boolean_value(parameter_value, ("no", "false", "0"))
|
||||
#
|
||||
# @staticmethod
|
||||
# def has_category(speckle_object: Base) -> bool:
|
||||
# """Checks if the speckle_object has a 'category' parameter.
|
||||
#
|
||||
# This method checks if the speckle_object has a 'category' parameter.
|
||||
# If the 'category' parameter exists, it returns True; otherwise, it returns False.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to check.
|
||||
#
|
||||
# Returns:
|
||||
# bool: True if the object has the 'category' parameter, False otherwise.
|
||||
# """
|
||||
# return PropertyRules.has_parameter(speckle_object, "category")
|
||||
#
|
||||
# @staticmethod
|
||||
# def is_category(speckle_object: Base, category_input: str) -> bool:
|
||||
# """Checks if the value of the 'category' property matches the given input.
|
||||
#
|
||||
# This method checks if the 'category' property of the speckle_object
|
||||
# matches the given category_input. If they match, it returns True;
|
||||
# otherwise, it returns False.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to check.
|
||||
# category_input (str): The category value to compare against.
|
||||
#
|
||||
# Returns:
|
||||
# bool: True if the 'category' property matches the input, False otherwise.
|
||||
# """
|
||||
# category_value = PropertyRules.get_parameter_value(speckle_object, "category")
|
||||
# return category_value == category_input
|
||||
#
|
||||
# @staticmethod
|
||||
# def get_category_value(speckle_object: Base) -> str:
|
||||
# """Retrieves the value of the 'category' parameter from the speckle_object.
|
||||
#
|
||||
# This method retrieves the value of the 'category' parameter from the speckle_object.
|
||||
# If the 'category' parameter exists and its value is not None, it returns the value.
|
||||
# If the 'category' parameter does not exist or its value is None, it returns an empty string.
|
||||
#
|
||||
# Args:
|
||||
# speckle_object (Base): The Speckle object to retrieve the 'category' parameter value from.
|
||||
#
|
||||
# Returns:
|
||||
# str: The value of the 'category' parameter if it exists and is not None, or an empty string otherwise.
|
||||
# """
|
||||
# return PropertyRules.get_parameter_value(speckle_object, "category")
|
||||
#
|
||||
#
|
||||
# class ParameterSearch:
|
||||
# """Unified parameter search functionality for Speckle objects."""
|
||||
#
|
||||
# @staticmethod
|
||||
# def convert_revit_boolean(value: Any) -> Any:
|
||||
# """Convert Revit-style Yes/No strings to boolean values.
|
||||
#
|
||||
# Args:
|
||||
# value: The value to potentially convert
|
||||
#
|
||||
# Returns:
|
||||
# bool if value is a Revit boolean string, original value otherwise
|
||||
# """
|
||||
# if isinstance(value, str):
|
||||
# if value.lower() == "yes":
|
||||
# return True
|
||||
# if value.lower() == "no":
|
||||
# return False
|
||||
# return value
|
||||
#
|
||||
# @staticmethod
|
||||
# def search_parameters(
|
||||
# params: dict, search_name: str, mode: PropertyMatchMode = PropertyMatchMode.STRICT
|
||||
# ) -> tuple[bool, Any]:
|
||||
# """Search for parameters using consistent matching logic.
|
||||
#
|
||||
# Supports flexible property chain matching that can find paths like "Instance Parameters.Dimensions.Length"
|
||||
# within longer chains like "properties.Parameters.Instance Parameters.Dimensions.Length.value".
|
||||
# Uses STRICT matching by default for more predictable results.
|
||||
#
|
||||
# Args:
|
||||
# params: Parameter dictionary to search
|
||||
# search_name: Name of parameter to find, can be dot-separated chain
|
||||
# mode: Matching mode to use (STRICT by default, or FUZZY/MIXED for looser matching)
|
||||
#
|
||||
# Returns:
|
||||
# Tuple of (value_found: bool, value: Any)
|
||||
# """
|
||||
#
|
||||
# def matches_name(match_key: str, target: str, match_mode: PropertyMatchMode) -> bool:
|
||||
# if match_mode == PropertyMatchMode.STRICT:
|
||||
# return match_key.lower() == target.lower()
|
||||
# elif match_mode == PropertyMatchMode.FUZZY:
|
||||
# return target.lower() in match_key.lower()
|
||||
# else: # MIXED mode
|
||||
# return match_key.lower() == target.lower() or target.lower() in match_key.lower()
|
||||
#
|
||||
# def try_get_value(obj: Any) -> Any:
|
||||
# """Extract value from parameter object or return as is.
|
||||
#
|
||||
# Handles both dict and Base objects, checking for 'value' property in both cases.
|
||||
# Returns the 'value' if found, otherwise returns the original object.
|
||||
# """
|
||||
# # Handle dictionary objects
|
||||
# if isinstance(obj, dict):
|
||||
# return obj.get("value", obj)
|
||||
#
|
||||
# # Handle Base objects
|
||||
# if isinstance(obj, Base):
|
||||
# return getattr(obj, "value", obj)
|
||||
#
|
||||
# # For all other types, return as is
|
||||
# return obj
|
||||
#
|
||||
# # First try property chain lookup
|
||||
# if "." in search_name:
|
||||
# search_parts = search_name.split(".")
|
||||
#
|
||||
# def try_match_path(current: dict, remaining_search_parts: list[str], depth: int = 0) -> tuple[bool, Any]:
|
||||
# if not isinstance(current, dict):
|
||||
# return False, None
|
||||
#
|
||||
# if not remaining_search_parts: # We've matched all parts
|
||||
# return True, try_get_value(current)
|
||||
#
|
||||
# current_search = remaining_search_parts[0]
|
||||
#
|
||||
# # Try each key at current level
|
||||
# for key, item_value in current.items():
|
||||
# if matches_name(key, current_search, mode):
|
||||
# # Found a match for current part, recurse with rest
|
||||
# match_found, result = try_match_path(item_value, remaining_search_parts[1:], depth + 1)
|
||||
# if match_found:
|
||||
# return True, result
|
||||
#
|
||||
# # If no match found and value is a dict, try searching deeper
|
||||
# if isinstance(item_value, dict):
|
||||
# match_found, result = try_match_path(item_value, remaining_search_parts, depth)
|
||||
# if match_found:
|
||||
# return True, result
|
||||
#
|
||||
# return False, None
|
||||
#
|
||||
# try:
|
||||
# found, value = try_match_path(params, search_parts)
|
||||
# if found:
|
||||
# return True, value
|
||||
# except Exception:
|
||||
# pass # Fall through to recursive search if chain lookup fails
|
||||
#
|
||||
# # Recursive search through nested dictionaries
|
||||
# def recursive_search(data: dict | Base, target: str) -> tuple[bool, Any]:
|
||||
# if not isinstance(data, dict | Base):
|
||||
# return False, None
|
||||
#
|
||||
# # Handle both dict and Base objects for iteration
|
||||
# if isinstance(data, dict):
|
||||
# items = data.items()
|
||||
# else:
|
||||
# items = [(k, getattr(data, k)) for k in dir(data) if not k.startswith("_")]
|
||||
#
|
||||
# # First check current level
|
||||
# for key, item_value in items:
|
||||
# if matches_name(key, target, mode):
|
||||
# return True, try_get_value(item_value)
|
||||
#
|
||||
# # Then check nested levels
|
||||
# for _, item_value in items:
|
||||
# if isinstance(item_value, dict | Base):
|
||||
# item_found, result = recursive_search(item_value, target)
|
||||
# if item_found:
|
||||
# return True, result
|
||||
#
|
||||
# return False, None
|
||||
#
|
||||
# return recursive_search(params, search_name.split(".")[-1] if "." in search_name else search_name)
|
||||
#
|
||||
# @staticmethod
|
||||
# def lookup_parameter(
|
||||
# obj: Base, param_name: str, mode: PropertyMatchMode = PropertyMatchMode.MIXED
|
||||
# ) -> tuple[bool, Any]:
|
||||
# """Unified parameter lookup for both checking existence and getting values.
|
||||
#
|
||||
# Args:
|
||||
# obj: Speckle object to search
|
||||
# param_name: Parameter name to find
|
||||
# mode: Matching mode to use
|
||||
#
|
||||
# Returns:
|
||||
# Tuple of (found: bool, value: Any)
|
||||
# """
|
||||
# # Check direct property first
|
||||
# if has_item(obj, param_name):
|
||||
# value = get_item(obj, param_name)
|
||||
# # Check if the direct property has a value field
|
||||
# if isinstance(value, dict) and "value" in value:
|
||||
# return True, value["value"]
|
||||
# return True, value
|
||||
#
|
||||
# # Handle v3 structure
|
||||
# if PropertyRules.is_v3(obj):
|
||||
# properties = get_item(obj, "properties")
|
||||
# if not properties or not has_item(properties, "Parameters"):
|
||||
# return False, None
|
||||
#
|
||||
# parameters = get_item(properties, "Parameters")
|
||||
# if not parameters:
|
||||
# return False, None
|
||||
#
|
||||
# return ParameterSearch.search_parameters(parameters, param_name, mode)
|
||||
#
|
||||
# # Handle v2 structure
|
||||
# parameters = get_item(obj, "parameters")
|
||||
# if not parameters:
|
||||
# return False, None
|
||||
#
|
||||
# return ParameterSearch.search_parameters(parameters, param_name, mode)
|
||||
+22
-2
@@ -1,7 +1,8 @@
|
||||
import pandas as pd
|
||||
from pandas import DataFrame
|
||||
|
||||
|
||||
def read_rules_from_spreadsheet(url):
|
||||
def read_rules_from_spreadsheet(url: str) -> DataFrame | None:
|
||||
"""Reads a TSV file from a provided URL and returns a DataFrame.
|
||||
|
||||
Args:
|
||||
@@ -12,7 +13,26 @@ def read_rules_from_spreadsheet(url):
|
||||
"""
|
||||
try:
|
||||
# Since the output is a TSV, we use `pd.read_csv` with `sep='\t'` to specify tab-separated values.
|
||||
return pd.read_csv(url, sep="\t")
|
||||
df = pd.read_csv(url, sep="\t")
|
||||
df = convert_mixed_columns(df)
|
||||
|
||||
# Convert columns to appropriate types based on their content.
|
||||
return df
|
||||
|
||||
except Exception as e:
|
||||
print(f"Failed to read the TSV from the URL: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def convert_mixed_columns(df):
|
||||
"""Converts columns in a DataFrame to appropriate types based on their content.
|
||||
|
||||
Args:
|
||||
df (DataFrame): The DataFrame whose columns are to be converted.
|
||||
|
||||
Returns:
|
||||
DataFrame: The DataFrame with columns converted to appropriate types.
|
||||
"""
|
||||
df = df.apply(lambda c: c.astype(object) if any(str(x).replace(".", "", 1).isdigit() for x in c) else c.astype(str))
|
||||
|
||||
return df
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,696 @@
|
||||
[
|
||||
{
|
||||
"id": "46f06fef727d64a0bbcbd7ced51e0cd2",
|
||||
"name": "Walls - W30(Fc24)",
|
||||
"type": "W30(Fc24)",
|
||||
"level": {
|
||||
"name": "1FL",
|
||||
"units": "mm",
|
||||
"elevation": 0
|
||||
},
|
||||
"units": "mm",
|
||||
"family": "Basic Wall",
|
||||
"flipped": false,
|
||||
"category": "Walls",
|
||||
"elements": [],
|
||||
"location": {
|
||||
"id": "9c76b8de34382c9052965ee463f8374b",
|
||||
"end": {
|
||||
"x": 22400.000000000015,
|
||||
"y": 20500,
|
||||
"z": 0,
|
||||
"id": "3455575bfd8939f264d295b61e74156f",
|
||||
"units": "mm",
|
||||
"speckle_type": "Objects.Geometry.Point",
|
||||
"applicationId": null
|
||||
},
|
||||
"bbox": null,
|
||||
"start": {
|
||||
"x": 22400.000000000007,
|
||||
"y": 15199.999999999998,
|
||||
"z": 0,
|
||||
"id": "d0c4fdb2e11cc825e7f05f9dc88a0be1",
|
||||
"units": "mm",
|
||||
"speckle_type": "Objects.Geometry.Point",
|
||||
"applicationId": null
|
||||
},
|
||||
"units": "mm",
|
||||
"domain": {
|
||||
"id": "3b97feaad2dbcc2d894c9cec024a9bf2",
|
||||
"end": 17.388451443569522,
|
||||
"start": -3.552713668866051e-14,
|
||||
"speckle_type": "Objects.Primitive.Interval",
|
||||
"applicationId": null
|
||||
},
|
||||
"length": 5300.000000000002,
|
||||
"speckle_type": "Objects.Geometry.Line",
|
||||
"applicationId": null
|
||||
},
|
||||
"topLevel": {
|
||||
"name": "1FL",
|
||||
"units": "mm",
|
||||
"elevation": 0
|
||||
},
|
||||
"__closure": {
|
||||
"0ad4db1fe261a5b640ad9f315a46a6fc": 100,
|
||||
"0d5518a7a3e63fe345e198ad5d6acc4e": 100,
|
||||
"ec2040af4bd9c8619f9029a43df61a2e": 100
|
||||
},
|
||||
"elementId": "4479852",
|
||||
"worksetId": "0",
|
||||
"properties": {
|
||||
"Parameters": {
|
||||
"Type Parameters": {
|
||||
"Text": {
|
||||
"符号": {
|
||||
"name": "符号",
|
||||
"value": "W30",
|
||||
"internalDefinitionName": "ee1f33e1-5506-4a64-b87b-7b98d30aea52"
|
||||
}
|
||||
},
|
||||
"Other": {
|
||||
"Family Name": {
|
||||
"name": "Family Name",
|
||||
"value": "Basic Wall",
|
||||
"internalDefinitionName": "SYMBOL_FAMILY_NAME_PARAM"
|
||||
},
|
||||
"横筋ピッチ": {
|
||||
"name": "横筋ピッチ",
|
||||
"units": "General",
|
||||
"value": 0,
|
||||
"internalDefinitionName": "cd19c040-0788-4424-8a67-7127427e311f"
|
||||
},
|
||||
"縦筋ピッチ": {
|
||||
"name": "縦筋ピッチ",
|
||||
"units": "General",
|
||||
"value": 0,
|
||||
"internalDefinitionName": "6796d143-ef09-4441-9ecc-3411fe837a65"
|
||||
}
|
||||
},
|
||||
"Rebar Set": {
|
||||
"横筋 主筋径1": {
|
||||
"name": "横筋 主筋径1",
|
||||
"value": "D13",
|
||||
"internalDefinitionName": "横筋 主筋径1"
|
||||
},
|
||||
"横筋 主筋径2": {
|
||||
"name": "横筋 主筋径2",
|
||||
"value": "D16",
|
||||
"internalDefinitionName": "横筋 主筋径2"
|
||||
},
|
||||
"縦筋 主筋径1": {
|
||||
"name": "縦筋 主筋径1",
|
||||
"value": "D13",
|
||||
"internalDefinitionName": "縦筋 主筋径1"
|
||||
},
|
||||
"縦筋 主筋径2": {
|
||||
"name": "縦筋 主筋径2",
|
||||
"value": "D16",
|
||||
"internalDefinitionName": "縦筋 主筋径2"
|
||||
},
|
||||
"横筋 主筋ピッチ": {
|
||||
"name": "横筋 主筋ピッチ",
|
||||
"value": "200",
|
||||
"internalDefinitionName": "横筋 主筋ピッチ"
|
||||
},
|
||||
"縦筋 主筋ピッチ": {
|
||||
"name": "縦筋 主筋ピッチ",
|
||||
"value": "200",
|
||||
"internalDefinitionName": "縦筋 主筋ピッチ"
|
||||
},
|
||||
"開口補強筋 斜筋 本数": {
|
||||
"name": "開口補強筋 斜筋 本数",
|
||||
"value": "―",
|
||||
"internalDefinitionName": "開口補強筋 斜筋 本数"
|
||||
},
|
||||
"開口補強筋 横筋 本数": {
|
||||
"name": "開口補強筋 横筋 本数",
|
||||
"value": "―",
|
||||
"internalDefinitionName": "開口補強筋 横筋 本数"
|
||||
},
|
||||
"開口補強筋 縦筋 本数": {
|
||||
"name": "開口補強筋 縦筋 本数",
|
||||
"value": "―",
|
||||
"internalDefinitionName": "開口補強筋 縦筋 本数"
|
||||
}
|
||||
},
|
||||
"Structure": {
|
||||
"Fc24 (0)": {
|
||||
"units": "mm",
|
||||
"function": "Structure",
|
||||
"material": "Fc24",
|
||||
"thickness": 300
|
||||
}
|
||||
},
|
||||
"Construction": {
|
||||
"Width": {
|
||||
"name": "Width",
|
||||
"units": "Millimeters",
|
||||
"value": 300,
|
||||
"internalDefinitionName": "WALL_ATTR_WIDTH_PARAM"
|
||||
},
|
||||
"Function": {
|
||||
"name": "Function",
|
||||
"value": "Interior",
|
||||
"internalDefinitionName": "FUNCTION_PARAM"
|
||||
},
|
||||
"Wrapping at Ends": {
|
||||
"name": "Wrapping at Ends",
|
||||
"value": "None",
|
||||
"internalDefinitionName": "WRAPPING_AT_ENDS_PARAM"
|
||||
},
|
||||
"Wrapping at Inserts": {
|
||||
"name": "Wrapping at Inserts",
|
||||
"value": "Do not wrap",
|
||||
"internalDefinitionName": "WRAPPING_AT_INSERTS_PARAM"
|
||||
}
|
||||
},
|
||||
"Identity Data": {
|
||||
"Cost": {
|
||||
"name": "Cost",
|
||||
"units": "Currency",
|
||||
"value": 0,
|
||||
"internalDefinitionName": "ALL_MODEL_COST"
|
||||
},
|
||||
"Type Name": {
|
||||
"name": "Type Name",
|
||||
"value": "W30(Fc24)",
|
||||
"internalDefinitionName": "SYMBOL_NAME_PARAM"
|
||||
}
|
||||
},
|
||||
"IFC Parameters": {
|
||||
"Type IfcGUID": {
|
||||
"name": "Type IfcGUID",
|
||||
"value": "0oqavz9$zDZxycDyfZdYh0",
|
||||
"internalDefinitionName": "IFC_TYPE_GUID"
|
||||
},
|
||||
"Export Type to IFC": {
|
||||
"name": "Export Type to IFC",
|
||||
"value": "Default",
|
||||
"internalDefinitionName": "IFC_EXPORT_ELEMENT_TYPE"
|
||||
}
|
||||
},
|
||||
"Analytical Properties": {
|
||||
"Roughness": {
|
||||
"name": "Roughness",
|
||||
"value": 1,
|
||||
"internalDefinitionName": "ANALYTICAL_ROUGHNESS"
|
||||
},
|
||||
"Absorptance": {
|
||||
"name": "Absorptance",
|
||||
"units": "General",
|
||||
"value": 0.1,
|
||||
"internalDefinitionName": "ANALYTICAL_ABSORPTANCE"
|
||||
},
|
||||
"Thermal Mass": {
|
||||
"name": "Thermal Mass",
|
||||
"units": "Kilojoules per square meter Kelvin",
|
||||
"value": 0,
|
||||
"internalDefinitionName": "ANALYTICAL_THERMAL_MASS"
|
||||
},
|
||||
"Thermal Resistance (R)": {
|
||||
"name": "Thermal Resistance (R)",
|
||||
"units": "Square meter kelvins per watt",
|
||||
"value": 0,
|
||||
"internalDefinitionName": "ANALYTICAL_THERMAL_RESISTANCE"
|
||||
},
|
||||
"Heat Transfer Coefficient (U)": {
|
||||
"name": "Heat Transfer Coefficient (U)",
|
||||
"units": "Watts per square meter kelvin",
|
||||
"value": 0,
|
||||
"internalDefinitionName": "ANALYTICAL_HEAT_TRANSFER_COEFFICIENT"
|
||||
}
|
||||
},
|
||||
"Materials and Finishes": {
|
||||
"Structural Material": {
|
||||
"name": "Structural Material",
|
||||
"value": "Fc24",
|
||||
"internalDefinitionName": "STRUCTURAL_MATERIAL_PARAM"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Instance Parameters": {
|
||||
"Other": {
|
||||
"Type": {
|
||||
"name": "Type",
|
||||
"value": "W30(Fc24)",
|
||||
"internalDefinitionName": "ELEM_TYPE_PARAM"
|
||||
},
|
||||
"Family": {
|
||||
"name": "Family",
|
||||
"value": "Basic Wall",
|
||||
"internalDefinitionName": "ELEM_FAMILY_PARAM"
|
||||
},
|
||||
"Type Id": {
|
||||
"name": "Type Id",
|
||||
"value": "Basic Wall W30(Fc24)",
|
||||
"internalDefinitionName": "SYMBOL_ID_PARAM"
|
||||
},
|
||||
"Family and Type": {
|
||||
"name": "Family and Type",
|
||||
"value": "Basic Wall W30(Fc24)",
|
||||
"internalDefinitionName": "ELEM_FAMILY_AND_TYPE_PARAM"
|
||||
}
|
||||
},
|
||||
"Phasing": {
|
||||
"Phase Created": {
|
||||
"name": "Phase Created",
|
||||
"value": "フェーズ1",
|
||||
"internalDefinitionName": "PHASE_CREATED"
|
||||
}
|
||||
},
|
||||
"Dimensions": {
|
||||
"Area": {
|
||||
"name": "Area",
|
||||
"units": "Square meters",
|
||||
"value": 7.630000000000015,
|
||||
"internalDefinitionName": "HOST_AREA_COMPUTED"
|
||||
},
|
||||
"Length": {
|
||||
"name": "Length",
|
||||
"units": "Millimeters",
|
||||
"value": 5300.000000000001,
|
||||
"internalDefinitionName": "CURVE_ELEM_LENGTH"
|
||||
},
|
||||
"Volume": {
|
||||
"name": "Volume",
|
||||
"units": "Cubic meters",
|
||||
"value": 2.2890000000000135,
|
||||
"internalDefinitionName": "HOST_VOLUME_COMPUTED"
|
||||
}
|
||||
},
|
||||
"Structural": {
|
||||
"Structural": {
|
||||
"name": "Structural",
|
||||
"value": "Yes",
|
||||
"internalDefinitionName": "WALL_STRUCTURAL_SIGNIFICANT"
|
||||
},
|
||||
"Structural Usage": {
|
||||
"name": "Structural Usage",
|
||||
"value": "Bearing",
|
||||
"internalDefinitionName": "WALL_STRUCTURAL_USAGE_PARAM"
|
||||
},
|
||||
"Rebar Cover - Other Faces": {
|
||||
"name": "Rebar Cover - Other Faces",
|
||||
"value": "Rebar Cover Settings 内壁(フレーム、柱、および耐力壁)",
|
||||
"internalDefinitionName": "CLEAR_COVER_OTHER"
|
||||
},
|
||||
"Rebar Cover - Exterior Face": {
|
||||
"name": "Rebar Cover - Exterior Face",
|
||||
"value": "Rebar Cover Settings 内壁(フレーム、柱、および耐力壁)",
|
||||
"internalDefinitionName": "CLEAR_COVER_EXTERIOR"
|
||||
},
|
||||
"Rebar Cover - Interior Face": {
|
||||
"name": "Rebar Cover - Interior Face",
|
||||
"value": "Rebar Cover Settings 内壁(フレーム、柱、および耐力壁)",
|
||||
"internalDefinitionName": "CLEAR_COVER_INTERIOR"
|
||||
},
|
||||
"構造スリット 下端": {
|
||||
"name": "構造スリット 下端",
|
||||
"value": "No",
|
||||
"internalDefinitionName": "0560d1bb-007b-45e4-b8c3-87f9c6a3d73c"
|
||||
},
|
||||
"構造スリット 始端": {
|
||||
"name": "構造スリット 始端",
|
||||
"value": "No",
|
||||
"internalDefinitionName": "60795a90-8c91-4e11-90a0-b77b819c2403"
|
||||
},
|
||||
"構造スリット 終端": {
|
||||
"name": "構造スリット 終端",
|
||||
"value": "No",
|
||||
"internalDefinitionName": "e3223f14-6158-4d4f-8697-0de2bcc7f737"
|
||||
}
|
||||
},
|
||||
"Constraints": {
|
||||
"Top Offset": {
|
||||
"name": "Top Offset",
|
||||
"units": "Millimeters",
|
||||
"value": -600,
|
||||
"internalDefinitionName": "WALL_TOP_OFFSET"
|
||||
},
|
||||
"Base Offset": {
|
||||
"name": "Base Offset",
|
||||
"units": "Millimeters",
|
||||
"value": -2000,
|
||||
"internalDefinitionName": "WALL_BASE_OFFSET"
|
||||
},
|
||||
"Location Line": {
|
||||
"name": "Location Line",
|
||||
"value": "Core Centerline",
|
||||
"internalDefinitionName": "WALL_KEY_REF_PARAM"
|
||||
},
|
||||
"Room Bounding": {
|
||||
"name": "Room Bounding",
|
||||
"value": "Yes",
|
||||
"internalDefinitionName": "WALL_ATTR_ROOM_BOUNDING"
|
||||
},
|
||||
"Top Constraint": {
|
||||
"name": "Top Constraint",
|
||||
"value": "1FL",
|
||||
"internalDefinitionName": "WALL_HEIGHT_TYPE"
|
||||
},
|
||||
"Base Constraint": {
|
||||
"name": "Base Constraint",
|
||||
"value": "1FL",
|
||||
"internalDefinitionName": "WALL_BASE_CONSTRAINT"
|
||||
},
|
||||
"Related to Mass": {
|
||||
"name": "Related to Mass",
|
||||
"value": "No",
|
||||
"internalDefinitionName": "RELATED_TO_MASS"
|
||||
},
|
||||
"Top is Attached": {
|
||||
"name": "Top is Attached",
|
||||
"value": "No",
|
||||
"internalDefinitionName": "WALL_TOP_IS_ATTACHED"
|
||||
},
|
||||
"Base is Attached": {
|
||||
"name": "Base is Attached",
|
||||
"value": "No",
|
||||
"internalDefinitionName": "WALL_BOTTOM_IS_ATTACHED"
|
||||
},
|
||||
"Unconnected Height": {
|
||||
"name": "Unconnected Height",
|
||||
"units": "Millimeters",
|
||||
"value": 1400,
|
||||
"internalDefinitionName": "WALL_USER_HEIGHT_PARAM"
|
||||
},
|
||||
"Top Extension Distance": {
|
||||
"name": "Top Extension Distance",
|
||||
"units": "Millimeters",
|
||||
"value": 0,
|
||||
"internalDefinitionName": "WALL_TOP_EXTENSION_DIST_PARAM"
|
||||
},
|
||||
"Base Extension Distance": {
|
||||
"name": "Base Extension Distance",
|
||||
"units": "Millimeters",
|
||||
"value": 0,
|
||||
"internalDefinitionName": "WALL_BOTTOM_EXTENSION_DIST_PARAM"
|
||||
}
|
||||
},
|
||||
"Identity Data": {
|
||||
"Has Association": {
|
||||
"name": "Has Association",
|
||||
"value": "Yes",
|
||||
"internalDefinitionName": "ANALYTICAL_ELEMENT_HAS_ASSOCIATION"
|
||||
},
|
||||
"SPECKLE_Classification": {
|
||||
"name": "SPECKLE_Classification",
|
||||
"value": "Wall",
|
||||
"internalDefinitionName": "SPECKLE_Classification"
|
||||
}
|
||||
},
|
||||
"IFC Parameters": {
|
||||
"IfcGUID": {
|
||||
"name": "IfcGUID",
|
||||
"value": "0oqavz9$zDZxycDyfZdYsW",
|
||||
"internalDefinitionName": "IFC_GUID"
|
||||
},
|
||||
"Export to IFC": {
|
||||
"name": "Export to IFC",
|
||||
"value": "By Type",
|
||||
"internalDefinitionName": "IFC_EXPORT_ELEMENT"
|
||||
}
|
||||
},
|
||||
"Cross-Section Definition": {
|
||||
"Cross-Section": {
|
||||
"name": "Cross-Section",
|
||||
"value": "Vertical",
|
||||
"internalDefinitionName": "WALL_CROSS_SECTION"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Material Quantities": {
|
||||
"Fc24": {
|
||||
"area": 7630000.000000016,
|
||||
"units": "mm",
|
||||
"volume": 2289000000.0000134,
|
||||
"materialName": "Fc24",
|
||||
"materialClass": "コンクリート",
|
||||
"materialCategory": "コンクリート"
|
||||
}
|
||||
}
|
||||
},
|
||||
"worksetName": "ワークセット1",
|
||||
"displayValue": [
|
||||
{
|
||||
"__closure": null,
|
||||
"referencedId": "ec2040af4bd9c8619f9029a43df61a2e",
|
||||
"speckle_type": "reference"
|
||||
}
|
||||
],
|
||||
"isStructural": true,
|
||||
"speckle_type": "Objects.Data.DataObject:Objects.Data.RevitObject",
|
||||
"applicationId": "32d24e7d-27ff-4d8f-bf26-37ca63da76cc-00445b6c",
|
||||
"builtInCategory": "OST_Walls",
|
||||
"totalChildrenCount": null
|
||||
},
|
||||
{
|
||||
"id": "0ad4db1fe261a5b640ad9f315a46a6fc",
|
||||
"data": [
|
||||
3,
|
||||
5,
|
||||
0,
|
||||
1,
|
||||
3,
|
||||
5,
|
||||
1,
|
||||
4,
|
||||
3,
|
||||
4,
|
||||
2,
|
||||
3,
|
||||
3,
|
||||
2,
|
||||
4,
|
||||
1,
|
||||
3,
|
||||
11,
|
||||
12,
|
||||
9,
|
||||
3,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
3,
|
||||
12,
|
||||
13,
|
||||
9,
|
||||
3,
|
||||
13,
|
||||
6,
|
||||
8,
|
||||
3,
|
||||
7,
|
||||
8,
|
||||
6,
|
||||
3,
|
||||
13,
|
||||
8,
|
||||
9,
|
||||
3,
|
||||
15,
|
||||
16,
|
||||
18,
|
||||
3,
|
||||
14,
|
||||
15,
|
||||
19,
|
||||
3,
|
||||
17,
|
||||
18,
|
||||
16,
|
||||
3,
|
||||
19,
|
||||
20,
|
||||
14,
|
||||
3,
|
||||
18,
|
||||
19,
|
||||
15,
|
||||
3,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
3,
|
||||
23,
|
||||
24,
|
||||
21,
|
||||
3,
|
||||
26,
|
||||
27,
|
||||
29,
|
||||
3,
|
||||
25,
|
||||
26,
|
||||
30,
|
||||
3,
|
||||
28,
|
||||
29,
|
||||
27,
|
||||
3,
|
||||
30,
|
||||
31,
|
||||
25,
|
||||
3,
|
||||
29,
|
||||
30,
|
||||
26,
|
||||
3,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
3,
|
||||
34,
|
||||
35,
|
||||
32
|
||||
],
|
||||
"speckle_type": "Speckle.Core.Models.DataChunk",
|
||||
"applicationId": null
|
||||
},
|
||||
{
|
||||
"id": "0d5518a7a3e63fe345e198ad5d6acc4e",
|
||||
"data": [
|
||||
22550.00031738281,
|
||||
15049.999969482422,
|
||||
-2000.000015258789,
|
||||
22550.00031738281,
|
||||
20274.999645996093,
|
||||
-2000.000015258789,
|
||||
22550.00031738281,
|
||||
20499.999865722657,
|
||||
-2000.000015258789,
|
||||
22550.00031738281,
|
||||
20499.999865722657,
|
||||
-600.0000045776368,
|
||||
22550.00031738281,
|
||||
20274.999645996093,
|
||||
-600.0000045776368,
|
||||
22550.00031738281,
|
||||
15049.999969482422,
|
||||
-600.0000045776368,
|
||||
22250.000024414065,
|
||||
15049.999969482422,
|
||||
-2000.000015258789,
|
||||
22250.000024414065,
|
||||
15049.999969482422,
|
||||
-600.0000045776368,
|
||||
22250.000024414065,
|
||||
15350.000262451173,
|
||||
-600.0000045776368,
|
||||
22250.000024414065,
|
||||
20274.999645996093,
|
||||
-600.0000045776368,
|
||||
22250.000024414065,
|
||||
20499.999865722657,
|
||||
-600.0000045776368,
|
||||
22250.000024414065,
|
||||
20499.999865722657,
|
||||
-2000.000015258789,
|
||||
22250.000024414065,
|
||||
20274.999645996093,
|
||||
-2000.000015258789,
|
||||
22250.000024414065,
|
||||
15350.000262451173,
|
||||
-2000.000015258789,
|
||||
22550.00031738281,
|
||||
20499.999865722657,
|
||||
-2000.000015258789,
|
||||
22550.00031738281,
|
||||
20274.999645996093,
|
||||
-2000.000015258789,
|
||||
22550.00031738281,
|
||||
15049.999969482422,
|
||||
-2000.000015258789,
|
||||
22250.000024414065,
|
||||
15049.999969482422,
|
||||
-2000.000015258789,
|
||||
22250.000024414065,
|
||||
15350.000262451173,
|
||||
-2000.000015258789,
|
||||
22250.000024414065,
|
||||
20274.999645996093,
|
||||
-2000.000015258789,
|
||||
22250.000024414065,
|
||||
20499.999865722657,
|
||||
-2000.000015258789,
|
||||
22550.00031738281,
|
||||
20499.999865722657,
|
||||
-2000.000015258789,
|
||||
22250.000024414065,
|
||||
20499.999865722657,
|
||||
-2000.000015258789,
|
||||
22250.000024414065,
|
||||
20499.999865722657,
|
||||
-600.0000045776368,
|
||||
22550.00031738281,
|
||||
20499.999865722657,
|
||||
-600.0000045776368,
|
||||
22550.00031738281,
|
||||
15049.999969482422,
|
||||
-600.0000045776368,
|
||||
22550.00031738281,
|
||||
20274.999645996093,
|
||||
-600.0000045776368,
|
||||
22550.00031738281,
|
||||
20499.999865722657,
|
||||
-600.0000045776368,
|
||||
22250.000024414065,
|
||||
20499.999865722657,
|
||||
-600.0000045776368,
|
||||
22250.000024414065,
|
||||
20274.999645996093,
|
||||
-600.0000045776368,
|
||||
22250.000024414065,
|
||||
15350.000262451173,
|
||||
-600.0000045776368,
|
||||
22250.000024414065,
|
||||
15049.999969482422,
|
||||
-600.0000045776368,
|
||||
22550.00031738281,
|
||||
15049.999969482422,
|
||||
-600.0000045776368,
|
||||
22250.000024414065,
|
||||
15049.999969482422,
|
||||
-600.0000045776368,
|
||||
22250.000024414065,
|
||||
15049.999969482422,
|
||||
-2000.000015258789,
|
||||
22550.00031738281,
|
||||
15049.999969482422,
|
||||
-2000.000015258789
|
||||
],
|
||||
"speckle_type": "Speckle.Core.Models.DataChunk",
|
||||
"applicationId": null
|
||||
},
|
||||
{
|
||||
"id": "ec2040af4bd9c8619f9029a43df61a2e",
|
||||
"area": 0,
|
||||
"bbox": null,
|
||||
"faces": [
|
||||
{
|
||||
"__closure": null,
|
||||
"referencedId": "0ad4db1fe261a5b640ad9f315a46a6fc",
|
||||
"speckle_type": "reference"
|
||||
}
|
||||
],
|
||||
"units": "mm",
|
||||
"colors": [],
|
||||
"volume": 0,
|
||||
"vertices": [
|
||||
{
|
||||
"__closure": null,
|
||||
"referencedId": "0d5518a7a3e63fe345e198ad5d6acc4e",
|
||||
"speckle_type": "reference"
|
||||
}
|
||||
],
|
||||
"__closure": {
|
||||
"0ad4db1fe261a5b640ad9f315a46a6fc": 100,
|
||||
"0d5518a7a3e63fe345e198ad5d6acc4e": 100
|
||||
},
|
||||
"speckle_type": "Objects.Geometry.Mesh",
|
||||
"applicationId": "d2c33253-d0ed-4682-9633-e083daaa87db",
|
||||
"textureCoordinates": []
|
||||
}
|
||||
]
|
||||
+126
-18
@@ -1,24 +1,132 @@
|
||||
import os
|
||||
|
||||
from dotenv import load_dotenv
|
||||
import pytest
|
||||
from specklepy.objects.base import Base
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
load_dotenv(dotenv_path=".env")
|
||||
@pytest.fixture
|
||||
def v2_wall():
|
||||
"""Creates a v2-style Speckle wall object."""
|
||||
wall = Base()
|
||||
wall.id = "cdb18060dc48281909e94f0f1d8d3cc0"
|
||||
wall.type = "W30(Fc24)"
|
||||
wall.units = "mm"
|
||||
wall.family = "Basic Wall"
|
||||
wall.height = 1400
|
||||
wall.flipped = False
|
||||
wall.category = "Walls"
|
||||
wall.elementId = "4479852"
|
||||
wall.worksetId = "0"
|
||||
wall.structural = True
|
||||
wall.baseOffset = -2000
|
||||
wall.topOffset = -600
|
||||
|
||||
token_var = "SPECKLE_TOKEN"
|
||||
server_var = "SPECKLE_SERVER_URL"
|
||||
token = os.getenv(token_var)
|
||||
server = os.getenv(server_var)
|
||||
# Create base line geometry
|
||||
wall.baseLine = Base()
|
||||
wall.baseLine.start = Base()
|
||||
wall.baseLine.start.x = 22400.000000000007
|
||||
wall.baseLine.start.y = 15199.999999999998
|
||||
wall.baseLine.start.z = -2000.0000000000002
|
||||
wall.baseLine.end = Base()
|
||||
wall.baseLine.end.x = 22400.000000000015
|
||||
wall.baseLine.end.y = 20500
|
||||
wall.baseLine.end.z = -2000.0000000000002
|
||||
wall.baseLine.units = "mm"
|
||||
wall.baseLine.length = 5300.000000000002
|
||||
|
||||
if not token:
|
||||
raise ValueError(f"Cannot run tests without a {token_var} environment variable")
|
||||
# Create parameters structure
|
||||
wall.parameters = Base()
|
||||
|
||||
if not server:
|
||||
raise ValueError(
|
||||
f"Cannot run tests without a {server_var} environment variable"
|
||||
)
|
||||
# Standard parameter
|
||||
wall.parameters["WALL_ATTR_WIDTH_PARAM"] = Base()
|
||||
wall.parameters["WALL_ATTR_WIDTH_PARAM"].name = "Width"
|
||||
wall.parameters["WALL_ATTR_WIDTH_PARAM"].value = 300
|
||||
wall.parameters["WALL_ATTR_WIDTH_PARAM"].units = "mm"
|
||||
|
||||
# Set the token as an attribute on the config object
|
||||
config.SPECKLE_TOKEN = token
|
||||
config.SPECKLE_SERVER_URL = server
|
||||
# Parameter with GUID key
|
||||
wall.parameters["ee1f33e1-5506-4a64-b87b-7b98d30aea52"] = Base()
|
||||
wall.parameters["ee1f33e1-5506-4a64-b87b-7b98d30aea52"].name = "符号"
|
||||
wall.parameters["ee1f33e1-5506-4a64-b87b-7b98d30aea52"].value = "W30"
|
||||
wall.parameters["ee1f33e1-5506-4a64-b87b-7b98d30aea52"].isShared = True
|
||||
wall.parameters[
|
||||
"ee1f33e1-5506-4a64-b87b-7b98d30aea52"
|
||||
].internalDefinitionName = "ee1f33e1-5506-4a64-b87b-7b98d30aea52"
|
||||
|
||||
wall.parameters["STRUCTURAL_MATERIAL_PARAM"] = Base()
|
||||
wall.parameters["STRUCTURAL_MATERIAL_PARAM"].name = "Structural Material"
|
||||
wall.parameters["STRUCTURAL_MATERIAL_PARAM"].value = "Fc24"
|
||||
|
||||
# Create basic level reference
|
||||
wall.level = Base()
|
||||
wall.level.name = "1FL"
|
||||
wall.level.elevation = 0
|
||||
wall.level.units = "mm"
|
||||
|
||||
return wall
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def v3_wall():
|
||||
"""Creates a v3-style Speckle wall object."""
|
||||
wall = Base()
|
||||
wall.id = "46f06fef727d64a0bbcbd7ced51e0cd2"
|
||||
wall.name = "Walls - W30(Fc24)"
|
||||
wall.type = "W30(Fc24)"
|
||||
wall.units = "mm"
|
||||
wall.family = "Basic Wall"
|
||||
wall.flipped = False
|
||||
wall.category = "Walls"
|
||||
wall.elementId = "4479852"
|
||||
wall.worksetId = "0"
|
||||
|
||||
# Create location geometry
|
||||
wall.location = Base()
|
||||
wall.location.start = Base()
|
||||
wall.location.start.x = 22400.000000000007
|
||||
wall.location.start.y = 15199.999999999998
|
||||
wall.location.start.z = 0
|
||||
wall.location.end = Base()
|
||||
wall.location.end.x = 22400.000000000015
|
||||
wall.location.end.y = 20500
|
||||
wall.location.end.z = 0
|
||||
wall.location.units = "mm"
|
||||
wall.location.length = 5300.000000000002
|
||||
|
||||
# Create nested properties structure
|
||||
wall.properties = Base()
|
||||
wall.properties.Parameters = Base()
|
||||
|
||||
# Type Parameters
|
||||
wall.properties.Parameters["Type Parameters"] = Base()
|
||||
|
||||
# Add Text section with GUID parameter
|
||||
wall.properties.Parameters["Type Parameters"].Text = Base()
|
||||
wall.properties.Parameters["Type Parameters"].Text["符号"] = {
|
||||
"name": "符号",
|
||||
"value": "W30",
|
||||
"internalDefinitionName": "ee1f33e1-5506-4a64-b87b-7b98d30aea52",
|
||||
}
|
||||
|
||||
wall.properties.Parameters["Type Parameters"].Structure = Base()
|
||||
wall.properties.Parameters["Type Parameters"].Structure["Fc24 (0)"] = {
|
||||
"units": "mm",
|
||||
"function": "Structure",
|
||||
"material": "Fc24",
|
||||
"thickness": 300,
|
||||
}
|
||||
|
||||
# Instance Parameters
|
||||
wall.properties.Parameters["Instance Parameters"] = Base()
|
||||
wall.properties.Parameters["Instance Parameters"].Structural = Base()
|
||||
wall.properties.Parameters["Instance Parameters"].Structural.Structural = {"name": "Structural", "value": "Yes"}
|
||||
|
||||
# Create basic level references
|
||||
wall.level = Base()
|
||||
wall.level.name = "1FL"
|
||||
wall.level.elevation = 0
|
||||
wall.level.units = "mm"
|
||||
|
||||
wall.topLevel = Base()
|
||||
wall.topLevel.name = "1FL"
|
||||
wall.topLevel.elevation = 0
|
||||
wall.topLevel.units = "mm"
|
||||
|
||||
return wall
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
"""Run integration tests with a speckle server."""
|
||||
|
||||
from speckle_automate import (
|
||||
AutomationContext,
|
||||
AutomationRunData,
|
||||
AutomationStatus,
|
||||
run_function
|
||||
)
|
||||
|
||||
from src.inputs import FunctionInputs
|
||||
from src.function import automate_function
|
||||
|
||||
|
||||
def test_function_run(test_automation_run_data: AutomationRunData, test_automation_token: str):
|
||||
"""Run an integration test for the automate function."""
|
||||
automation_context = AutomationContext.initialize(
|
||||
test_automation_run_data, test_automation_token
|
||||
)
|
||||
default_url: str = (
|
||||
"https://docs.google.com/spreadsheets/d/e/2PACX-1vSFmjLfqxPKXJHg-wEs1cp_nJEJJhESGVTLCvWLG_"
|
||||
"IgIuRZ4CmMDCSceOYFvuo8IqcmT4sj9qPiLfCx/pub?gid=0&single=true&output=tsv"
|
||||
)
|
||||
|
||||
automate_sdk = run_function(
|
||||
automation_context,
|
||||
automate_function,
|
||||
FunctionInputs(spreadsheet_url=default_url),
|
||||
)
|
||||
|
||||
assert automate_sdk.run_status == AutomationStatus.SUCCEEDED
|
||||
|
||||
# cli command to run just this test with pytest: pytest tests/local_test_exercise2.py::test_function_run
|
||||
+20
-10
@@ -1,31 +1,41 @@
|
||||
"""Run integration tests with a speckle server."""
|
||||
|
||||
from pydantic import SecretStr
|
||||
|
||||
from speckle_automate import (
|
||||
AutomationContext,
|
||||
AutomationRunData,
|
||||
AutomationStatus,
|
||||
run_function
|
||||
run_function,
|
||||
)
|
||||
from speckle_automate.fixtures import * # noqa: F401, F403
|
||||
|
||||
from main import FunctionInputs, automate_function
|
||||
|
||||
from speckle_automate.fixtures import *
|
||||
from src.function import automate_function
|
||||
from src.helpers import speckle_print
|
||||
from src.inputs import FunctionInputs
|
||||
|
||||
|
||||
def test_function_run(test_automation_run_data: AutomationRunData, test_automation_token: str):
|
||||
"""Run an integration test for the automate function.
|
||||
|
||||
Args:
|
||||
test_automation_run_data (AutomationRunData): The automation run data provided by sdk.
|
||||
test_automation_token (str): The automation token.
|
||||
|
||||
"""
|
||||
speckle_print(str(test_automation_run_data))
|
||||
speckle_print(str(test_automation_token))
|
||||
|
||||
"""Run an integration test for the automate function."""
|
||||
automation_context = AutomationContext.initialize(
|
||||
test_automation_run_data, test_automation_token
|
||||
)
|
||||
default_url: str = (
|
||||
"https://drive.google.com/uc?export=download&id=1hiPSw23eOaqd27QD_YsXvZg9PWm7_XBx"
|
||||
)
|
||||
|
||||
automate_sdk = run_function(
|
||||
automation_context,
|
||||
automate_function,
|
||||
FunctionInputs(
|
||||
forbidden_speckle_type="None",
|
||||
whisper_message=SecretStr("testing automatically"),
|
||||
),
|
||||
FunctionInputs(spreadsheet_url=default_url),
|
||||
)
|
||||
|
||||
assert automate_sdk.run_status == AutomationStatus.SUCCEEDED
|
||||
|
||||
@@ -0,0 +1,404 @@
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from dotenv import load_dotenv
|
||||
from speckle_automate import AutomationContext, AutomationRunData # noqa: F401, F403
|
||||
|
||||
# from speckle_automate.fixtures import * # noqa: F401, F403
|
||||
from specklepy.api.client import SpeckleClient
|
||||
from specklepy.core.api import operations
|
||||
from specklepy.objects.base import Base
|
||||
from specklepy.transports.server import ServerTransport
|
||||
|
||||
from helpers import speckle_print
|
||||
from src.rules import PropertyRules
|
||||
|
||||
|
||||
def load_test_objects(v2_wall: Any, v3_wall: Any) -> tuple[Base, Base]:
|
||||
"""Load test objects from a Speckle server."""
|
||||
client = SpeckleClient(host="https://app.speckle.systems", use_ssl=True)
|
||||
|
||||
load_dotenv(dotenv_path="../.env")
|
||||
|
||||
client.authenticate_with_token(os.getenv("SPECKLE_TOKEN"))
|
||||
|
||||
transport = ServerTransport(client=client, stream_id=os.getenv("SPECKLE_PROJECT_ID"))
|
||||
|
||||
speckle_print(v2_wall)
|
||||
v2_obj = operations.receive("cdb18060dc48281909e94f0f1d8d3cc0", transport)
|
||||
v3_obj = operations.receive("46f06fef727d64a0bbcbd7ced51e0cd2", transport)
|
||||
|
||||
# return v2_wall, v3_wall
|
||||
return v2_obj, v3_obj
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_objects(v2_wall: Any, v3_wall: Any) -> tuple[Base, Base]:
|
||||
"""Pytest fixture to provide test objects."""
|
||||
return load_test_objects(v2_wall, v3_wall)
|
||||
|
||||
|
||||
def test_deserialization_structure(test_objects):
|
||||
"""Test that objects are properly deserialized with correct structure."""
|
||||
v2_obj, v3_obj = test_objects
|
||||
|
||||
# Check base class type
|
||||
for obj in [v2_obj, v3_obj]:
|
||||
assert isinstance(obj, Base), f"Expected {obj} to be an instance of Base"
|
||||
|
||||
# Check v2 structure
|
||||
assert hasattr(v2_obj, "parameters"), "v2_obj should have 'parameters' attribute"
|
||||
assert v2_obj["parameters"] is not None, "v2_obj['parameters'] should not be None"
|
||||
|
||||
# Check v3 structure
|
||||
assert hasattr(v3_obj, "properties"), "v3_obj should have 'properties' attribute"
|
||||
assert v3_obj["properties"] is not None, "v3_obj['properties'] should not be None"
|
||||
assert "Parameters" in v3_obj["properties"], "'Parameters' key should exist in v3_obj['properties']"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name, expected_result",
|
||||
[
|
||||
("category", True), # Test parameters that should exist
|
||||
("WALL_ATTR_WIDTH_PARAM", True), # Test nested parameters
|
||||
("WALL_ATTR_WIDTH_PARAM.value", True),
|
||||
("WALL_ATTR_WIDTH_PARAM.id", True),
|
||||
("WALL_ATTR_WIDTH_PARAM.units", True),
|
||||
("non_existent_param", False), # Test non-existent parameters
|
||||
],
|
||||
)
|
||||
def test_v2_parameter_exists(test_objects, param_name, expected_result):
|
||||
"""Test parameter existence checking in v2 objects."""
|
||||
v2_obj, _ = test_objects
|
||||
assert PropertyRules.has_parameter(v2_obj, param_name) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name",
|
||||
[
|
||||
"WALL_ATTR_WIDTH_PARAM.id",
|
||||
"WALL_ATTR_WIDTH_PARAM.value",
|
||||
"WALL_ATTR_WIDTH_PARAM",
|
||||
"WALL_ATTR_WIDTH_PARAM.units",
|
||||
],
|
||||
)
|
||||
def test_v2_parameter_value_retrieval(test_objects, param_name):
|
||||
"""Test parameter value retrieval in v2 objects."""
|
||||
v2_obj, _ = test_objects
|
||||
assert PropertyRules.get_parameter_value(v2_obj, param_name)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name, expected_result",
|
||||
[
|
||||
("category", True), # Test parameters that should exist
|
||||
("Width", True), # Test nested parameters
|
||||
("non_existent_param", False), # Test non-existent parameters
|
||||
],
|
||||
)
|
||||
def test_v3_parameter_exists(test_objects, param_name, expected_result):
|
||||
"""Test parameter existence checking in v3 objects."""
|
||||
_, v3_obj = test_objects
|
||||
assert PropertyRules.has_parameter(v3_obj, param_name) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name_1, param_name_2",
|
||||
[
|
||||
(
|
||||
"properties.Parameters.Instance Parameters.Dimensions.Length.value",
|
||||
"Instance Parameters.Dimensions.Length",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_v3_parameter_search_equivalence(test_objects, param_name_1, param_name_2):
|
||||
"""Test parameter existence checking equivalence in v3 objects."""
|
||||
_, v3_obj = test_objects
|
||||
assert PropertyRules.get_parameter_value(v3_obj, param_name_1) == PropertyRules.get_parameter_value(
|
||||
v3_obj, param_name_2
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"obj_version, param_name, expected_value, default_value",
|
||||
[
|
||||
# Test direct parameters
|
||||
("v2", "category", "Walls", None),
|
||||
("v3", "category", "Walls", None),
|
||||
# Test nested parameters - using both internal and friendly names
|
||||
("v2", "WALL_ATTR_WIDTH_PARAM", 300, None),
|
||||
("v3", "Construction.Width", 300, None),
|
||||
# Test parameters with units
|
||||
("v2", "CURVE_ELEM_LENGTH", 5300.000000000001, None),
|
||||
("v3", "Instance Parameters.Dimensions.Length", 5300.000000000001, None),
|
||||
# Test non-existent parameters with a default value
|
||||
("v2", "parameters.non_existent", "default", "default"),
|
||||
("v3", "properties.Parameters.non_existent", "default", "default"),
|
||||
],
|
||||
)
|
||||
def test_parameter_value_retrieval(test_objects, obj_version, param_name, expected_value, default_value):
|
||||
"""Test parameter value retrieval from both v2 and v3 objects."""
|
||||
v2_obj, v3_obj = test_objects
|
||||
obj = v2_obj if obj_version == "v2" else v3_obj
|
||||
result = PropertyRules.get_parameter_value(obj, param_name, default_value=default_value)
|
||||
assert result == expected_value
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name, expected_value, expected_result",
|
||||
[
|
||||
("category", "Walls", True), # Test exact match
|
||||
("WALL_ATTR_WIDTH_PARAM", 300, True), # Test numeric match
|
||||
("category", "Windows", False), # Test non-match
|
||||
],
|
||||
)
|
||||
def test_v2_parameter_value_matching(test_objects, param_name, expected_value, expected_result):
|
||||
"""Test parameter value matching in v2 objects."""
|
||||
v2_obj, _ = test_objects
|
||||
assert PropertyRules.is_parameter_value(v2_obj, param_name, expected_value) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name, expected_value, expected_result",
|
||||
[
|
||||
("category", "Walls", True), # Test exact match
|
||||
("Width", 300, True), # Test numeric match
|
||||
("category", "Windows", False), # Test non-match
|
||||
],
|
||||
)
|
||||
def test_v3_parameter_value_matching(test_objects, param_name, expected_value, expected_result):
|
||||
"""Test parameter value matching in v3 objects."""
|
||||
_, v3_obj = test_objects
|
||||
assert PropertyRules.is_parameter_value(v3_obj, param_name, expected_value) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"comparison_func, param_name, value, expected_result",
|
||||
[
|
||||
(PropertyRules.is_parameter_value_greater_than, "WALL_ATTR_WIDTH_PARAM", "200", True), # Test greater than
|
||||
(PropertyRules.is_parameter_value_less_than, "WALL_ATTR_WIDTH_PARAM", "400", True), # Test less than
|
||||
(PropertyRules.is_parameter_value_in_range, "WALL_ATTR_WIDTH_PARAM", "200,400", True), # Test in range
|
||||
],
|
||||
)
|
||||
def test_v2_parameter_numeric_comparisons(test_objects, comparison_func, param_name, value, expected_result):
|
||||
"""Test numeric parameter comparisons in v2 objects."""
|
||||
v2_obj, _ = test_objects
|
||||
assert comparison_func(v2_obj, param_name, value) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"comparison_func, param_name, value, expected_result",
|
||||
[
|
||||
(PropertyRules.is_parameter_value_greater_than, "Width", "200", True), # Test greater than
|
||||
(PropertyRules.is_parameter_value_less_than, "Width", "400", True), # Test less than
|
||||
(PropertyRules.is_parameter_value_in_range, "Width", "200,400", True), # Test in range
|
||||
],
|
||||
)
|
||||
def test_v3_parameter_numeric_comparisons(test_objects, comparison_func, param_name, value, expected_result):
|
||||
"""Test numeric parameter comparisons in v3 objects."""
|
||||
_, v3_obj = test_objects
|
||||
assert comparison_func(v3_obj, param_name, value) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name, pattern, fuzzy, expected_result",
|
||||
[
|
||||
("category", "^Walls$", False, True), # Test exact pattern matches
|
||||
("category", "Walls", True, True), # Test fuzzy matches
|
||||
("category", "Wall", False, True), # Test partial pattern matches
|
||||
("category", "^Windows$", False, False), # Test non-matches
|
||||
],
|
||||
)
|
||||
def test_v2_parameter_value_like(test_objects, param_name, pattern, fuzzy, expected_result):
|
||||
"""Test pattern matching on parameter values in v2 objects."""
|
||||
v2_obj, _ = test_objects
|
||||
assert PropertyRules.is_parameter_value_like(v2_obj, param_name, pattern, fuzzy=fuzzy) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name, pattern, fuzzy, expected_result",
|
||||
[
|
||||
("category", "^Walls$", False, True), # Test exact pattern matches
|
||||
("category", "Walls", True, True), # Test fuzzy matches
|
||||
("category", "Wall", False, True), # Test partial pattern matches
|
||||
("category", "^Windows$", False, False), # Test non-matches
|
||||
],
|
||||
)
|
||||
def test_v3_parameter_value_like(test_objects, param_name, pattern, fuzzy, expected_result):
|
||||
"""Test pattern matching on parameter values in v3 objects."""
|
||||
_, v3_obj = test_objects
|
||||
assert PropertyRules.is_parameter_value_like(v3_obj, param_name, pattern, fuzzy=fuzzy) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name, valid_list, expected_result",
|
||||
[
|
||||
("category", ["Walls", "Windows", "Doors"], True), # Test value in list
|
||||
("category", "Walls,Windows,Doors", True), # Test comma-separated string list
|
||||
("category", ["Windows", "Doors"], False), # Test value not in list
|
||||
],
|
||||
)
|
||||
def test_v2_parameter_lists(test_objects, param_name, valid_list, expected_result):
|
||||
"""Test list-based parameter checks in v2 objects."""
|
||||
v2_obj, _ = test_objects
|
||||
assert PropertyRules.is_parameter_value_in_list(v2_obj, param_name, valid_list) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name, valid_list, expected_result",
|
||||
[
|
||||
("category", ["Walls", "Windows", "Doors"], True), # Test value in list
|
||||
("category", "Walls,Windows,Doors", True), # Test comma-separated string list
|
||||
("category", ["Windows", "Doors"], False), # Test value not in list
|
||||
],
|
||||
)
|
||||
def test_v3_parameter_lists(test_objects, param_name, valid_list, expected_result):
|
||||
"""Test list-based parameter checks in v3 objects."""
|
||||
_, v3_obj = test_objects
|
||||
assert PropertyRules.is_parameter_value_in_list(v3_obj, param_name, valid_list) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name, expected_result",
|
||||
[
|
||||
("WALL_ATTR_ROOM_BOUNDING.value", True), # Test true values
|
||||
("wall_top_is_attached", False), # Test false values
|
||||
],
|
||||
)
|
||||
def test_v2_boolean_parameters(test_objects, param_name, expected_result):
|
||||
"""Test boolean parameter checks in v2 objects."""
|
||||
v2_obj, _ = test_objects
|
||||
if expected_result:
|
||||
assert PropertyRules.is_parameter_value_true(v2_obj, param_name)
|
||||
else:
|
||||
assert PropertyRules.is_parameter_value_false(v2_obj, param_name)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name, expected_result",
|
||||
[
|
||||
("Room Bounding", True), # Test true values
|
||||
("top is attached", False), # Test false values
|
||||
("Top is Attached", False), # Case sensitivity test
|
||||
],
|
||||
)
|
||||
def test_v3_boolean_parameters(test_objects, param_name, expected_result):
|
||||
"""Test boolean parameter checks in v3 objects."""
|
||||
_, v3_obj = test_objects
|
||||
if expected_result:
|
||||
assert PropertyRules.is_parameter_value_true(v3_obj, param_name)
|
||||
else:
|
||||
assert PropertyRules.is_parameter_value_false(v3_obj, param_name)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"param_name, expected_value, expected_result",
|
||||
[
|
||||
# Test numeric value comparisons
|
||||
("WALL_ATTR_WIDTH_PARAM", 300, True),
|
||||
("WALL_ATTR_WIDTH_PARAM.value", 300, True),
|
||||
("baseLine.length", 5300.000000000002, True),
|
||||
# Test string value comparisons
|
||||
("STRUCTURAL_MATERIAL_PARAM.value", "Fc24", True),
|
||||
("ee1f33e1-5506-4a64-b87b-7b98d30aea52.value", "W30", True),
|
||||
# Test non-matches
|
||||
("WALL_ATTR_WIDTH_PARAM", 301, False),
|
||||
("nonexistent_param", "any_value", False),
|
||||
],
|
||||
)
|
||||
def test_v2_parameter_value_comparisons(v2_wall, param_name, expected_value, expected_result):
|
||||
"""Test value comparisons using v2 wall parameters."""
|
||||
assert PropertyRules.is_equal_value(v2_wall, param_name, expected_value) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"attribute, value, expected",
|
||||
[
|
||||
# Test numeric value comparisons
|
||||
("Type Parameters.Structure.Fc24 (0).thickness", 300, True),
|
||||
("location.length", 5300.000000000002, True),
|
||||
("location.length", 5300, True),
|
||||
# Test string value comparisons
|
||||
("Type Parameters.Text.符号.value", "W30", True),
|
||||
("Instance Parameters.Structural.Structural.value", "Yes", True),
|
||||
# Test non-matches
|
||||
("Type Parameters.Structure.Fc24 (0).thickness", 301, False),
|
||||
("nonexistent_param", "any_value", False),
|
||||
],
|
||||
)
|
||||
def test_v3_parameter_value_comparisons(v3_wall, attribute, value, expected):
|
||||
"""Test value comparisons using v3 wall parameters."""
|
||||
assert PropertyRules.is_equal_value(v3_wall, attribute, value) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"wall, attribute, value, expected",
|
||||
[
|
||||
# V2 wall tests
|
||||
("v2_wall", "WALL_ATTR_WIDTH_PARAM.value", 300, True),
|
||||
("v2_wall", "type", "W30(Fc24)", True),
|
||||
("v2_wall", "WALL_ATTR_WIDTH_PARAM.value", 300.0001, False),
|
||||
# V3 wall tests
|
||||
("v3_wall", "Type Parameters.Structure.Fc24 (0).thickness", 300, True),
|
||||
("v3_wall", "type", "W30(Fc24)", True),
|
||||
("v3_wall", "Type Parameters.Structure.Fc24 (0).thickness", 300.0001, False),
|
||||
("v3_wall", "location.length", 5300.000000000002, True),
|
||||
("v3_wall", "location.length", 5300, False),
|
||||
],
|
||||
)
|
||||
def test_identical_comparisons(request, wall, attribute, value, expected):
|
||||
"""Test identical value comparisons on both wall versions."""
|
||||
wall_instance = request.getfixturevalue(wall)
|
||||
assert PropertyRules.is_identical_value(wall_instance, attribute, value) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"wall, attribute, value",
|
||||
[
|
||||
# V2 wall tests
|
||||
("v2_wall", "WALL_ATTR_WIDTH_PARAM.value", 301),
|
||||
("v2_wall", "STRUCTURAL_MATERIAL_PARAM.value", "Fc25"),
|
||||
("v2_wall", "nonexistent_param", "any_value"),
|
||||
# V3 wall tests
|
||||
("v3_wall", "Type Parameters.Structure.Fc24 (0).thickness", 301),
|
||||
("v3_wall", "Type Parameters.Text.符号.value", "W31"),
|
||||
("v3_wall", "nonexistent_param", "any_value"),
|
||||
],
|
||||
)
|
||||
def test_not_equal_comparisons(request, wall, attribute, value):
|
||||
"""Test not equal comparisons on both wall versions."""
|
||||
wall_instance = request.getfixturevalue(wall)
|
||||
assert PropertyRules.is_not_equal_value(wall_instance, attribute, value)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"attribute, value, expected_equal, expected_identical",
|
||||
[
|
||||
# Test Yes/No conversion in equals (should convert)
|
||||
("Instance Parameters.Structural.Structural.value", True, True, False), # Yes vs True
|
||||
("Instance Parameters.Structural.Structural.value", "Yes", True, True), # Yes vs "Yes"
|
||||
("Instance Parameters.Structural.Structural.value", "yes", True, False), # Yes vs "yes"
|
||||
],
|
||||
)
|
||||
def test_boolean_conversions(v3_wall, attribute, value, expected_equal, expected_identical):
|
||||
"""Test conversion of Yes/No strings to boolean values."""
|
||||
assert PropertyRules.is_equal_value(v3_wall, attribute, value) == expected_equal
|
||||
assert PropertyRules.is_identical_value(v3_wall, attribute, value) == expected_identical
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"wall, attribute, expected_value",
|
||||
[
|
||||
# V2 wall tests
|
||||
("v2_wall", "WALL_ATTR_WIDTH_PARAM.value", "300"),
|
||||
("v2_wall", "baseLine.length", "5300.000000000002"),
|
||||
# V3 wall tests
|
||||
("v3_wall", "Type Parameters.Structure.Fc24 (0).thickness", "300"),
|
||||
("v3_wall", "location.length", "5300.000000000002"),
|
||||
],
|
||||
)
|
||||
def test_numeric_string_handling(wall, attribute, expected_value, request):
|
||||
"""Test handling of numeric strings in both wall versions."""
|
||||
wall_instance = request.getfixturevalue(wall) # Retrieve fixture dynamically
|
||||
assert PropertyRules.is_equal_value(wall_instance, attribute, expected_value)
|
||||
@@ -0,0 +1,33 @@
|
||||
import pandas as pd
|
||||
import pytest
|
||||
|
||||
from src.rule_processor import SeverityLevel, get_severity
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"input_severity, expected_enum",
|
||||
[
|
||||
("INFO", SeverityLevel.INFO),
|
||||
("info", SeverityLevel.INFO),
|
||||
("Info", SeverityLevel.INFO),
|
||||
("WARNING", SeverityLevel.WARNING),
|
||||
("warning", SeverityLevel.WARNING),
|
||||
("Warning", SeverityLevel.WARNING),
|
||||
("ERROR", SeverityLevel.ERROR),
|
||||
("error", SeverityLevel.ERROR),
|
||||
("Error", SeverityLevel.ERROR),
|
||||
("WARN", SeverityLevel.WARNING), # Invalid → Defaults to ERROR
|
||||
("warn", SeverityLevel.WARNING), # Invalid → Defaults to ERROR
|
||||
("Critical", SeverityLevel.ERROR), # Invalid → Defaults to ERROR
|
||||
("Severe", SeverityLevel.ERROR), # Invalid → Defaults to ERROR
|
||||
("", SeverityLevel.ERROR), # Empty string → Defaults to ERROR
|
||||
(None, SeverityLevel.ERROR), # None → Defaults to ERROR
|
||||
(1.0, SeverityLevel.ERROR), # None → Defaults to ERROR
|
||||
],
|
||||
)
|
||||
def test_severity_conversion(input_severity, expected_enum):
|
||||
"""Test various user inputs for severity and check expected outputs."""
|
||||
rule_info = pd.Series({"Report Severity": input_severity})
|
||||
severity = get_severity(rule_info)
|
||||
|
||||
assert severity == expected_enum, f"Failed for input: {input_severity}"
|
||||
@@ -0,0 +1,977 @@
|
||||
version = 1
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
version = "0.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.8.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "idna" },
|
||||
{ name = "sniffio" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a3/73/199a98fc2dae33535d6b8e8e6ec01f8c1d76c9adb096c6b7d64823038cde/anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a", size = 181126 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/46/eb/e7f063ad1fec6b3178a3cd82d1a3c4de82cccf283fc42746168188e1cdd5/anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a", size = 96041 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "appdirs"
|
||||
version = "1.4.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d7/d8/05696357e0311f5b5c316d7b95f46c669dd9c15aaeecbb48c7d0aeb88c40/appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", size = 13470 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/00/2344469e2084fb287c2e0b57b72910309874c3245463acd6cf5e3db69324/appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128", size = 9566 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "23.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e3/fc/f800d51204003fa8ae392c4e8278f256206e7a919b708eef054f5f4b650d/attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", size = 780820 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1", size = 60752 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backoff"
|
||||
version = "2.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/47/d7/5bbeb12c44d7c4f2fb5b56abce497eb5ed9f34d85701de869acedd602619/backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba", size = 17001 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/df/73/b6e24bd22e6720ca8ee9a85a0c4a2971af8497d8f3193fa05390cbd46e09/backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8", size = 15148 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "25.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "mypy-extensions" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pathspec" },
|
||||
{ name = "platformdirs" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/83/71/3fe4741df7adf015ad8dfa082dd36c94ca86bb21f25608eb247b4afb15b2/black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", size = 1650988 },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/f3/89aac8a83d73937ccd39bbe8fc6ac8860c11cfa0af5b1c96d081facac844/black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", size = 1453985 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/22/b99efca33f1f3a1d2552c714b1e1b5ae92efac6c43e790ad539a163d1754/black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", size = 1783816 },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/7e/a27c3ad3822b6f2e0e00d63d58ff6299a99a5b3aee69fa77cd4b0076b261/black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", size = 1440860 },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/87/0edf98916640efa5d0696e1abb0a8357b52e69e82322628f25bf14d263d1/black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", size = 1650673 },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/e5/f7bf17207cf87fa6e9b676576749c6b6ed0d70f179a3d812c997870291c3/black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", size = 1453190 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", size = 1782926 },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/64/94eb5f45dcb997d2082f097a3944cfc7fe87e071907f677e80788a2d7b7a/black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", size = 1442613 },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2025.1.31"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/9a/dd1e1cdceb841925b7798369a09279bd1cf183cef0f9ddf15a3a6502ee45/charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", size = 196105 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/8c/90bfabf8c4809ecb648f39794cf2a84ff2e7d2a6cf159fe68d9a26160467/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", size = 140404 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/8f/e410d57c721945ea3b4f1a04b74f70ce8fa800d393d72899f0a40526401f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", size = 150423 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/b8/e6825e25deb691ff98cf5c9072ee0605dc2acfca98af70c2d1b1bc75190d/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", size = 143184 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/a2/513f6cbe752421f16d969e32f3583762bfd583848b763913ddab8d9bfd4f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", size = 145268 },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/94/8a5277664f27c3c438546f3eb53b33f5b19568eb7424736bdc440a88a31f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616", size = 147601 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/5f/6d352c51ee763623a98e31194823518e09bfa48be2a7e8383cf691bbb3d0/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", size = 141098 },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/d4/f5704cb629ba5ab16d1d3d741396aec6dc3ca2b67757c45b0599bb010478/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", size = 149520 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/96/64120b1d02b81785f222b976c0fb79a35875457fa9bb40827678e54d1bc8/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", size = 152852 },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/c9/98e3732278a99f47d487fd3468bc60b882920cef29d1fa6ca460a1fdf4e6/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", size = 150488 },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/0e/9c8d4cb99c98c1007cc11eda969ebfe837bbbd0acdb4736d228ccaabcd22/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", size = 146192 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/21/2b6b5b860781a0b49427309cb8670785aa543fb2178de875b87b9cc97746/charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", size = 95550 },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/5b/1b390b03b1d16c7e382b561c5329f83cc06623916aab983e8ab9239c7d5c/charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", size = 102785 },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/94/ce8e6f63d18049672c76d07d119304e1e2d7c6098f0841b51c666e9f44a0/charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", size = 195698 },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/2e/dfdd9770664aae179a96561cc6952ff08f9a8cd09a908f259a9dfa063568/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", size = 140162 },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/4e/f646b9093cff8fc86f2d60af2de4dc17c759de9d554f130b140ea4738ca6/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", size = 150263 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/67/2937f8d548c3ef6e2f9aab0f6e21001056f692d43282b165e7c56023e6dd/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", size = 142966 },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/ed/b7f4f07de100bdb95c1756d3a4d17b90c1a3c53715c1a476f8738058e0fa/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", size = 144992 },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/2c/d49710a6dbcd3776265f4c923bb73ebe83933dfbaa841c5da850fe0fd20b/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", size = 147162 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/41/35ff1f9a6bd380303dea55e44c4933b4cc3c4850988927d4082ada230273/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", size = 140972 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/43/c6a0b685fe6910d08ba971f62cd9c3e862a85770395ba5d9cad4fede33ab/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", size = 149095 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/ff/a9a504662452e2d2878512115638966e75633519ec11f25fca3d2049a94a/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", size = 152668 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/71/189996b6d9a4b932564701628af5cee6716733e9165af1d5e1b285c530ed/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", size = 150073 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/93/946a86ce20790e11312c87c75ba68d5f6ad2208cfb52b2d6a2c32840d922/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", size = 145732 },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/e5/131d2fb1b0dddafc37be4f3a2fa79aa4c037368be9423061dccadfd90091/charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", size = 95391 },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/f2/4f9a69cc7712b9b5ad8fdb87039fd89abba997ad5cbe690d1835d40405b0/charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", size = 102702 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.1.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deprecated"
|
||||
version = "1.2.18"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "wrapt" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/98/97/06afe62762c9a8a86af0cfb7bfdab22a43ad17138b07af5b1a58442690a2/deprecated-1.2.18.tar.gz", hash = "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d", size = 2928744 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/c6/ac0b6c1e2d138f1002bcf799d330bd6d85084fece321e662a14223794041/Deprecated-1.2.18-py2.py3-none-any.whl", hash = "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec", size = 9998 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gql"
|
||||
version = "3.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
{ name = "backoff" },
|
||||
{ name = "graphql-core" },
|
||||
{ name = "yarl" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3d/85/feda24b33adcc6c8463a62a8e2ca2cc3425dc6d687388ff728ceae231204/gql-3.5.0.tar.gz", hash = "sha256:ccb9c5db543682b28f577069950488218ed65d4ac70bb03b6929aaadaf636de9", size = 179939 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/74/fb/01a200e1c31b79690427c8e983014e4220d2652b4372a46fe4598e1d7a8e/gql-3.5.0-py2.py3-none-any.whl", hash = "sha256:70dda5694a5b194a8441f077aa5fb70cc94e4ec08016117523f013680901ecb7", size = 74001 },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
requests = [
|
||||
{ name = "requests" },
|
||||
{ name = "requests-toolbelt" },
|
||||
]
|
||||
websockets = [
|
||||
{ name = "websockets" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "graphql-core"
|
||||
version = "3.2.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c4/16/7574029da84834349b60ed71614d66ca3afe46e9bf9c7b9562102acb7d4f/graphql_core-3.2.6.tar.gz", hash = "sha256:c08eec22f9e40f0bd61d805907e3b3b1b9a320bc606e23dc145eebca07c8fbab", size = 505353 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/4f/7297663840621022bc73c22d7d9d80dbc78b4db6297f764b545cd5dd462d/graphql_core-3.2.6-py3-none-any.whl", hash = "sha256:78b016718c161a6fb20a7d97bbf107f331cd1afe53e45566c59f776ed7f0b45f", size = 203416 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.14.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpx"
|
||||
version = "0.25.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
{ name = "certifi" },
|
||||
{ name = "httpcore" },
|
||||
{ name = "idna" },
|
||||
{ name = "sniffio" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8c/23/911d93a022979d3ea295f659fbe7edb07b3f4561a477e83b3a6d0e0c914e/httpx-0.25.2.tar.gz", hash = "sha256:8b8fcaa0c8ea7b05edd69a094e63a2094c4efcb48129fb757361bc423c0ad9e8", size = 123889 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/65/6940eeb21dcb2953778a6895281c179efd9100463ff08cb6232bb6480da7/httpx-0.25.2-py3-none-any.whl", hash = "sha256:a05d3d052d9b2dfce0e3896636467f8a5342fb2b902c819428e1ac65413ca118", size = 74980 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "2.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "levenshtein"
|
||||
version = "0.26.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "rapidfuzz" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/97/e6/79807d3b59a67dd78bb77072ca6a28d8db0935161fecf935e6c38c5f6825/levenshtein-0.26.1.tar.gz", hash = "sha256:0d19ba22330d50609b2349021ec3cf7d905c6fe21195a2d0d876a146e7ed2575", size = 374307 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/53/3685ee7fbe9b8eb4b82d8045255e59dd6943f94e8091697ef3808e7ecf63/levenshtein-0.26.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cc741ca406d3704dc331a69c04b061fc952509a069b79cab8287413f434684bd", size = 176447 },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/7f/7d6fe9b76bd030200f8f9b162f3de862d597804d292af292ec3ce9ae8bee/levenshtein-0.26.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:821ace3b4e1c2e02b43cf5dc61aac2ea43bdb39837ac890919c225a2c3f2fea4", size = 157589 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/d3/44539e952df93c5d88a95a0edff34af38e4f87330a76e8335bfe2c0f31bf/levenshtein-0.26.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92694c9396f55d4c91087efacf81297bef152893806fc54c289fc0254b45384", size = 153306 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/fe/21443c0c50824314e2d2ce7e1e9cd11d21b3643f3c14da156b15b4d399c7/levenshtein-0.26.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:51ba374de7a1797d04a14a4f0ad3602d2d71fef4206bb20a6baaa6b6a502da58", size = 184409 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/7b/c95066c64bb18628cf7488e0dd6aec2b7cbda307d93ba9ede68a21af2a7b/levenshtein-0.26.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f7aa5c3327dda4ef952769bacec09c09ff5bf426e07fdc94478c37955681885b", size = 193134 },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/22/5f9760b135bdefb8cf8d663890756136754db03214f929b73185dfa33f05/levenshtein-0.26.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33e2517e8d3c221de2d1183f400aed64211fcfc77077b291ed9f3bb64f141cdc", size = 162266 },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/50/6b1a5f3600caae40db0928f6775d7efc62c13dec2407d3d540bc4afdb72c/levenshtein-0.26.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9092b622765c7649dd1d8af0f43354723dd6f4e570ac079ffd90b41033957438", size = 246339 },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/eb/ede282fcb495570898b39a0d2f21bbc9be5587d604c93a518ece80f3e7dc/levenshtein-0.26.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fc16796c85d7d8b259881d59cc8b5e22e940901928c2ff6924b2c967924e8a0b", size = 1077937 },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/41/eebe1c4a75f592d9bdc3c2595418f083bcad747e0aec52a1a9ffaae93f5c/levenshtein-0.26.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4370733967f5994ceeed8dc211089bedd45832ee688cecea17bfd35a9eb22b9", size = 1330607 },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/8e/4d34b1857adfd69c2a72d84bca1b8538d4cfaaf6fddd8599573f4281a9d1/levenshtein-0.26.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3535ecfd88c9b283976b5bc61265855f59bba361881e92ed2b5367b6990c93fe", size = 1197505 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/7b/6afcda1b0a0622cedaa4f7a5b3507c2384a7358fc051ccf619e5d2453bf2/levenshtein-0.26.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:90236e93d98bdfd708883a6767826fafd976dac8af8fc4a0fb423d4fa08e1bf0", size = 1352832 },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/5e/0ed4e7b5c820b6bc40e2c391633292c3666400339042a3d306f0dc8fdcb4/levenshtein-0.26.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:04b7cabb82edf566b1579b3ed60aac0eec116655af75a3c551fee8754ffce2ea", size = 1135970 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/91/3ff1abacb58642749dfd130ad855370e01b9c7aeaa73801964361f6e355f/levenshtein-0.26.1-cp312-cp312-win32.whl", hash = "sha256:ae382af8c76f6d2a040c0d9ca978baf461702ceb3f79a0a3f6da8d596a484c5b", size = 87599 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/f9/727f3ba7843a3fb2a0f3db825358beea2a52bc96258874ee80cb2e5ecabb/levenshtein-0.26.1-cp312-cp312-win_amd64.whl", hash = "sha256:fd091209798cfdce53746f5769987b4108fe941c54fb2e058c016ffc47872918", size = 98809 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/f4/f87f19222d279dbac429b9bc7ccae271d900fd9c48a581b8bc180ba6cd09/levenshtein-0.26.1-cp312-cp312-win_arm64.whl", hash = "sha256:7e82f2ea44a81ad6b30d92a110e04cd3c8c7c6034b629aca30a3067fa174ae89", size = 88227 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/d6/b4b522b94d7b387c023d22944590befc0ac6b766ac6d197afd879ddd77fc/levenshtein-0.26.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:790374a9f5d2cbdb30ee780403a62e59bef51453ac020668c1564d1e43438f0e", size = 175836 },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/76/06d1e26a8e6d0de68ef4a157dd57f6b342413c03550309e4aa095a453b28/levenshtein-0.26.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7b05c0415c386d00efda83d48db9db68edd02878d6dbc6df01194f12062be1bb", size = 157036 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/23/21209a9e96b878aede3bea104533866762ba621e36fc344aa080db5feb02/levenshtein-0.26.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3114586032361722ddededf28401ce5baf1cf617f9f49fb86b8766a45a423ff", size = 153326 },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/38/9fc68685fffd8863b13864552eba8f3eb6a82a4dc558bf2c6553c2347d6c/levenshtein-0.26.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2532f8a13b68bf09f152d906f118a88da2063da22f44c90e904b142b0a53d534", size = 183693 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/82/ccd7bdd7d431329da025e649c63b731df44f8cf31b957e269ae1c1dc9a8e/levenshtein-0.26.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:219c30be6aa734bf927188d1208b7d78d202a3eb017b1c5f01ab2034d2d4ccca", size = 190581 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/c5/57f90b4aea1f89f853872b27a5a5dbce37b89ffeae42c02060b3e82038b2/levenshtein-0.26.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:397e245e77f87836308bd56305bba630010cd8298c34c4c44bd94990cdb3b7b1", size = 162446 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/da/df6acca738921f896ce2d178821be866b43a583f85e2d1de63a4f8f78080/levenshtein-0.26.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aeff6ea3576f72e26901544c6c55c72a7b79b9983b6f913cba0e9edbf2f87a97", size = 247123 },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/fb/f44a4c0d7784ccd32e4166714fea61e50f62b232162ae16332f45cb55ab2/levenshtein-0.26.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a19862e3539a697df722a08793994e334cd12791e8144851e8a1dee95a17ff63", size = 1077437 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/5e/d9b9e7daa13cc7e2184a3c2422bb847f05d354ce15ba113b20d83e9ab366/levenshtein-0.26.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:dc3b5a64f57c3c078d58b1e447f7d68cad7ae1b23abe689215d03fc434f8f176", size = 1330362 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/67/480d85bb516798014a6849be0225b246f35df4b54499c348c9c9e311f936/levenshtein-0.26.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bb6c7347424a91317c5e1b68041677e4c8ed3e7823b5bbaedb95bffb3c3497ea", size = 1198721 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/7d/889ff7d86903b6545665655627113d263c88c6d596c68fb09a640ee4f0a7/levenshtein-0.26.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b817376de4195a207cc0e4ca37754c0e1e1078c2a2d35a6ae502afde87212f9e", size = 1351820 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/29/cd42273150f08c200ed2d1879486d73502ee35265f162a77952f101d93a0/levenshtein-0.26.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7b50c3620ff47c9887debbb4c154aaaac3e46be7fc2e5789ee8dbe128bce6a17", size = 1135747 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/90/cbcfa3dd86023e82036662a19fec2fcb48782d3f9fa322d44dc898d95a5d/levenshtein-0.26.1-cp313-cp313-win32.whl", hash = "sha256:9fb859da90262eb474c190b3ca1e61dee83add022c676520f5c05fdd60df902a", size = 87318 },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/73/372edebc79fd09a8b2382cf1244d279ada5b795124f1e1c4fc73d9fbb00f/levenshtein-0.26.1-cp313-cp313-win_amd64.whl", hash = "sha256:8adcc90e3a5bfb0a463581d85e599d950fe3c2938ac6247b29388b64997f6e2d", size = 98418 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/6d/f0160ea5a7bb7a62b3b3d56e9fc5024b440cb59555a90be2347abf2e7888/levenshtein-0.26.1-cp313-cp313-win_arm64.whl", hash = "sha256:c2599407e029865dc66d210b8804c7768cbdbf60f061d993bb488d5242b0b73e", size = 87792 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "more-itertools"
|
||||
version = "10.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/88/3b/7fa1fe835e2e93fd6d7b52b2f95ae810cf5ba133e1845f726f5a992d62c2/more-itertools-10.6.0.tar.gz", hash = "sha256:2cd7fad1009c31cc9fb6a035108509e6547547a7a738374f10bd49a09eb3ee3b", size = 125009 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/23/62/0fe302c6d1be1c777cab0616e6302478251dfbf9055ad426f5d0def75c89/more_itertools-10.6.0-py3-none-any.whl", hash = "sha256:6eb054cb4b6db1473f6e15fcc676a08e4732548acd47c708f0e179c2c7c01e89", size = 63038 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multidict"
|
||||
version = "6.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d6/be/504b89a5e9ca731cd47487e91c469064f8ae5af93b7259758dcfc2b9c848/multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", size = 64002 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/16/92057c74ba3b96d5e211b553895cd6dc7cc4d1e43d9ab8fafc727681ef71/multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", size = 48713 },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/3d/37d1b8893ae79716179540b89fc6a0ee56b4a65fcc0d63535c6f5d96f217/multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", size = 29516 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/12/adb6b3200c363062f805275b4c1e656be2b3681aada66c80129932ff0bae/multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", size = 29557 },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/e9/604bb05e6e5bce1e6a5cf80a474e0f072e80d8ac105f1b994a53e0b28c42/multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", size = 130170 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/13/9efa50801785eccbf7086b3c83b71a4fb501a4d43549c2f2f80b8787d69f/multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", size = 134836 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/0f/93808b765192780d117814a6dfcc2e75de6dcc610009ad408b8814dca3ba/multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", size = 133475 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/c8/529101d7176fe7dfe1d99604e48d69c5dfdcadb4f06561f465c8ef12b4df/multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", size = 131049 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/0c/fc85b439014d5a58063e19c3a158a889deec399d47b5269a0f3b6a2e28bc/multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", size = 120370 },
|
||||
{ url = "https://files.pythonhosted.org/packages/db/46/d4416eb20176492d2258fbd47b4abe729ff3b6e9c829ea4236f93c865089/multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", size = 125178 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/46/73697ad7ec521df7de5531a32780bbfd908ded0643cbe457f981a701457c/multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", size = 119567 },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/ed/51f060e2cb0e7635329fa6ff930aa5cffa17f4c7f5c6c3ddc3500708e2f2/multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", size = 129822 },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/9e/ee7d1954b1331da3eddea0c4e08d9142da5f14b1321c7301f5014f49d492/multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", size = 128656 },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/00/8538f11e3356b5d95fa4b024aa566cde7a38aa7a5f08f4912b32a037c5dc/multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", size = 125360 },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/05/5d334c1f2462d43fec2363cd00b1c44c93a78c3925d952e9a71caf662e96/multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", size = 26382 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/bf/f332a13486b1ed0496d624bcc7e8357bb8053823e8cd4b9a18edc1d97e73/multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", size = 28529 },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/67/1c7c0f39fe069aa4e5d794f323be24bf4d33d62d2a348acdb7991f8f30db/multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", size = 48771 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/25/c186ee7b212bdf0df2519eacfb1981a017bda34392c67542c274651daf23/multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", size = 29533 },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/5e/04575fd837e0958e324ca035b339cea174554f6f641d3fb2b4f2e7ff44a2/multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", size = 29595 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/b2/e56388f86663810c07cfe4a3c3d87227f3811eeb2d08450b9e5d19d78876/multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", size = 130094 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/ee/30ae9b4186a644d284543d55d491fbd4239b015d36b23fea43b4c94f7052/multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", size = 134876 },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/c7/70461c13ba8ce3c779503c70ec9d0345ae84de04521c1f45a04d5f48943d/multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", size = 133500 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/9f/002af221253f10f99959561123fae676148dd730e2daa2cd053846a58507/multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", size = 131099 },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/42/d1c7a7301d52af79d88548a97e297f9d99c961ad76bbe6f67442bb77f097/multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", size = 120403 },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/f3/471985c2c7ac707547553e8f37cff5158030d36bdec4414cb825fbaa5327/multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", size = 125348 },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/2c/e6df05c77e0e433c214ec1d21ddd203d9a4770a1f2866a8ca40a545869a0/multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", size = 119673 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/cd/bc8608fff06239c9fb333f9db7743a1b2eafe98c2666c9a196e867a3a0a4/multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", size = 129927 },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/8e/281b69b7bc84fc963a44dc6e0bbcc7150e517b91df368a27834299a526ac/multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", size = 128711 },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/a4/63e7cd38ed29dd9f1881d5119f272c898ca92536cdb53ffe0843197f6c85/multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", size = 125519 },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/e0/4f5855037a72cd8a7a2f60a3952d9aa45feedb37ae7831642102604e8a37/multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", size = 26426 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/a5/17ee3a4db1e310b7405f5d25834460073a8ccd86198ce044dfaf69eac073/multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", size = 28531 },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/b7/b9e70fde2c0f0c9af4cc5277782a89b66d35948ea3369ec9f598358c3ac5/multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", size = 10051 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mypy"
|
||||
version = "1.15.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mypy-extensions" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717 }
|
||||
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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592 },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348 },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648 },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "1.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.2.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ec/d0/c12ddfd3a02274be06ffc71f3efc6d0e457b0409c4481596881e748cb264/numpy-2.2.2.tar.gz", hash = "sha256:ed6906f61834d687738d25988ae117683705636936cc605be0bb208b23df4d8f", size = 20233295 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/e6/847d15770ab7a01e807bdfcd4ead5bdae57c0092b7dc83878171b6af97bb/numpy-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ac9bea18d6d58a995fac1b2cb4488e17eceeac413af014b1dd26170b766d8467", size = 20912636 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/af/f83580891577b13bd7e261416120e036d0d8fb508c8a43a73e38928b794b/numpy-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23ae9f0c2d889b7b2d88a3791f6c09e2ef827c2446f1c4a3e3e76328ee4afd9a", size = 14098403 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/86/d019fb60a9d0f1d4cf04b014fe88a9135090adfadcc31c1fadbb071d7fa7/numpy-2.2.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3074634ea4d6df66be04f6728ee1d173cfded75d002c75fac79503a880bf3825", size = 5128938 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/1b/50985edb6f1ec495a1c36452e860476f5b7ecdc3fc59ea89ccad3c4926c5/numpy-2.2.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:8ec0636d3f7d68520afc6ac2dc4b8341ddb725039de042faf0e311599f54eb37", size = 6661937 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/1b/17efd94cad1b9d605c3f8907fb06bcffc4ce4d1d14d46b95316cccccf2b9/numpy-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ffbb1acd69fdf8e89dd60ef6182ca90a743620957afb7066385a7bbe88dc748", size = 14049518 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/73/65d2f0b698df1731e851e3295eb29a5ab8aa06f763f7e4188647a809578d/numpy-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0349b025e15ea9d05c3d63f9657707a4e1d471128a3b1d876c095f328f8ff7f0", size = 16099146 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/69/308f55c0e19d4b5057b5df286c5433822e3c8039ede06d4051d96f1c2c4e/numpy-2.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:463247edcee4a5537841d5350bc87fe8e92d7dd0e8c71c995d2c6eecb8208278", size = 15246336 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/d8/d8d333ad0d8518d077a21aeea7b7c826eff766a2b1ce1194dea95ca0bacf/numpy-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9dd47ff0cb2a656ad69c38da850df3454da88ee9a6fde0ba79acceee0e79daba", size = 17863507 },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/6e/0b84ad3103ffc16d6673e63b5acbe7901b2af96c2837174c6318c98e27ab/numpy-2.2.2-cp312-cp312-win32.whl", hash = "sha256:4525b88c11906d5ab1b0ec1f290996c0020dd318af8b49acaa46f198b1ffc283", size = 6276491 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/84/7f801a42a67b9772a883223a0a1e12069a14626c81a732bd70aac57aebc1/numpy-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:5acea83b801e98541619af398cc0109ff48016955cc0818f478ee9ef1c5c3dcb", size = 12616372 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/fe/df5624001f4f5c3e0b78e9017bfab7fdc18a8d3b3d3161da3d64924dd659/numpy-2.2.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b208cfd4f5fe34e1535c08983a1a6803fdbc7a1e86cf13dd0c61de0b51a0aadc", size = 20899188 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/80/d349c3b5ed66bd3cb0214be60c27e32b90a506946857b866838adbe84040/numpy-2.2.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d0bbe7dd86dca64854f4b6ce2ea5c60b51e36dfd597300057cf473d3615f2369", size = 14113972 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/50/949ec9cbb28c4b751edfa64503f0913cbfa8d795b4a251e7980f13a8a655/numpy-2.2.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:22ea3bb552ade325530e72a0c557cdf2dea8914d3a5e1fecf58fa5dbcc6f43cd", size = 5114294 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/f3/399c15629d5a0c68ef2aa7621d430b2be22034f01dd7f3c65a9c9666c445/numpy-2.2.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:128c41c085cab8a85dc29e66ed88c05613dccf6bc28b3866cd16050a2f5448be", size = 6648426 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/03/c72474c13772e30e1bc2e558cdffd9123c7872b731263d5648b5c49dd459/numpy-2.2.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:250c16b277e3b809ac20d1f590716597481061b514223c7badb7a0f9993c7f84", size = 14045990 },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/9c/96a9ab62274ffafb023f8ee08c88d3d31ee74ca58869f859db6845494fa6/numpy-2.2.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0c8854b09bc4de7b041148d8550d3bd712b5c21ff6a8ed308085f190235d7ff", size = 16096614 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/34/cd0a735534c29bec7093544b3a509febc9b0df77718a9b41ffb0809c9f46/numpy-2.2.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b6fb9c32a91ec32a689ec6410def76443e3c750e7cfc3fb2206b985ffb2b85f0", size = 15242123 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/6d/541717a554a8f56fa75e91886d9b79ade2e595918690eb5d0d3dbd3accb9/numpy-2.2.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:57b4012e04cc12b78590a334907e01b3a85efb2107df2b8733ff1ed05fce71de", size = 17859160 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/a5/fbf1f2b54adab31510728edd06a05c1b30839f37cf8c9747cb85831aaf1b/numpy-2.2.2-cp313-cp313-win32.whl", hash = "sha256:4dbd80e453bd34bd003b16bd802fac70ad76bd463f81f0c518d1245b1c55e3d9", size = 6273337 },
|
||||
{ url = "https://files.pythonhosted.org/packages/56/e5/01106b9291ef1d680f82bc47d0c5b5e26dfed15b0754928e8f856c82c881/numpy-2.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:5a8c863ceacae696aff37d1fd636121f1a512117652e5dfb86031c8d84836369", size = 12609010 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/30/f23d9876de0f08dceb707c4dcf7f8dd7588266745029debb12a3cdd40be6/numpy-2.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b3482cb7b3325faa5f6bc179649406058253d91ceda359c104dac0ad320e1391", size = 20924451 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/ec/6ea85b2da9d5dfa1dbb4cb3c76587fc8ddcae580cb1262303ab21c0926c4/numpy-2.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9491100aba630910489c1d0158034e1c9a6546f0b1340f716d522dc103788e39", size = 14122390 },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/05/bfbdf490414a7dbaf65b10c78bc243f312c4553234b6d91c94eb7c4b53c2/numpy-2.2.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:41184c416143defa34cc8eb9d070b0a5ba4f13a0fa96a709e20584638254b317", size = 5156590 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/ec/fe2e91b2642b9d6544518388a441bcd65c904cea38d9ff998e2e8ebf808e/numpy-2.2.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7dca87ca328f5ea7dafc907c5ec100d187911f94825f8700caac0b3f4c384b49", size = 6671958 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/6f/6531a78e182f194d33ee17e59d67d03d0d5a1ce7f6be7343787828d1bd4a/numpy-2.2.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bc61b307655d1a7f9f4b043628b9f2b721e80839914ede634e3d485913e1fb2", size = 14019950 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/fb/13c58591d0b6294a08cc40fcc6b9552d239d773d520858ae27f39997f2ae/numpy-2.2.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fad446ad0bc886855ddf5909cbf8cb5d0faa637aaa6277fb4b19ade134ab3c7", size = 16079759 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/f2/f2f8edd62abb4b289f65a7f6d1f3650273af00b91b7267a2431be7f1aec6/numpy-2.2.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:149d1113ac15005652e8d0d3f6fd599360e1a708a4f98e43c9c77834a28238cb", size = 15226139 },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/29/14a177f1a90b8ad8a592ca32124ac06af5eff32889874e53a308f850290f/numpy-2.2.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:106397dbbb1896f99e044efc90360d098b3335060375c26aa89c0d8a97c5f648", size = 17856316 },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/03/242ae8d7b97f4e0e4ab8dd51231465fb23ed5e802680d629149722e3faf1/numpy-2.2.2-cp313-cp313t-win32.whl", hash = "sha256:0eec19f8af947a61e968d5429f0bd92fec46d92b0008d0a6685b40d6adf8a4f4", size = 6329134 },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/94/cd9e9b04012c015cb6320ab3bf43bc615e248dddfeb163728e800a5d96f0/numpy-2.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:97b974d3ba0fb4612b77ed35d7627490e8e3dff56ab41454d9e8b23448940576", size = 12696208 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "24.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pandas"
|
||||
version = "2.2.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
{ name = "python-dateutil" },
|
||||
{ name = "pytz" },
|
||||
{ name = "tzdata" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/17/a3/fb2734118db0af37ea7433f57f722c0a56687e14b14690edff0cdb4b7e58/pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", size = 12529893 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/0c/ad295fd74bfac85358fd579e271cded3ac969de81f62dd0142c426b9da91/pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4", size = 11363475 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/2a/4bba3f03f7d07207481fed47f5b35f556c7441acddc368ec43d6643c5777/pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3", size = 15188645 },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/f8/d8fddee9ed0d0c0f4a2132c1dfcf0e3e53265055da8df952a53e7eaf178c/pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319", size = 12739445 },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/e8/45a05d9c39d2cea61ab175dbe6a2de1d05b679e8de2011da4ee190d7e748/pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8", size = 16359235 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/99/617d07a6a5e429ff90c90da64d428516605a1ec7d7bea494235e1c3882de/pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a", size = 14056756 },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/d4/1244ab8edf173a10fd601f7e13b9566c1b525c4f365d6bee918e68381889/pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", size = 11504248 },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/22/3b8f4e0ed70644e85cfdcd57454686b9057c6c38d2f74fe4b8bc2527214a/pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", size = 12477643 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/93/b3f5d1838500e22c8d793625da672f3eec046b1a99257666c94446969282/pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28", size = 11281573 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/94/6c79b07f0e5aab1dcfa35a75f4817f5c4f677931d4234afcd75f0e6a66ca/pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0", size = 15196085 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/31/aa8da88ca0eadbabd0a639788a6da13bb2ff6edbbb9f29aa786450a30a91/pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", size = 12711809 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/7c/c6dbdb0cb2a4344cacfb8de1c5808ca885b2e4dcfde8008266608f9372af/pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659", size = 16356316 },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/b7/8b757e7d92023b832869fa8881a992696a0bfe2e26f72c9ae9f255988d42/pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", size = 14022055 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/bc/4b18e2b8c002572c5a441a64826252ce5da2aa738855747247a971988043/pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", size = 11481175 },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/a3/a5d88146815e972d40d19247b2c162e88213ef51c7c25993942c39dbf41d/pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", size = 12615650 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/8c/f0fd18f6140ddafc0c24122c8a964e48294acc579d47def376fef12bcb4a/pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18", size = 11290177 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/f9/e995754eab9c0f14c6777401f7eece0943840b7a9fc932221c19d1abee9f/pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2", size = 14651526 },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/b0/98d6ae2e1abac4f35230aa756005e8654649d305df9a28b16b9ae4353bff/pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", size = 11871013 },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/57/0f72a10f9db6a4628744c8e8f0df4e6e21de01212c7c981d31e50ffc8328/pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d", size = 15711620 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/5f/b38085618b950b79d2d9164a711c52b10aefc0ae6833b96f626b7021b2ed/pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", size = 13098436 },
|
||||
]
|
||||
|
||||
[[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 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "4.3.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "propcache"
|
||||
version = "0.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/20/c8/2a13f78d82211490855b2fb303b6721348d0787fdd9a12ac46d99d3acde1/propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64", size = 41735 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/28/1d205fe49be8b1b4df4c50024e62480a442b1a7b818e734308bb0d17e7fb/propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a", size = 79588 },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/ee/fc4d893f8d81cd4971affef2a6cb542b36617cd1d8ce56b406112cb80bf7/propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0", size = 45825 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/de/bbe712f94d088da1d237c35d735f675e494a816fd6f54e9db2f61ef4d03f/propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d", size = 45357 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/14/7ae06a6cf2a2f1cb382586d5a99efe66b0b3d0c6f9ac2f759e6f7af9d7cf/propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4", size = 241869 },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/59/227a78be960b54a41124e639e2c39e8807ac0c751c735a900e21315f8c2b/propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d", size = 247884 },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/58/f62b4ffaedf88dc1b17f04d57d8536601e4e030feb26617228ef930c3279/propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5", size = 248486 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/07/ebe102777a830bca91bbb93e3479cd34c2ca5d0361b83be9dbd93104865e/propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24", size = 243649 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/bc/4f7aba7f08f520376c4bb6a20b9a981a581b7f2e385fa0ec9f789bb2d362/propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff", size = 229103 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/d5/04ac9cd4e51a57a96f78795e03c5a0ddb8f23ec098b86f92de028d7f2a6b/propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f", size = 226607 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/f0/24060d959ea41d7a7cc7fdbf68b31852331aabda914a0c63bdb0e22e96d6/propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec", size = 221153 },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/a7/3ac76045a077b3e4de4859a0753010765e45749bdf53bd02bc4d372da1a0/propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348", size = 222151 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/af/5e29da6f80cebab3f5a4dcd2a3240e7f56f2c4abf51cbfcc99be34e17f0b/propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6", size = 233812 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/89/ebe3ad52642cc5509eaa453e9f4b94b374d81bae3265c59d5c2d98efa1b4/propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6", size = 238829 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/2f/6b32f273fa02e978b7577159eae7471b3cfb88b48563b1c2578b2d7ca0bb/propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518", size = 230704 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/2e/f40ae6ff5624a5f77edd7b8359b208b5455ea113f68309e2b00a2e1426b6/propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246", size = 40050 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/77/a92c3ef994e47180862b9d7d11e37624fb1c00a16d61faf55115d970628b/propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1", size = 44117 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/2a/329e0547cf2def8857157f9477669043e75524cc3e6251cef332b3ff256f/propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc", size = 77002 },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/2d/c4df5415e2382f840dc2ecbca0eeb2293024bc28e57a80392f2012b4708c/propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9", size = 44639 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/5a/21aaa4ea2f326edaa4e240959ac8b8386ea31dedfdaa636a3544d9e7a408/propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439", size = 44049 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/3e/021b6cd86c0acc90d74784ccbb66808b0bd36067a1bf3e2deb0f3845f618/propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536", size = 224819 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/57/c2fdeed1b3b8918b1770a133ba5c43ad3d78e18285b0c06364861ef5cc38/propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629", size = 229625 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/81/70d4ff57bf2877b5780b466471bebf5892f851a7e2ca0ae7ffd728220281/propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b", size = 232934 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/b9/bb51ea95d73b3fb4100cb95adbd4e1acaf2cbb1fd1083f5468eeb4a099a8/propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052", size = 227361 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/20/3c6d696cd6fd70b29445960cc803b1851a1131e7a2e4ee261ee48e002bcd/propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce", size = 213904 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/cb/1593bfc5ac6d40c010fa823f128056d6bc25b667f5393781e37d62f12005/propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d", size = 212632 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/5c/e95617e222be14a34c709442a0ec179f3207f8a2b900273720501a70ec5e/propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce", size = 207897 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/3b/56c5ab3dc00f6375fbcdeefdede5adf9bee94f1fab04adc8db118f0f9e25/propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95", size = 208118 },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/25/d7ef738323fbc6ebcbce33eb2a19c5e07a89a3df2fded206065bd5e868a9/propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf", size = 217851 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/77/763e6cef1852cf1ba740590364ec50309b89d1c818e3256d3929eb92fabf/propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f", size = 222630 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/e9/0f86be33602089c701696fbed8d8c4c07b6ee9605c5b7536fd27ed540c5b/propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30", size = 216269 },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/02/5ac83217d522394b6a2e81a2e888167e7ca629ef6569a3f09852d6dcb01a/propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6", size = 39472 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/33/d6f5420252a36034bc8a3a01171bc55b4bff5df50d1c63d9caa50693662f/propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1", size = 43363 },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/b6/c5319caea262f4821995dca2107483b94a3345d4607ad797c76cb9c36bcc/propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54", size = 11818 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.10.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
{ name = "pydantic-core" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b7/ae/d5220c5c52b158b1de7ca89fc5edb72f304a70a4c540c84c8844bf4008de/pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236", size = 761681 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.27.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 }
|
||||
wheels = [
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092 },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709 },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/1c/b6f402cfc18ec0024120602bdbcebc7bdd5b856528c013bd4d13865ca473/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", size = 1868888 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/7b/8cb75b66ac37bc2975a3b7de99f3c6f355fcc4d89820b61dffa8f1e81677/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", size = 2037738 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/f1/786d8fe78970a06f61df22cba58e365ce304bf9b9f46cc71c8c424e0c334/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", size = 2685138 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/74/d12b2cd841d8724dc8ffb13fc5cef86566a53ed358103150209ecd5d1999/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", size = 1997025 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/6e/940bcd631bc4d9a06c9539b51f070b66e8f370ed0933f392db6ff350d873/pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", size = 2004633 },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/cc/a46b34f1708d82498c227d5d80ce615b2dd502ddcfd8376fc14a36655af1/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", size = 1999404 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/2d/c365cfa930ed23bc58c41463bae347d1005537dc8db79e998af8ba28d35e/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", size = 2130130 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/d7/eb64d015c350b7cdb371145b54d96c919d4db516817f31cd1c650cae3b21/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", size = 2157946 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-settings"
|
||||
version = "2.7.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "python-dotenv" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/73/7b/c58a586cd7d9ac66d2ee4ba60ca2d241fa837c02bca9bea80a9a8c3d22a9/pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93", size = 79920 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/46/93416fdae86d40879714f72956ac14df9c7b76f7d41a4d68aa9f71a0028b/pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd", size = 29718 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "8.3.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "iniconfig" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pluggy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-assertcount"
|
||||
version = "1.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/84/9f/e6eee30903096887e2fa359163a4ed0969dfd81b301400f5c46fe3e99a41/pytest-assertcount-1.0.0.tar.gz", hash = "sha256:e8271a284e337f89a28789790e68faa18ab8d5e1ca9aad5bd439a672b836a76b", size = 2652 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/61/8d/4415383d305c7d79271e8e349dedc62d7a2a00f997d894b12a18b3ec487a/pytest_assertcount-1.0.0-py3-none-any.whl", hash = "sha256:08a2945248f666787ee1413736fff91875e355aee23bf03900d1438bd4bf81ec", size = 3287 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
version = "2.9.0.post0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "six" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.0.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-levenshtein"
|
||||
version = "0.26.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "levenshtein" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/31/72/58d77cb80b3c130d94f53a8204ffad9acfddb925b2fb5818ff9af0b3c832/python_levenshtein-0.26.1.tar.gz", hash = "sha256:24ba578e28058ebb4afa2700057e1678d7adf27e43cd1f17700c09a9009d5d3a", size = 12276 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/d7/03e0453719ed89724664f781f0255949408118093dbf77a2aa2a1198b38e/python_Levenshtein-0.26.1-py3-none-any.whl", hash = "sha256:8ef5e529dd640fb00f05ee62d998d2ee862f19566b641ace775d5ae16167b2ef", size = 9426 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2025.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5f/57/df1c9157c8d5a05117e455d66fd7cf6dbc46974f832b1058ed4856785d8a/pytz-2025.1.tar.gz", hash = "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e", size = 319617 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/38/ac33370d784287baa1c3d538978b5e2ea064d4c1b93ffbd12826c190dd10/pytz-2025.1-py2.py3-none-any.whl", hash = "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57", size = 507930 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rapidfuzz"
|
||||
version = "3.12.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c9/df/c300ead8c2962f54ad87872e6372a6836f0181a7f20b433c987bd106bfce/rapidfuzz-3.12.1.tar.gz", hash = "sha256:6a98bbca18b4a37adddf2d8201856441c26e9c981d8895491b5bc857b5f780eb", size = 57907552 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/20/6049061411df87f2814a2677db0f15e673bb9795bfeff57dc9708121374d/rapidfuzz-3.12.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f6235b57ae3faa3f85cb3f90c9fee49b21bd671b76e90fc99e8ca2bdf0b5e4a3", size = 1944328 },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/73/199383c4c21ae3b4b6ea6951c6896ab38e9dc96942462fa01f9d3fb047da/rapidfuzz-3.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:af4585e5812632c357fee5ab781c29f00cd06bea58f8882ff244cc4906ba6c9e", size = 1430203 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/51/77ebaeec5413c53c3e6d8b800f2b979551adbed7b5efa094d1fad5c5b751/rapidfuzz-3.12.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5942dc4460e5030c5f9e1d4c9383de2f3564a2503fe25e13e89021bcbfea2f44", size = 1403662 },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/06/1fadd2704db0a7eecf78de812e2f4fab37c4ae105a5ce4578c9fc66bb0c5/rapidfuzz-3.12.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b31ab59e1a0df5afc21f3109b6cfd77b34040dbf54f1bad3989f885cfae1e60", size = 5555849 },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/45/da128c3952bd09cef2935df58db5273fc4eb67f04a69dcbf9e25af9e4432/rapidfuzz-3.12.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97c885a7a480b21164f57a706418c9bbc9a496ec6da087e554424358cadde445", size = 1655273 },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/ee/bf2b2a95b5af4e6d36105dd9284dc5335fdcc7f0326186d4ab0b5aa4721e/rapidfuzz-3.12.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d844c0587d969ce36fbf4b7cbf0860380ffeafc9ac5e17a7cbe8abf528d07bb", size = 1678041 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/4f/36ea4d7f306a23e30ea1a6cabf545d2a794e8ca9603d2ee48384314cde3a/rapidfuzz-3.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93c95dce8917bf428064c64024de43ffd34ec5949dd4425780c72bd41f9d969", size = 3137099 },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/ef/48195d94b018e7340a60c9a642ab0081bf9dc64fb0bd01dfafd93757d2a2/rapidfuzz-3.12.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:834f6113d538af358f39296604a1953e55f8eeffc20cb4caf82250edbb8bf679", size = 2307388 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/cd/53d5dbc4791df3e1a8640fc4ad5e328ebb040cc01c10c66f891aa6b83ed5/rapidfuzz-3.12.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a940aa71a7f37d7f0daac186066bf6668d4d3b7e7ef464cb50bc7ba89eae1f51", size = 6906504 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/99/c27e7db1d49cfd77780cb73978f81092682c2bdbc6de75363df6aaa086d6/rapidfuzz-3.12.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ec9eaf73501c9a7de2c6938cb3050392e2ee0c5ca3921482acf01476b85a7226", size = 2684757 },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/8c/2474d6282fdd4aae386a6b16272e544a3f9ea2dcdcf2f3b0b286549bc3d5/rapidfuzz-3.12.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3c5ec360694ac14bfaeb6aea95737cf1a6cf805b5fe8ea7fd28814706c7fa838", size = 3229940 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/27/95d5a8ebe5fcc5462dd0fd265553c8a2ec4a770e079afabcff978442bcb3/rapidfuzz-3.12.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6b5e176524653ac46f1802bdd273a4b44a5f8d0054ed5013a8e8a4b72f254599", size = 4148489 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/2c/e509bc24b6514de4d6f2c5480201568e1d9a3c7e4692cc969ef899227ba5/rapidfuzz-3.12.1-cp312-cp312-win32.whl", hash = "sha256:6f463c6f1c42ec90e45d12a6379e18eddd5cdf74138804d8215619b6f4d31cea", size = 1834110 },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/ab/900b8d57090b30269258e3ae31752ec9c31042cd58660fcc96d50728487d/rapidfuzz-3.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:b894fa2b30cd6498a29e5c470cb01c6ea898540b7e048a0342775a5000531334", size = 1612461 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/df/3f51a0a277185b3f28b2941e071aff62908a6b81527efc67a643bcb59fb8/rapidfuzz-3.12.1-cp312-cp312-win_arm64.whl", hash = "sha256:43bb17056c5d1332f517b888c4e57846c4b5f936ed304917eeb5c9ac85d940d4", size = 864251 },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/d2/ceebc2446d1f3d3f2cae2597116982e50c2eed9ff2f5a322a51736981405/rapidfuzz-3.12.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:97f824c15bc6933a31d6e3cbfa90188ba0e5043cf2b6dd342c2b90ee8b3fd47c", size = 1936794 },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/38/37f7ea800aa959a4f7a63477fc9ad7f3cd024e46bfadce5d23420af6c7e5/rapidfuzz-3.12.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a973b3f5cabf931029a3ae4a0f72e3222e53d412ea85fc37ddc49e1774f00fbf", size = 1424155 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/14/409d0aa84430451488177fcc5cba8babcdf5a45cee772a2a265b9b5f4c7e/rapidfuzz-3.12.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df7880e012228722dec1be02b9ef3898ed023388b8a24d6fa8213d7581932510", size = 1398013 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/2c/601e3ad0bbe61e65f99e72c8cefed9713606cf4b297cc4c3876051db7722/rapidfuzz-3.12.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c78582f50e75e6c2bc38c791ed291cb89cf26a3148c47860c1a04d6e5379c8e", size = 5526157 },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/ce/deb7b00ce6e06713fc4df81336402b7fa062f2393c8a47401c228ee906c3/rapidfuzz-3.12.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2d7d9e6a04d8344b0198c96394c28874086888d0a2b2f605f30d1b27b9377b7d", size = 1648446 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/6f/2b8eae1748a022290815999594b438dbc1e072c38c76178ea996920a6253/rapidfuzz-3.12.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5620001fd4d6644a2f56880388179cc8f3767670f0670160fcb97c3b46c828af", size = 1676038 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/6c/5c831197aca7148ed85c86bbe940e66073fea0fa97f30307bb5850ed8858/rapidfuzz-3.12.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0666ab4c52e500af7ba5cc17389f5d15c0cdad06412c80312088519fdc25686d", size = 3114137 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/f2/d66ac185eeb0ee3fc0fe208dab1e72feece2c883bc0ab2097570a8159a7b/rapidfuzz-3.12.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:27b4d440fa50b50c515a91a01ee17e8ede719dca06eef4c0cccf1a111a4cfad3", size = 2305754 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/61/9bf74d7ea9bebc7a1bed707591617bba7901fce414d346a7c5532ef02dbd/rapidfuzz-3.12.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83dccfd5a754f2a0e8555b23dde31f0f7920601bfa807aa76829391ea81e7c67", size = 6901746 },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/73/d8dddf73e168f723ef21272e8abb7d34d9244da395eb90ed5a617f870678/rapidfuzz-3.12.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b572b634740e047c53743ed27a1bb3b4f93cf4abbac258cd7af377b2c4a9ba5b", size = 2673947 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/31/3c473cea7d76af162819a5b84f5e7bdcf53b9e19568fc37cfbdab4f4512a/rapidfuzz-3.12.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7fa7b81fb52902d5f78dac42b3d6c835a6633b01ddf9b202a3ca8443be4b2d6a", size = 3233070 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/b7/73227dcbf8586f0ca4a77be2720311367288e2db142ae00a1404f42e712d/rapidfuzz-3.12.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b1d4fbff980cb6baef4ee675963c081f7b5d6580a105d6a4962b20f1f880e1fb", size = 4146828 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/c8/fea749c662e268d348a77501995b51ac95cdc3624f3f95ba261f30b000ff/rapidfuzz-3.12.1-cp313-cp313-win32.whl", hash = "sha256:3fe8da12ea77271097b303fa7624cfaf5afd90261002314e3b0047d36f4afd8d", size = 1831797 },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/18/11052be5984d9972eb04a52e2931e19e95b2e87731d179f60b79707b7efd/rapidfuzz-3.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:6f7e92fc7d2a7f02e1e01fe4f539324dfab80f27cb70a30dd63a95445566946b", size = 1610169 },
|
||||
{ url = "https://files.pythonhosted.org/packages/db/c1/66427c618f000298edbd24e46dd3dd2d3fa441a602701ba6a260d41dd62b/rapidfuzz-3.12.1-cp313-cp313-win_arm64.whl", hash = "sha256:e31be53d7f4905a6a038296d8b773a79da9ee9f0cd19af9490c5c5a22e37d2e5", size = 863036 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "charset-normalizer" },
|
||||
{ name = "idna" },
|
||||
{ name = "urllib3" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests-toolbelt"
|
||||
version = "1.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "requests" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.9.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2a/e1/e265aba384343dd8ddd3083f5e33536cd17e1566c41453a5517b5dd443be/ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9", size = 3639454 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/e3/3d2c022e687e18cf5d93d6bfa2722d46afc64eaa438c7fbbdd603b3597be/ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba", size = 11714128 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/22/aff073b70f95c052e5c58153cba735748c9e70107a77d03420d7850710a0/ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504", size = 11682539 },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/a7/f5b7390afd98a7918582a3d256cd3e78ba0a26165a467c1820084587cbf9/ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83", size = 11132512 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/e3/45de13ef65047fea2e33f7e573d848206e15c715e5cd56095589a7733d04/ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc", size = 11929275 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/f2/23d04cd6c43b2e641ab961ade8d0b5edb212ecebd112506188c91f2a6e6c/ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b", size = 11466502 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/6f/3a8cf166f2d7f1627dd2201e6cbc4cb81f8b7d58099348f0c1ff7b733792/ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e", size = 12676364 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/c4/db52e2189983c70114ff2b7e3997e48c8318af44fe83e1ce9517570a50c6/ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666", size = 13335518 },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/44/545f8a4d136830f08f4d24324e7db957c5374bf3a3f7a6c0bc7be4623a37/ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5", size = 12823287 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/26/8208ef9ee7431032c143649a9967c3ae1aae4257d95e6f8519f07309aa66/ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5", size = 14592374 },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/70/e917781e55ff39c5b5208bda384fd397ffd76605e68544d71a7e40944945/ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217", size = 12500173 },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/f5/e4ddee07660f5a9622a9c2b639afd8f3104988dc4f6ba0b73ffacffa9a8c/ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6", size = 11906555 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/2b/6ff2fe383667075eef8656b9892e73dd9b119b5e3add51298628b87f6429/ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897", size = 11538958 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/db/98e59e90de45d1eb46649151c10a062d5707b5b7f76f64eb1e29edf6ebb1/ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08", size = 12117247 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/bc/54e38f6d219013a9204a5a2015c09e7a8c36cedcd50a4b01ac69a550b9d9/ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656", size = 12554647 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/7d/7b461ab0e2404293c0627125bb70ac642c2e8d55bf590f6fce85f508f1b2/ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d", size = 9949214 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/30/c3cee10f915ed75a5c29c1e57311282d1a15855551a64795c1b2bbe5cf37/ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa", size = 10999914 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/a8/d71f44b93e3aa86ae232af1f2126ca7b95c0f515ec135462b3e1f351441c/ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a", size = 10177499 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.17.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sniffio"
|
||||
version = "1.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "speckle-automate-checker"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "more-itertools" },
|
||||
{ name = "pandas" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "pytest-assertcount" },
|
||||
{ name = "python-dotenv" },
|
||||
{ name = "python-levenshtein" },
|
||||
{ name = "specklepy" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "black" },
|
||||
{ name = "mypy" },
|
||||
{ name = "pydantic-settings" },
|
||||
{ name = "pytest" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "more-itertools", specifier = ">=10.6.0" },
|
||||
{ name = "pandas", specifier = ">=2.2.3" },
|
||||
{ name = "pydantic", specifier = "==2.10.6" },
|
||||
{ name = "pytest-assertcount", specifier = ">=1.0.0" },
|
||||
{ name = "python-dotenv", specifier = ">=1.0.1" },
|
||||
{ name = "python-levenshtein", specifier = ">=0.26.1" },
|
||||
{ name = "specklepy", specifier = ">=2.21.2" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "black", specifier = ">=25.1.0" },
|
||||
{ name = "mypy", specifier = ">=1.15.0" },
|
||||
{ name = "pydantic-settings", specifier = ">=2.7.1" },
|
||||
{ name = "pytest", specifier = ">=8.3.4" },
|
||||
{ name = "ruff", specifier = ">=0.9.6" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "specklepy"
|
||||
version = "2.21.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "appdirs" },
|
||||
{ name = "attrs" },
|
||||
{ name = "deprecated" },
|
||||
{ name = "gql", extra = ["requests", "websockets"] },
|
||||
{ name = "httpx" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "stringcase" },
|
||||
{ name = "ujson" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/18/79/58269be683ca06194a464deaac3655989b094c6a0df0f8dccb24eeb47031/specklepy-2.21.2.tar.gz", hash = "sha256:ba44bb9167ced32e52ba7e5717d0b1d0ece1aa23ca02243ce75f0eaba08e8107", size = 93326 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/13/89/78eb05af38fc455c695c2ab882db2cca0ef518313c49f73b6536d0cad9e7/specklepy-2.21.2-py3-none-any.whl", hash = "sha256:bb34bb0de56f8731f88ac9a1ada4cddfbf2d71e52d4e9cce07bab95c1dac2b2d", size = 136495 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stringcase"
|
||||
version = "1.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f3/1f/1241aa3d66e8dc1612427b17885f5fcd9c9ee3079fc0d28e9a3aeeb36fa3/stringcase-1.2.0.tar.gz", hash = "sha256:48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008", size = 2958 }
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.12.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tzdata"
|
||||
version = "2025.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/43/0f/fa4723f22942480be4ca9527bbde8d43f6c3f2fe8412f00e7f5f6746bc8b/tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", size = 194950 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/dd/84f10e23edd882c6f968c21c2434fe67bd4a528967067515feca9e611e5e/tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639", size = 346762 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ujson"
|
||||
version = "5.10.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f0/00/3110fd566786bfa542adb7932d62035e0c0ef662a8ff6544b6643b3d6fd7/ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1", size = 7154885 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/a6/fd3f8bbd80842267e2d06c3583279555e8354c5986c952385199d57a5b6c/ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5", size = 55642 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/47/dd03fd2b5ae727e16d5d18919b383959c6d269c7b948a380fdd879518640/ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e", size = 51807 },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/23/079a4cc6fd7e2655a473ed9e776ddbb7144e27f04e8fc484a0fb45fe6f71/ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043", size = 51972 },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/81/668707e5f2177791869b624be4c06fb2473bf97ee33296b18d1cf3092af7/ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1", size = 53686 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/50/056d518a386d80aaf4505ccf3cee1c40d312a46901ed494d5711dd939bc3/ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3", size = 58591 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/d6/aeaf3e2d6fb1f4cfb6bf25f454d60490ed8146ddc0600fae44bfe7eb5a72/ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21", size = 997853 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/d5/1f2a5d2699f447f7d990334ca96e90065ea7f99b142ce96e85f26d7e78e2/ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2", size = 1140689 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/2c/6990f4ccb41ed93744aaaa3786394bca0875503f97690622f3cafc0adfde/ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e", size = 1043576 },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/f5/a2368463dbb09fbdbf6a696062d0c0f62e4ae6fa65f38f829611da2e8fdd/ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e", size = 38764 },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/2d/691f741ffd72b6c84438a93749ac57bf1a3f217ac4b0ea4fd0e96119e118/ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc", size = 42211 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/69/b3e3f924bb0e8820bb46671979770c5be6a7d51c77a66324cdb09f1acddb/ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287", size = 55646 },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/8a/9b748eb543c6cabc54ebeaa1f28035b1bd09c0800235b08e85990734c41e/ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e", size = 51806 },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/50/4b53ea234413b710a18b305f465b328e306ba9592e13a791a6a6b378869b/ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557", size = 51975 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/9d/8061934f960cdb6dd55f0b3ceeff207fcc48c64f58b43403777ad5623d9e/ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988", size = 53693 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/be/7bfa84b28519ddbb67efc8410765ca7da55e6b93aba84d97764cd5794dbc/ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816", size = 58594 },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/eb/85d465abafb2c69d9699cfa5520e6e96561db787d36c677370e066c7e2e7/ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20", size = 997853 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/76/2a63409fc05d34dd7d929357b7a45e3a2c96f22b4225cd74becd2ba6c4cb/ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0", size = 1140694 },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/ed/582c4daba0f3e1688d923b5cb914ada1f9defa702df38a1916c899f7c4d1/ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f", size = 1043580 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/0c/9837fece153051e19c7bade9f88f9b409e026b9525927824cdf16293b43b/ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165", size = 38766 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/72/6cb6728e2738c05bbe9bd522d6fc79f86b9a28402f38663e85a28fddd4a0/ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539", size = 42212 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "websockets"
|
||||
version = "11.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/3b/2ed38e52eed4cf277f9df5f0463a99199a04d9e29c9e227cfafa57bd3993/websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016", size = 104235 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/47/96/9d5749106ff57629b54360664ae7eb9afd8302fad1680ead385383e33746/websockets-11.0.3-py3-none-any.whl", hash = "sha256:6681ba9e7f8f3b19440921e99efbb40fc89f26cd71bf539e45d8c8a25c976dc6", size = 118056 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wrapt"
|
||||
version = "1.17.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c3/fc/e91cc220803d7bc4db93fb02facd8461c37364151b8494762cc88b0fbcef/wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", size = 55531 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/bd/ab55f849fd1f9a58ed7ea47f5559ff09741b25f00c191231f9f059c83949/wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", size = 53799 },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/18/75ddc64c3f63988f5a1d7e10fb204ffe5762bc663f8023f18ecaf31a332e/wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", size = 38821 },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/2a/97928387d6ed1c1ebbfd4efc4133a0633546bec8481a2dd5ec961313a1c7/wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", size = 38919 },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/54/3bfe5a1febbbccb7a2f77de47b989c0b85ed3a6a41614b104204a788c20e/wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", size = 88721 },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/cb/7262bc1b0300b4b64af50c2720ef958c2c1917525238d661c3e9a2b71b7b/wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", size = 80899 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/5a/04cde32b07a7431d4ed0553a76fdb7a61270e78c5fd5a603e190ac389f14/wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", size = 89222 },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/28/2e45a4f4771fcfb109e244d5dbe54259e970362a311b67a965555ba65026/wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", size = 86707 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/d2/dcb56bf5f32fcd4bd9aacc77b50a539abdd5b6536872413fd3f428b21bed/wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", size = 79685 },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/4e/eb8b353e36711347893f502ce91c770b0b0929f8f0bed2670a6856e667a9/wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", size = 87567 },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/27/4fe749a54e7fae6e7146f1c7d914d28ef599dacd4416566c055564080fe2/wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", size = 36672 },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/06/1dbf478ea45c03e78a6a8c4be4fdc3c3bddea5c8de8a93bc971415e47f0f/wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", size = 38865 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/b9/0ffd557a92f3b11d4c5d5e0c5e4ad057bd9eb8586615cdaf901409920b14/wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", size = 53800 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/ef/8be90a0b7e73c32e550c73cfb2fa09db62234227ece47b0e80a05073b375/wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", size = 38824 },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/89/0aae34c10fe524cce30fe5fc433210376bce94cf74d05b0d68344c8ba46e/wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", size = 38920 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/24/11c4510de906d77e0cfb5197f1b1445d4fec42c9a39ea853d482698ac681/wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8", size = 88690 },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/d7/cfcf842291267bf455b3e266c0c29dcb675b5540ee8b50ba1699abf3af45/wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6", size = 80861 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/66/5d973e9f3e7370fd686fb47a9af3319418ed925c27d72ce16b791231576d/wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc", size = 89174 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/d3/8e17bb70f6ae25dabc1aaf990f86824e4fd98ee9cadf197054e068500d27/wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2", size = 86721 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/54/f170dfb278fe1c30d0ff864513cff526d624ab8de3254b20abb9cffedc24/wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b", size = 79763 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/98/de07243751f1c4a9b15c76019250210dd3486ce098c3d80d5f729cba029c/wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504", size = 87585 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/f0/13925f4bd6548013038cdeb11ee2cbd4e37c30f8bfd5db9e5a2a370d6e20/wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a", size = 36676 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/ae/743f16ef8c2e3628df3ddfd652b7d4c555d12c84b53f3d8218498f4ade9b/wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845", size = 38871 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/bc/30f903f891a82d402ffb5fda27ec1d621cc97cb74c16fea0b6141f1d4e87/wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192", size = 56312 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/04/c97273eb491b5f1c918857cd26f314b74fc9b29224521f5b83f872253725/wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b", size = 40062 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/ca/3b7afa1eae3a9e7fefe499db9b96813f41828b9fdb016ee836c4c379dadb/wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0", size = 40155 },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/be/7c1baed43290775cb9030c774bc53c860db140397047cc49aedaf0a15477/wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306", size = 113471 },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/98/4ed894cf012b6d6aae5f5cc974006bdeb92f0241775addad3f8cd6ab71c8/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb", size = 101208 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/fd/0c30f2301ca94e655e5e057012e83284ce8c545df7661a78d8bfca2fac7a/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681", size = 109339 },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/56/05d000de894c4cfcb84bcd6b1df6214297b8089a7bd324c21a4765e49b14/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6", size = 110232 },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/f8/c3f6b2cf9b9277fb0813418e1503e68414cd036b3b099c823379c9575e6d/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6", size = 100476 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/b1/0bb11e29aa5139d90b770ebbfa167267b1fc548d2302c30c8f7572851738/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f", size = 106377 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/e1/0122853035b40b3f333bbb25f1939fc1045e21dd518f7f0922b60c156f7c/wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555", size = 37986 },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/5e/1655cf481e079c1f22d0cabdd4e51733679932718dc23bf2db175f329b76/wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", size = 40750 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/82/f56956041adef78f849db6b289b282e72b55ab8045a75abad81898c28d19/wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", size = 23594 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yarl"
|
||||
version = "1.18.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "idna" },
|
||||
{ name = "multidict" },
|
||||
{ name = "propcache" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b7/9d/4b94a8e6d2b51b599516a5cb88e5bc99b4d8d4583e468057eaa29d5f0918/yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1", size = 181062 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/33/85/bd2e2729752ff4c77338e0102914897512e92496375e079ce0150a6dc306/yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50", size = 142644 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/74/1178322cc0f10288d7eefa6e4a85d8d2e28187ccab13d5b844e8b5d7c88d/yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576", size = 94962 },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/75/79c6acc0261e2c2ae8a1c41cf12265e91628c8c58ae91f5ff59e29c0787f/yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640", size = 92795 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/32/927b2d67a412c31199e83fefdce6e645247b4fb164aa1ecb35a0f9eb2058/yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2", size = 332368 },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/e5/859fca07169d6eceeaa4fde1997c91d8abde4e9a7c018e371640c2da2b71/yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75", size = 342314 },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/75/76b63ccd91c9e03ab213ef27ae6add2e3400e77e5cdddf8ed2dbc36e3f21/yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512", size = 341987 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/e1/a097d5755d3ea8479a42856f51d97eeff7a3a7160593332d98f2709b3580/yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba", size = 336914 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/42/e1b4d0e396b7987feceebe565286c27bc085bf07d61a59508cdaf2d45e63/yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb", size = 325765 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/18/03a5834ccc9177f97ca1bbb245b93c13e58e8225276f01eedc4cc98ab820/yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272", size = 344444 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/03/a713633bdde0640b0472aa197b5b86e90fbc4c5bc05b727b714cd8a40e6d/yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6", size = 340760 },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/99/f6567e3f3bbad8fd101886ea0276c68ecb86a2b58be0f64077396cd4b95e/yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e", size = 346484 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/a9/84717c896b2fc6cb15bd4eecd64e34a2f0a9fd6669e69170c73a8b46795a/yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb", size = 359864 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/2e/d0f5f1bef7ee93ed17e739ec8dbcb47794af891f7d165fa6014517b48169/yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393", size = 364537 },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/8a/568d07c5d4964da5b02621a517532adb8ec5ba181ad1687191fffeda0ab6/yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285", size = 357861 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/e3/924c3f64b6b3077889df9a1ece1ed8947e7b61b0a933f2ec93041990a677/yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2", size = 84097 },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/45/0e055320daaabfc169b21ff6174567b2c910c45617b0d79c68d7ab349b02/yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477", size = 90399 },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/c7/c790513d5328a8390be8f47be5d52e141f78b66c6c48f48d241ca6bd5265/yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb", size = 140789 },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/aa/a2f84e93554a578463e2edaaf2300faa61c8701f0898725842c704ba5444/yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa", size = 94144 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/fc/d68d8f83714b221a85ce7866832cba36d7c04a68fa6a960b908c2c84f325/yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782", size = 91974 },
|
||||
{ url = "https://files.pythonhosted.org/packages/56/4e/d2563d8323a7e9a414b5b25341b3942af5902a2263d36d20fb17c40411e2/yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0", size = 333587 },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/c9/cfec0bc0cac8d054be223e9f2c7909d3e8442a856af9dbce7e3442a8ec8d/yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482", size = 344386 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/5d/4c532190113b25f1364d25f4c319322e86232d69175b91f27e3ebc2caf9a/yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186", size = 345421 },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/d1/6cdd1632da013aa6ba18cee4d750d953104a5e7aac44e249d9410a972bf5/yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58", size = 339384 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/c4/6b3c39bec352e441bd30f432cda6ba51681ab19bb8abe023f0d19777aad1/yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53", size = 326689 },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/30/07fb088f2eefdc0aa4fc1af4e3ca4eb1a3aadd1ce7d866d74c0f124e6a85/yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2", size = 345453 },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/09/d54befb48f9cd8eec43797f624ec37783a0266855f4930a91e3d5c7717f8/yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8", size = 341872 },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/26/fd0ef9bf29dd906a84b59f0cd1281e65b0c3e08c6aa94b57f7d11f593518/yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1", size = 347497 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/b5/14ac7a256d0511b2ac168d50d4b7d744aea1c1aa20c79f620d1059aab8b2/yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a", size = 359981 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/b3/d493221ad5cbd18bc07e642894030437e405e1413c4236dd5db6e46bcec9/yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10", size = 366229 },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/56/6a3e2a5d9152c56c346df9b8fb8edd2c8888b1e03f96324d457e5cf06d34/yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8", size = 360383 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/b7/4b3c7c7913a278d445cc6284e59b2e62fa25e72758f888b7a7a39eb8423f/yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d", size = 310152 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/d5/688db678e987c3e0fb17867970700b92603cadf36c56e5fb08f23e822a0c/yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c", size = 315723 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/4b/a06e0ec3d155924f77835ed2d167ebd3b211a7b0853da1cf8d8414d784ef/yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b", size = 45109 },
|
||||
]
|
||||
Reference in New Issue
Block a user