From 22e375f7df6d52f5d4e94b53a0806f721152d4b9 Mon Sep 17 00:00:00 2001 From: Sam Wolk <36545842+szvsw@users.noreply.github.com> Date: Thu, 19 Feb 2026 17:03:24 -0500 Subject: [PATCH] create dat builder --- .../plans/decision_dag_module_backup.plan.md | 355 +++ epinterface/sbem/decision_dag/__init__.py | 56 + epinterface/sbem/decision_dag/agent.py | 180 ++ epinterface/sbem/decision_dag/dag.py | 158 ++ epinterface/sbem/decision_dag/executor.py | 196 ++ epinterface/sbem/decision_dag/fields.py | 124 + epinterface/sbem/decision_dag/schema_utils.py | 264 ++ epinterface/sbem/decision_dag/validation.py | 237 ++ epinterface/sbem/decision_dag/visualize.py | 289 +++ epinterface/sbem/flat_model.py | 363 ++- pyproject.toml | 8 +- tests/test_decision_dag/__init__.py | 1 + tests/test_decision_dag/_last_dag.json | 570 +++++ .../_last_user_field_set.yaml | 104 + .../test_decision_dag/_last_user_message.txt | 92 + tests/test_decision_dag/test_dag.py | 214 ++ tests/test_decision_dag/test_executor.py | 303 +++ tests/test_decision_dag/test_fields.py | 198 ++ .../test_decision_dag/test_llm_integration.py | 291 +++ tests/test_decision_dag/test_validation.py | 372 +++ tests/test_decision_dag/tester.ipynb | 334 +++ tests/test_decision_dag/visualized_dag.md | 375 +++ tests/test_decision_dag/working_dag.json | 628 +++++ tests/test_decision_dag/working_dag.md | 406 +++ .../working_user_field_set.yaml | 110 + uv.lock | 2181 ++++++++++++++++- 26 files changed, 8256 insertions(+), 153 deletions(-) create mode 100644 .cursor/plans/decision_dag_module_backup.plan.md create mode 100644 epinterface/sbem/decision_dag/__init__.py create mode 100644 epinterface/sbem/decision_dag/agent.py create mode 100644 epinterface/sbem/decision_dag/dag.py create mode 100644 epinterface/sbem/decision_dag/executor.py create mode 100644 epinterface/sbem/decision_dag/fields.py create mode 100644 epinterface/sbem/decision_dag/schema_utils.py create mode 100644 epinterface/sbem/decision_dag/validation.py create mode 100644 epinterface/sbem/decision_dag/visualize.py create mode 100644 tests/test_decision_dag/__init__.py create mode 100644 tests/test_decision_dag/_last_dag.json create mode 100644 tests/test_decision_dag/_last_user_field_set.yaml create mode 100644 tests/test_decision_dag/_last_user_message.txt create mode 100644 tests/test_decision_dag/test_dag.py create mode 100644 tests/test_decision_dag/test_executor.py create mode 100644 tests/test_decision_dag/test_fields.py create mode 100644 tests/test_decision_dag/test_llm_integration.py create mode 100644 tests/test_decision_dag/test_validation.py create mode 100644 tests/test_decision_dag/tester.ipynb create mode 100644 tests/test_decision_dag/visualized_dag.md create mode 100644 tests/test_decision_dag/working_dag.json create mode 100644 tests/test_decision_dag/working_dag.md create mode 100644 tests/test_decision_dag/working_user_field_set.yaml diff --git a/.cursor/plans/decision_dag_module_backup.plan.md b/.cursor/plans/decision_dag_module_backup.plan.md new file mode 100644 index 0000000..92f4eae --- /dev/null +++ b/.cursor/plans/decision_dag_module_backup.plan.md @@ -0,0 +1,355 @@ +--- +name: Decision DAG Module +overview: Design and implement a new `epinterface/sbem/decision_dag/` subpackage that allows users to define rich field schemas for their data, and uses Pydantic AI to have an LLM generate a decision DAG that maps those fields to FlatModel parameters, with an executor to process individual data rows through the DAG. +todos: + - id: todo-1771528465803-6iv7tr81p + content: Add field descriptions and unit annotations where relevant (all SI) to all of the fields of flat model to assist the AI/LLM when constructing decision trees. + status: pending + - id: add-dep + content: Add pydantic-ai dependency via `uv add pydantic-ai` + status: pending + - id: fields + content: Create `decision_dag/fields.py` with UserFieldDefinition, UserFieldSet, FieldType + status: pending + - id: dag-schema + content: Create `decision_dag/dag.py` with DAG node types, IntermediateComponent, DecisionDAG + status: pending + - id: schema-utils + content: Create `decision_dag/schema_utils.py` with FlatModel introspection and assignment validation + status: pending + - id: executor + content: Create `decision_dag/executor.py` with DAGExecutor and BFS execution logic + status: pending + - id: validation + content: Create `decision_dag/validation.py` with structural graph validation (cycles, refs, coverage) + status: pending + - id: agent + content: Create `decision_dag/agent.py` with Pydantic AI agent, system prompt, and generate_dag() + status: pending + - id: init + content: Create `decision_dag/__init__.py` with public exports + status: pending + - id: tests + content: Create test suite under tests/test_decision_dag/ for fields, DAG, executor, and validation + status: pending +isProject: false +--- + +# Decision DAG Module for LLM-Driven FlatModel Inference + +## Context + +The existing pipeline (`[epinterface/sbem/components/composer.py](epinterface/sbem/components/composer.py)`) resolves building energy model components from a Prisma database using declarative selector trees. The existing `[epinterface/sbem/fields/spec.py](epinterface/sbem/fields/spec.py)` defines simple field schemas (categorical options, numeric ranges) for GIS data. + +The new module replaces the database-backed component library approach with an **LLM-generated decision DAG**: users describe their available fields, and an LLM produces a structured graph that maps user data rows to all ~72 parameters of `[FlatModel](epinterface/sbem/flat_model.py)` (line 629). + +## Architecture + +```mermaid +flowchart TD + subgraph userInput [User Input] + UFS["UserFieldSet\n(field definitions + context)"] + SUP["SupplementaryContext\n(JSON, prose, CSV, etc.)"] + ROW["Data Row\n(dict of field values)"] + end + + subgraph llmPhase [DAG Generation - once per field set] + SCHEMA["FlatModel Schema\nIntrospection"] + AGENT["Pydantic AI Agent"] + UFS --> AGENT + SUP --> AGENT + SCHEMA --> AGENT + AGENT --> DAG["DecisionDAG\n(nodes + components)"] + end + + subgraph execPhase [Execution - per row] + ROW --> EXEC["DAGExecutor"] + DAG --> EXEC + EXEC --> ASSIGN["Parameter\nAssignments"] + DIRECT["Direct Values\n(geometry, weather)"] + ASSIGN --> FM["FlatModel"] + DIRECT --> FM + end +``` + + + +## New Module: `epinterface/sbem/decision_dag/` + +### 1. `fields.py` -- User Field Definitions + +Extends the patterns from `[spec.py](epinterface/sbem/fields/spec.py)` with richer metadata for LLM consumption. + +```python +class FieldType(str, Enum): + CATEGORICAL = "categorical" + NUMERIC = "numeric" + PLAINTEXT = "plaintext" + +class UserFieldDefinition(BaseModel): + name: str + field_type: FieldType + description: str # English description of what this field represents + data_quality_description: str = "" # How reliable/complete this field is + # categorical fields + categories: list[str] | None = None + # numeric fields + min_value: float | None = None + max_value: float | None = None + unit: str | None = None + +class SupplementaryContext(BaseModel): + title: str # e.g. "HVAC System Frequency Distribution" + content: str # Plain text, JSON, markdown, CSV -- any format + format_hint: str = "plaintext" # "plaintext", "json", "csv", "markdown", etc. + +class UserFieldSet(BaseModel): + fields: list[UserFieldDefinition] + context_description: str = "" # Overall project context + region_description: str = "" # Geographic/climate context + building_stock_description: str = "" # Building stock characteristics + supplementary_context: list[SupplementaryContext] = [] +``` + +`supplementary_context` allows the user to attach any number of unstructured knowledge documents that help the LLM build a better DAG. Examples: + +- A JSON object describing construction typology distributions (e.g. `{"wood_frame": 0.6, "masonry": 0.3, "steel": 0.1}`) +- A plain English paragraph about regional building codes and common retrofit practices +- A CSV-like table of HVAC system types and their prevalence by building age +- Notes on local energy audit findings, weatherization program data, or utility rebate patterns +- Historical construction practice descriptions (e.g. "pre-1940 buildings in this region typically have uninsulated double-wythe brick walls") + +The `format_hint` helps the LLM interpret the content correctly. All supplementary context is injected into the LLM user message alongside the field definitions. + +Validators ensure `categories` is set for categorical fields, `min_value`/`max_value` for numeric, etc. + +### 2. `dag.py` -- Decision DAG Schema (LLM Output) + +This is the structured output the LLM produces. Uses discriminated unions for node types. + +**Conditions:** + +```python +class ComparisonOperator(str, Enum): + EQ = "eq" + NEQ = "neq" + LT = "lt" + LTE = "lte" + GT = "gt" + GTE = "gte" + IN = "in" + NOT_IN = "not_in" + CONTAINS = "contains" + IS_MISSING = "is_missing" + IS_NOT_MISSING = "is_not_missing" + +class FieldCondition(BaseModel): + field: str # references a UserFieldDefinition.name + operator: ComparisonOperator + value: Any = None # not needed for is_missing / is_not_missing +``` + +**Node types (discriminated union on `node_type`):** + +- **ConditionNode** -- Evaluates branches against a user data row, routes to the first matching target. Has an optional `default_target_id` fallback. + +```python +class ConditionalBranch(BaseModel): + condition: FieldCondition + target_node_id: str + +class ConditionNode(BaseModel): + node_type: Literal["condition"] = "condition" + id: str + description: str + branches: list[ConditionalBranch] + default_target_id: str | None = None +``` + +- **AssignmentNode** -- Directly assigns values to FlatModel parameters. Can chain to further nodes via `next_node_ids`. + +```python +class AssignmentNode(BaseModel): + node_type: Literal["assignment"] = "assignment" + id: str + description: str + assignments: dict[str, Any] # FlatModel field name -> value + next_node_ids: list[str] = [] +``` + +- **ComponentRefNode** -- References a named IntermediateComponent (a reusable bundle of assignments). Enables the "high performing single family wall" pattern. + +```python +class ComponentRefNode(BaseModel): + node_type: Literal["component_ref"] = "component_ref" + id: str + description: str + component_id: str + next_node_ids: list[str] = [] +``` + +**Intermediate Components and the DAG itself:** + +```python +class IntermediateComponent(BaseModel): + id: str + name: str # Human-readable (e.g. "High Performance SF Wall") + description: str + assignments: dict[str, Any] # FlatModel field name -> value + +DAGNode = Annotated[ + ConditionNode | AssignmentNode | ComponentRefNode, + Field(discriminator="node_type"), +] + +class DecisionDAG(BaseModel): + description: str # LLM's summary of its reasoning + components: list[IntermediateComponent] + nodes: list[DAGNode] + entry_node_ids: list[str] # Root(s) of the graph +``` + +Multiple entry nodes allow independent sub-DAGs for orthogonal parameter groups (e.g., one sub-DAG for envelope, another for HVAC, another for schedules). + +### 3. `executor.py` -- DAG Execution Engine + +Processes a single data row through the DAG via BFS from entry nodes: + +```python +class DAGExecutionTrace(BaseModel): + visited_node_ids: list[str] + applied_component_ids: list[str] + unresolved_fields: list[str] # FlatModel fields not assigned + +class DAGExecutionResult(BaseModel): + assignments: dict[str, Any] + trace: DAGExecutionTrace + +class DAGExecutor: + def __init__(self, dag: DecisionDAG): ... + def execute(self, row: dict[str, Any]) -> DAGExecutionResult: ... + def execute_to_flat_model( + self, + row: dict[str, Any], + direct_values: dict[str, Any] | None = None, + ) -> FlatModel: ... +``` + +Key execution rules: + +- BFS from `entry_node_ids`; each node visited at most once (cycle protection) +- **ConditionNode**: evaluates branches in order, follows first match (or default) +- **AssignmentNode**: merges `assignments` into result, then follows `next_node_ids` +- **ComponentRefNode**: looks up component, merges its assignments, then follows `next_node_ids` +- Later assignments override earlier ones (allows refinement chains) +- `IS_MISSING` operator handles absent/null fields gracefully +- `execute_to_flat_model` merges DAG assignments with `direct_values` (direct wins) and constructs a `FlatModel` + +### 4. `schema_utils.py` -- FlatModel Schema Introspection + +Generates a prompt-friendly description of all FlatModel fields for the LLM system prompt: + +```python +def get_flat_model_schema_description() -> str: + """Introspect FlatModel and return a structured description of all fields.""" +``` + +This will iterate over `FlatModel.model_fields`, extracting: + +- Field name, Python type, constraints (ge, le, enum values) +- Grouping by parameter category (schedules, setpoints, HVAC, etc.) + +Also provides DAG validation: + +```python +def validate_dag_assignments(dag: DecisionDAG) -> list[str]: + """Validate that all assignments reference valid FlatModel fields + and that values are compatible with field types/constraints.""" +``` + +### 5. `agent.py` -- Pydantic AI Agent + +Uses `pydantic-ai` with structured output. Depends on `pydantic-ai` being added as a dependency. + +```python +from pydantic_ai import Agent + +dag_agent = Agent( + "openai:gpt-4o", # configurable + result_type=DecisionDAG, + system_prompt=..., # includes FlatModel schema from schema_utils +) +``` + +The system prompt will instruct the LLM to: + +- Analyze the user's field definitions, their data quality, and regional context +- Incorporate all supplementary context documents (building stock distributions, construction typology info, local code references, audit data, etc.) to inform parameter choices and component definitions +- Design a DAG that handles sparse data (heavy use of `IS_MISSING` checks with sensible defaults) +- Use intermediate components for common parameter bundles, informed by the supplementary context (e.g., if the user provides HVAC frequency data, create components matching those system archetypes) +- Ensure every required FlatModel field is assigned on every possible execution path +- Apply regional building code knowledge and climate-appropriate defaults + +The user message will be constructed from a `UserFieldSet` instance. It will include: + +1. The structured field definitions with types, descriptions, and data quality notes +2. Each `SupplementaryContext` entry rendered as a titled, labeled section with its format hint so the LLM can interpret JSON, CSV, prose, etc. correctly +3. The regional and building stock context strings + +A convenience function wraps the agent call: + +```python +async def generate_dag( + field_set: UserFieldSet, + model: str = "openai:gpt-4o", +) -> DecisionDAG: ... +``` + +### 6. `validation.py` -- Structural DAG Validation + +Validates the DAG after LLM generation: + +- All `target_node_id` and `next_node_ids` reference existing node IDs +- All `component_id` references point to existing components +- All `entry_node_ids` exist +- The graph is acyclic (topological sort check) +- All referenced user fields exist in the `UserFieldSet` +- All FlatModel field names in assignments are valid +- Coverage check: every FlatModel field (excluding geometry/weather, which come from `direct_values`) is assigned on at least one path + +### 7. `__init__.py` -- Public API + +Exports the key types and functions: + +- `UserFieldDefinition`, `UserFieldSet`, `FieldType`, `SupplementaryContext` +- `DecisionDAG`, `IntermediateComponent`, `ConditionNode`, `AssignmentNode`, `ComponentRefNode` +- `DAGExecutor`, `DAGExecutionResult` +- `generate_dag` +- `validate_dag_assignments`, `get_flat_model_schema_description` + +## Dependency Change + +Add `pydantic-ai` to `[project.dependencies]` in `[pyproject.toml](pyproject.toml)`: + +``` +uv add pydantic-ai +``` + +## File Summary + + +| New file | Purpose | +| ----------------------------------------------- | -------------------------------------------------- | +| `epinterface/sbem/decision_dag/__init__.py` | Public exports | +| `epinterface/sbem/decision_dag/fields.py` | User field definitions (input schema) | +| `epinterface/sbem/decision_dag/dag.py` | DAG node types and DecisionDAG (output schema) | +| `epinterface/sbem/decision_dag/executor.py` | Row-level DAG execution engine | +| `epinterface/sbem/decision_dag/schema_utils.py` | FlatModel introspection + DAG-vs-schema validation | +| `epinterface/sbem/decision_dag/validation.py` | Structural graph validation | +| `epinterface/sbem/decision_dag/agent.py` | Pydantic AI agent + prompt engineering | +| `tests/test_decision_dag/test_fields.py` | Tests for field definitions | +| `tests/test_decision_dag/test_dag.py` | Tests for DAG serialization/deserialization | +| `tests/test_decision_dag/test_executor.py` | Tests for DAG execution with mock DAGs | +| `tests/test_decision_dag/test_validation.py` | Tests for structural + schema validation | + + diff --git a/epinterface/sbem/decision_dag/__init__.py b/epinterface/sbem/decision_dag/__init__.py new file mode 100644 index 0000000..e81b279 --- /dev/null +++ b/epinterface/sbem/decision_dag/__init__.py @@ -0,0 +1,56 @@ +"""Decision DAG module for LLM-driven FlatModel inference. + +Provides schemas for user field definitions, a decision DAG structure +that maps user data to FlatModel parameters, an execution engine, +structural validation, and a Pydantic AI agent for DAG generation. +""" + +from epinterface.sbem.decision_dag.dag import ( + AssignmentNode, + ComparisonOperator, + ComponentRefNode, + ConditionalBranch, + ConditionNode, + DAGNode, + DecisionDAG, + FieldCondition, + IntermediateComponent, +) +from epinterface.sbem.decision_dag.executor import ( + DAGExecutionResult, + DAGExecutionTrace, + DAGExecutor, +) +from epinterface.sbem.decision_dag.fields import ( + FieldType, + SupplementaryContext, + UserFieldDefinition, + UserFieldSet, +) +from epinterface.sbem.decision_dag.schema_utils import ( + get_flat_model_field_names, + get_flat_model_schema_description, + validate_dag_assignments, +) + +__all__ = [ + "AssignmentNode", + "ComparisonOperator", + "ComponentRefNode", + "ConditionNode", + "ConditionalBranch", + "DAGExecutionResult", + "DAGExecutionTrace", + "DAGExecutor", + "DAGNode", + "DecisionDAG", + "FieldCondition", + "FieldType", + "IntermediateComponent", + "SupplementaryContext", + "UserFieldDefinition", + "UserFieldSet", + "get_flat_model_field_names", + "get_flat_model_schema_description", + "validate_dag_assignments", +] diff --git a/epinterface/sbem/decision_dag/agent.py b/epinterface/sbem/decision_dag/agent.py new file mode 100644 index 0000000..3c995d6 --- /dev/null +++ b/epinterface/sbem/decision_dag/agent.py @@ -0,0 +1,180 @@ +"""Pydantic AI agent for generating DecisionDAGs from user field definitions. + +Uses structured output to have an LLM produce a validated DecisionDAG +that maps user data fields to FlatModel parameters. + +Requires the ``pydantic-ai`` optional dependency:: + + pip install epinterface[llm] +""" + +from __future__ import annotations + +from pydantic_ai import Agent + +from epinterface.sbem.decision_dag.dag import DecisionDAG +from epinterface.sbem.decision_dag.fields import ( + FieldType, + SupplementaryContext, + UserFieldDefinition, + UserFieldSet, +) +from epinterface.sbem.decision_dag.schema_utils import get_flat_model_schema_description + +INSTRUCTIONS_TEMPLATE = """\ +You are an expert building energy modeler. Your task is to create a decision DAG \ +(directed acyclic graph) that maps user-provided building data fields to the \ +parameters of a building energy model (FlatModel). + +The DAG you produce will be executed against individual rows of building data. \ +Each row contains values for the user's fields. Your DAG must assign values to \ +ALL required FlatModel parameters for every possible execution path. + +## Key Concepts + +- **ConditionNode**: Branches based on evaluating a user field. Branches are \ +checked in order; the first match is followed. Always include a default_target_id \ +as a fallback. +- **AssignmentNode**: Directly sets FlatModel parameter values. Can chain to \ +further nodes via next_node_ids. +- **ComponentRefNode**: References a reusable IntermediateComponent -- a named \ +bundle of parameter assignments (e.g. "High Performance Residential Envelope"). \ +Use these for common parameter combinations. +- **IntermediateComponent**: A reusable set of FlatModel parameter assignments \ +with a descriptive name and explanation. + +## Design Guidelines + +1. **Handle sparse data**: User fields may be incomplete. Use IS_MISSING / \ +IS_NOT_MISSING conditions extensively with sensible defaults. +2. **Use intermediate components**: Group related parameters into named \ +components that represent building archetypes or subsystem types. This makes \ +the DAG readable and maintainable. +3. **Multiple entry nodes**: Use separate sub-DAGs for orthogonal parameter \ +groups (e.g. one for envelope, one for HVAC, one for schedules) rather than \ +one monolithic tree. +4. **Regional specificity**: Apply your knowledge of regional building codes, \ +construction practices, and climate-appropriate defaults based on the user's \ +context. +5. **Data quality awareness**: When a field has low data quality, prefer \ +cross-referencing with other fields rather than trusting it directly. +6. **Always provide defaults**: Every execution path must assign all required \ +FlatModel parameters. Use sensible defaults for the given region and building stock. +7. **Refinement chains**: Start with broad defaults, then override with more \ +specific values as conditions narrow. Later assignments override earlier ones. +8. **Geometry and weather**: Fields like WWR, F2FHeight, NFloors, Width, Depth, \ +Rotation, and EPWURI are typically provided directly by the user and don't need \ +to be assigned by the DAG, unless the user's field set suggests the DAG should \ +infer them. + +{flat_model_schema} +""" + + +def _format_field_definition(field_def: UserFieldDefinition) -> str: + """Format a single field definition for the user message.""" + lines = [f"### {field_def.name}"] + lines.append(f"- Type: {field_def.field_type.value}") + lines.append(f"- Description: {field_def.description}") + + if field_def.data_quality_description: + lines.append(f"- Data quality: {field_def.data_quality_description}") + + if field_def.field_type == FieldType.CATEGORICAL and field_def.categories: + lines.append(f"- Categories: {field_def.categories}") + elif field_def.field_type == FieldType.NUMERIC: + range_str = f"{field_def.min_value} to {field_def.max_value}" + if field_def.unit: + range_str += f" {field_def.unit}" + lines.append(f"- Range: {range_str}") + + return "\n".join(lines) + + +def _format_supplementary_context(ctx: SupplementaryContext) -> str: + """Format a supplementary context document for the user message.""" + return f"### {ctx.title} (format: {ctx.format_hint})\n\n{ctx.content}" + + +def build_user_message(field_set: UserFieldSet) -> str: + """Construct the user message from a UserFieldSet. + + Includes field definitions, supplementary context, and + regional/building stock descriptions. + """ + sections: list[str] = [] + + if field_set.context_description: + sections.append(f"## Project Context\n\n{field_set.context_description}") + + if field_set.region_description: + sections.append(f"## Region & Climate\n\n{field_set.region_description}") + + if field_set.building_stock_description: + sections.append(f"## Building Stock\n\n{field_set.building_stock_description}") + + sections.append("## Available Data Fields\n") + for field_def in field_set.fields: + sections.append(_format_field_definition(field_def)) + + if field_set.supplementary_context: + sections.append("## Supplementary Context\n") + for ctx in field_set.supplementary_context: + sections.append(_format_supplementary_context(ctx)) + + sections.append( + "## Task\n\n" + "Based on the above field definitions, context, and supplementary " + "information, create a DecisionDAG that maps these user data fields " + "to all required FlatModel parameters. Use intermediate components " + "for common parameter bundles, handle missing data gracefully, and " + "apply regionally appropriate defaults." + ) + + return "\n\n".join(sections) + + +def build_instructions() -> str: + """Build the full agent instructions including the FlatModel schema.""" + schema_desc = get_flat_model_schema_description() + return INSTRUCTIONS_TEMPLATE.format(flat_model_schema=schema_desc) + + +def create_dag_agent(model: str = "openai:gpt-4o") -> Agent[None, DecisionDAG]: + """Create a Pydantic AI agent configured for DAG generation. + + Args: + model: The LLM model identifier (e.g. 'openai:gpt-4o', + 'anthropic:claude-sonnet-4-20250514'). + + Returns: + A configured Agent instance with DecisionDAG as the output type. + """ + return Agent( + model, + output_type=DecisionDAG, + instructions=build_instructions(), + output_retries=2, + ) + + +async def generate_dag( + field_set: UserFieldSet, + model: str = "openai:gpt-4o", +) -> DecisionDAG: + """Generate a DecisionDAG from user field definitions using an LLM. + + This is the main entry point for DAG generation. It creates an agent, + constructs the prompt from the field set, and returns the structured DAG. + + Args: + field_set: Complete specification of the user's available data and context. + model: The LLM model identifier. + + Returns: + A DecisionDAG ready for validation and execution. + """ + agent = create_dag_agent(model=model) + user_message = build_user_message(field_set) + result = await agent.run(user_message) + return result.output diff --git a/epinterface/sbem/decision_dag/dag.py b/epinterface/sbem/decision_dag/dag.py new file mode 100644 index 0000000..97490d5 --- /dev/null +++ b/epinterface/sbem/decision_dag/dag.py @@ -0,0 +1,158 @@ +"""Decision DAG schema -- the structured output produced by the LLM. + +Defines the node types, intermediate components, and the top-level +DecisionDAG model that represents the complete mapping from user +data fields to FlatModel parameters. +""" + +from __future__ import annotations + +from enum import Enum +from typing import Annotated, Any, Literal + +from pydantic import BaseModel, Field + + +class ComparisonOperator(str, Enum): + """Operators for evaluating conditions against a user data row.""" + + EQ = "eq" + NEQ = "neq" + LT = "lt" + LTE = "lte" + GT = "gt" + GTE = "gte" + IN = "in" + NOT_IN = "not_in" + CONTAINS = "contains" + IS_MISSING = "is_missing" + IS_NOT_MISSING = "is_not_missing" + + +class FieldCondition(BaseModel): + """A condition that evaluates a user data field against a value.""" + + field: str = Field(description="Name of the user data field to evaluate.") + operator: ComparisonOperator = Field(description="Comparison operator to apply.") + value: Any = Field( + default=None, + description="Comparison value (not needed for is_missing/is_not_missing).", + ) + + +class ConditionalBranch(BaseModel): + """A branch in a condition node: a condition paired with a target node.""" + + condition: FieldCondition = Field(description="The condition to evaluate.") + target_node_id: str = Field( + description="ID of the node to visit if condition is true." + ) + + +class ConditionNode(BaseModel): + """A node that branches based on evaluating conditions against a user data row. + + Branches are evaluated in order; the first matching branch is followed. + If no branch matches, the default_target_id is followed (if set). + """ + + node_type: Literal["condition"] = "condition" + id: str = Field(description="Unique identifier for this node.") + description: str = Field( + description="Human-readable description of what this node decides." + ) + branches: list[ConditionalBranch] = Field( + description="Ordered list of conditional branches." + ) + default_target_id: str | None = Field( + default=None, + description="Fallback node ID if no branch condition matches.", + ) + + +class AssignmentNode(BaseModel): + """A node that directly assigns values to FlatModel parameters. + + Can chain to further nodes via next_node_ids for sequential processing. + """ + + node_type: Literal["assignment"] = "assignment" + id: str = Field(description="Unique identifier for this node.") + description: str = Field( + description="Human-readable description of what this assignment represents." + ) + assignments: dict[str, Any] = Field( + description="Mapping of FlatModel field names to values." + ) + next_node_ids: list[str] = Field( + default_factory=list, + description="Node IDs to visit after this assignment.", + ) + + +class ComponentRefNode(BaseModel): + """A node that references a named IntermediateComponent. + + Applies all of the component's assignments, then optionally + continues to further nodes. This enables reusable parameter + bundles like 'high performance single family wall'. + """ + + node_type: Literal["component_ref"] = "component_ref" + id: str = Field(description="Unique identifier for this node.") + description: str = Field( + description="Human-readable description of why this component is applied." + ) + component_id: str = Field(description="ID of the IntermediateComponent to apply.") + next_node_ids: list[str] = Field( + default_factory=list, + description="Node IDs to visit after applying the component.", + ) + + +class IntermediateComponent(BaseModel): + """A named, reusable bundle of FlatModel parameter assignments. + + Intermediate components represent archetypal building subsystems + (e.g. 'Old Leaky SF Wall', 'High Efficiency Heat Pump') that + set multiple parameters at once. + """ + + id: str = Field(description="Unique identifier for this component.") + name: str = Field( + description="Human-readable name (e.g. 'High Performance SF Wall')." + ) + description: str = Field( + description="Description of what this component represents and its assumptions." + ) + assignments: dict[str, Any] = Field( + description="Mapping of FlatModel field names to values." + ) + + +DAGNode = Annotated[ + ConditionNode | AssignmentNode | ComponentRefNode, + Field(discriminator="node_type"), +] +"""Discriminated union of all node types in the decision DAG.""" + + +class DecisionDAG(BaseModel): + """The complete decision DAG that maps user data fields to FlatModel parameters. + + Generated by the LLM based on the user's field definitions and + supplementary context. Contains reusable intermediate components, + a graph of decision/assignment nodes, and entry point(s). + """ + + description: str = Field( + description="Summary of the DAG's overall logic and reasoning." + ) + components: list[IntermediateComponent] = Field( + default_factory=list, + description="Reusable intermediate components referenced by ComponentRefNodes.", + ) + nodes: list[DAGNode] = Field(description="All nodes in the decision graph.") + entry_node_ids: list[str] = Field( + description="IDs of root nodes where DAG execution begins. Multiple entries allow independent sub-DAGs for orthogonal parameter groups.", + ) diff --git a/epinterface/sbem/decision_dag/executor.py b/epinterface/sbem/decision_dag/executor.py new file mode 100644 index 0000000..247d29e --- /dev/null +++ b/epinterface/sbem/decision_dag/executor.py @@ -0,0 +1,196 @@ +"""DAG execution engine. + +Processes individual data rows through a DecisionDAG to produce +FlatModel parameter assignments via BFS traversal. +""" + +from __future__ import annotations + +from collections import deque +from typing import Any + +from pydantic import BaseModel, Field + +from epinterface.sbem.decision_dag.dag import ( + AssignmentNode, + ComparisonOperator, + ComponentRefNode, + ConditionNode, + DecisionDAG, + FieldCondition, +) + + +class DAGExecutionTrace(BaseModel): + """Audit trail of a single DAG execution.""" + + visited_node_ids: list[str] = Field( + default_factory=list, + description="Node IDs visited during execution, in order.", + ) + applied_component_ids: list[str] = Field( + default_factory=list, + description="Component IDs whose assignments were applied.", + ) + unresolved_fields: list[str] = Field( + default_factory=list, + description="FlatModel fields that were not assigned by the DAG.", + ) + + +class DAGExecutionResult(BaseModel): + """Result of executing a DAG against a single data row.""" + + assignments: dict[str, Any] = Field( + default_factory=dict, + description="Collected FlatModel field assignments.", + ) + trace: DAGExecutionTrace = Field( + default_factory=DAGExecutionTrace, + description="Execution audit trail.", + ) + + +def _is_missing(row: dict[str, Any], field: str) -> bool: + """Check if a field is absent or None in the data row.""" + return field not in row or row[field] is None + + +def _evaluate_condition(condition: FieldCondition, row: dict[str, Any]) -> bool: + """Evaluate a single FieldCondition against a data row.""" + op = condition.operator + + if op == ComparisonOperator.IS_MISSING: + return _is_missing(row, condition.field) + if op == ComparisonOperator.IS_NOT_MISSING: + return not _is_missing(row, condition.field) + + if _is_missing(row, condition.field): + return False + + row_val = row[condition.field] + cmp_val = condition.value + + if op == ComparisonOperator.EQ: + return row_val == cmp_val # type: ignore[no-any-return] + if op == ComparisonOperator.NEQ: + return row_val != cmp_val # type: ignore[no-any-return] + if op == ComparisonOperator.LT: + return row_val < cmp_val # type: ignore[no-any-return] + if op == ComparisonOperator.LTE: + return row_val <= cmp_val # type: ignore[no-any-return] + if op == ComparisonOperator.GT: + return row_val > cmp_val # type: ignore[no-any-return] + if op == ComparisonOperator.GTE: + return row_val >= cmp_val # type: ignore[no-any-return] + if op == ComparisonOperator.IN: + return row_val in cmp_val # type: ignore[no-any-return] + if op == ComparisonOperator.NOT_IN: + return row_val not in cmp_val # type: ignore[no-any-return] + if op == ComparisonOperator.CONTAINS: + return cmp_val in row_val # type: ignore[no-any-return] + + msg = f"Unknown operator: {op}" + raise ValueError(msg) + + +class DAGExecutor: + """Executes a DecisionDAG against data rows to produce FlatModel assignments. + + Traversal uses BFS from entry nodes. Each node is visited at most once + to prevent cycles. Later assignments override earlier ones, allowing + refinement chains. + """ + + def __init__(self, dag: DecisionDAG) -> None: + """Initialize the executor with a validated DAG.""" + self.dag = dag + self._node_map = {n.id: n for n in dag.nodes} + self._component_map = {c.id: c for c in dag.components} + + def execute(self, row: dict[str, Any]) -> DAGExecutionResult: + """Execute the DAG against a single data row. + + Args: + row: A dictionary of user field values for one data record. + + Returns: + DAGExecutionResult with collected assignments and execution trace. + """ + assignments: dict[str, Any] = {} + trace = DAGExecutionTrace() + visited: set[str] = set() + queue: deque[str] = deque(self.dag.entry_node_ids) + + while queue: + node_id = queue.popleft() + if node_id in visited: + continue + visited.add(node_id) + trace.visited_node_ids.append(node_id) + + node = self._node_map.get(node_id) + if node is None: + continue + + if isinstance(node, ConditionNode): + self._process_condition(node, row, queue) + elif isinstance(node, AssignmentNode): + assignments.update(node.assignments) + queue.extend(node.next_node_ids) + elif isinstance(node, ComponentRefNode): + comp = self._component_map.get(node.component_id) + if comp is not None: + assignments.update(comp.assignments) + trace.applied_component_ids.append(comp.id) + queue.extend(node.next_node_ids) + + from epinterface.sbem.decision_dag.schema_utils import ( + get_flat_model_field_names, + ) + + all_fields = get_flat_model_field_names() + trace.unresolved_fields = sorted(all_fields - set(assignments.keys())) + + return DAGExecutionResult(assignments=assignments, trace=trace) + + def execute_to_flat_model( + self, + row: dict[str, Any], + direct_values: dict[str, Any] | None = None, + ): + """Execute the DAG and construct a FlatModel instance. + + Args: + row: A dictionary of user field values for one data record. + direct_values: Optional dict of FlatModel field values that + override DAG assignments (e.g. geometry, weather). + + Returns: + A FlatModel instance with all parameters populated. + + Raises: + pydantic.ValidationError: If the combined assignments don't + satisfy FlatModel's validation constraints. + """ + from epinterface.sbem.flat_model import FlatModel + + result = self.execute(row) + combined = {**result.assignments} + if direct_values: + combined.update(direct_values) + return FlatModel(**combined) + + @staticmethod + def _process_condition( + node: ConditionNode, + row: dict[str, Any], + queue: deque[str], + ) -> None: + """Evaluate branches and enqueue the first matching target.""" + for branch in node.branches: + if _evaluate_condition(branch.condition, row): + queue.append(branch.target_node_id) + return + if node.default_target_id is not None: + queue.append(node.default_target_id) diff --git a/epinterface/sbem/decision_dag/fields.py b/epinterface/sbem/decision_dag/fields.py new file mode 100644 index 0000000..f4e3eb6 --- /dev/null +++ b/epinterface/sbem/decision_dag/fields.py @@ -0,0 +1,124 @@ +"""User field definitions for the decision DAG module. + +Defines the schema for users to describe their available data fields, +supplementary context, and building stock characteristics that will be +used by an LLM to generate a decision DAG. +""" + +from __future__ import annotations + +from enum import Enum + +from pydantic import BaseModel, Field, model_validator + + +class FieldType(str, Enum): + """The type of a user-provided data field.""" + + CATEGORICAL = "categorical" + NUMERIC = "numeric" + PLAINTEXT = "plaintext" + + +class UserFieldDefinition(BaseModel): + """A definition of a single field in the user's data. + + Describes the field's name, type, semantics, and data quality + so the LLM can make informed decisions about how to use it + in the decision DAG. + """ + + name: str = Field(description="Column/field name as it appears in the user's data.") + field_type: FieldType = Field( + description="Whether this field is categorical, numeric, or free-text." + ) + description: str = Field( + description="Plain English description of what this field represents." + ) + data_quality_description: str = Field( + default="", + description="Description of the data quality, completeness, and reliability of this field.", + ) + categories: list[str] | None = Field( + default=None, + description="Allowed category values (required for categorical fields).", + ) + min_value: float | None = Field( + default=None, + description="Minimum value (required for numeric fields).", + ) + max_value: float | None = Field( + default=None, + description="Maximum value (required for numeric fields).", + ) + unit: str | None = Field( + default=None, + description="Unit of measurement for numeric fields (e.g. 'm2K/W', 'years').", + ) + + @model_validator(mode="after") + def _check_type_specific_fields(self) -> UserFieldDefinition: + if self.field_type == FieldType.CATEGORICAL and not self.categories: + msg = f"Field '{self.name}': categorical fields must specify 'categories'." + raise ValueError(msg) + if self.field_type == FieldType.NUMERIC: + if self.min_value is None or self.max_value is None: + msg = f"Field '{self.name}': numeric fields must specify 'min_value' and 'max_value'." + raise ValueError(msg) + return self + + +class SupplementaryContext(BaseModel): + """An unstructured knowledge document that provides additional context to the LLM. + + Users can attach any number of these to describe their building stock + in detail. Content can be plain text, JSON, CSV, markdown, or any other + text-based format. + """ + + title: str = Field( + description="Short title for this context document (e.g. 'HVAC System Frequency Distribution')." + ) + content: str = Field(description="The context content in any text-based format.") + format_hint: str = Field( + default="plaintext", + description="Format of the content: 'plaintext', 'json', 'csv', 'markdown', etc.", + ) + + +class UserFieldSet(BaseModel): + """Complete specification of the user's available data and context. + + Combines field definitions with contextual information that helps + the LLM generate an appropriate decision DAG for the building stock. + """ + + fields: list[UserFieldDefinition] = Field( + description="Definitions of all data fields available in the user's dataset.", + ) + context_description: str = Field( + default="", + description="Overall project context and goals.", + ) + region_description: str = Field( + default="", + description="Geographic and climate context (e.g. 'Northeast US, IECC Climate Zone 5A').", + ) + building_stock_description: str = Field( + default="", + description="General description of the building stock characteristics.", + ) + supplementary_context: list[SupplementaryContext] = Field( + default_factory=list, + description="Additional unstructured knowledge documents about the building stock.", + ) + + @model_validator(mode="after") + def _check_unique_field_names(self) -> UserFieldSet: + names = [f.name for f in self.fields] + if len(names) != len(set(names)): + seen: set[str] = set() + dupes = [n for n in names if n in seen or seen.add(n)] # type: ignore[func-returns-value] + msg = f"Duplicate field names: {dupes}" + raise ValueError(msg) + return self diff --git a/epinterface/sbem/decision_dag/schema_utils.py b/epinterface/sbem/decision_dag/schema_utils.py new file mode 100644 index 0000000..665ec84 --- /dev/null +++ b/epinterface/sbem/decision_dag/schema_utils.py @@ -0,0 +1,264 @@ +"""FlatModel schema introspection and DAG assignment validation. + +Provides utilities to generate prompt-friendly descriptions of the +FlatModel schema for LLM consumption, and to validate that DAG +assignments reference valid fields with compatible values. +""" + +from __future__ import annotations + +import typing +from typing import Any, get_args, get_origin + +from pydantic.fields import FieldInfo + +from epinterface.sbem.decision_dag.dag import ( + AssignmentNode, + ComponentRefNode, + DecisionDAG, +) + +_FIELD_GROUPS: dict[str, list[str]] = { + "Equipment Schedule": [ + "EquipmentBase", + "EquipmentAMInterp", + "EquipmentLunchInterp", + "EquipmentPMInterp", + "EquipmentWeekendPeakInterp", + "EquipmentSummerPeakInterp", + ], + "Lighting Schedule": [ + "LightingBase", + "LightingAMInterp", + "LightingLunchInterp", + "LightingPMInterp", + "LightingWeekendPeakInterp", + "LightingSummerPeakInterp", + ], + "Occupancy Schedule": [ + "OccupancyBase", + "OccupancyAMInterp", + "OccupancyLunchInterp", + "OccupancyPMInterp", + "OccupancyWeekendPeakInterp", + "OccupancySummerPeakInterp", + ], + "Thermostat Setpoints": [ + "HeatingSetpointBase", + "SetpointDeadband", + "HeatingSetpointSetback", + "CoolingSetpointSetback", + "NightSetback", + "WeekendSetback", + "SummerSetback", + ], + "HVAC Systems": [ + "HeatingFuel", + "CoolingFuel", + "HeatingSystemCOP", + "CoolingSystemCOP", + "HeatingDistributionCOP", + "CoolingDistributionCOP", + ], + "Space Use": [ + "EquipmentPowerDensity", + "LightingPowerDensity", + "OccupantDensity", + ], + "Ventilation": [ + "VentFlowRatePerPerson", + "VentFlowRatePerArea", + "VentProvider", + "VentHRV", + "VentEconomizer", + "VentDCV", + ], + "Domestic Hot Water": [ + "DHWFlowRatePerPerson", + "DHWFuel", + "DHWSystemCOP", + "DHWDistributionCOP", + ], + "Envelope": [ + "InfiltrationACH", + ], + "Windows": [ + "WindowUValue", + "WindowSHGF", + "WindowTVis", + ], + "Facade Construction": [ + "FacadeStructuralSystem", + "FacadeCavityInsulationRValue", + "FacadeExteriorInsulationRValue", + "FacadeInteriorInsulationRValue", + "FacadeInteriorFinish", + "FacadeExteriorFinish", + ], + "Roof Construction": [ + "RoofStructuralSystem", + "RoofCavityInsulationRValue", + "RoofExteriorInsulationRValue", + "RoofInteriorInsulationRValue", + "RoofInteriorFinish", + "RoofExteriorFinish", + ], + "Slab Construction": [ + "SlabStructuralSystem", + "SlabInsulationRValue", + "SlabInsulationPlacement", + "SlabInteriorFinish", + "SlabExteriorFinish", + ], + "Geometry": [ + "WWR", + "F2FHeight", + "NFloors", + "Width", + "Depth", + "Rotation", + ], + "Weather": [ + "EPWURI", + ], +} + +GEOMETRY_AND_WEATHER_FIELDS = { + "WWR", + "F2FHeight", + "NFloors", + "Width", + "Depth", + "Rotation", + "EPWURI", +} +"""Fields typically provided directly rather than through the DAG.""" + + +def _get_literal_values(annotation: Any) -> list[str] | None: + """Extract allowed values from a Literal type annotation.""" + origin = get_origin(annotation) + if origin is typing.Literal: + return list(get_args(annotation)) + args = get_args(annotation) + for arg in args: + if get_origin(arg) is typing.Literal: + return list(get_args(arg)) + return None + + +def _describe_field(name: str, info: FieldInfo, annotation: Any) -> str: + """Produce a one-line description of a single FlatModel field.""" + parts: list[str] = [f" - {name}"] + + literal_vals = _get_literal_values(annotation) + if literal_vals is not None: + parts.append(f"(one of: {literal_vals})") + else: + origin = get_origin(annotation) + if origin is typing.Union: + type_names = [ + a.__name__ if hasattr(a, "__name__") else str(a) + for a in get_args(annotation) + ] + parts.append(f"({' | '.join(type_names)})") + elif hasattr(annotation, "__name__"): + parts.append(f"({annotation.__name__})") + else: + parts.append(f"({annotation})") + + constraints: list[str] = [] + for attr in ("ge", "gt", "le", "lt"): + val = info.metadata and next( + (getattr(m, attr, None) for m in info.metadata if hasattr(m, attr)), + None, + ) + if val is not None: + constraints.append(f"{attr}={val}") + if constraints: + parts.append(f"[{', '.join(constraints)}]") + + if info.default is not None and info.default is not ...: + parts.append(f"default={info.default}") + + if info.description: + parts.append(f"-- {info.description}") + + return " ".join(parts) + + +def get_flat_model_schema_description() -> str: + """Introspect FlatModel and return a structured, prompt-friendly description. + + Groups fields by category and includes type info, constraints, + defaults, and descriptions for each field. + """ + from epinterface.sbem.flat_model import FlatModel + + lines: list[str] = ["# FlatModel Parameters", ""] + + all_fields = FlatModel.model_fields + type_hints = typing.get_type_hints(FlatModel) + grouped_names: set[str] = set() + + for group_name, field_names in _FIELD_GROUPS.items(): + lines.append(f"## {group_name}") + for fname in field_names: + if fname in all_fields: + lines.append( + _describe_field(fname, all_fields[fname], type_hints.get(fname)) + ) + grouped_names.add(fname) + lines.append("") + + ungrouped = set(all_fields.keys()) - grouped_names + if ungrouped: + lines.append("## Other") + for fname in sorted(ungrouped): + lines.append( + _describe_field(fname, all_fields[fname], type_hints.get(fname)) + ) + lines.append("") + + return "\n".join(lines) + + +def get_flat_model_field_names() -> set[str]: + """Return the set of all valid FlatModel field names.""" + from epinterface.sbem.flat_model import FlatModel + + return set(FlatModel.model_fields.keys()) + + +def validate_dag_assignments(dag: DecisionDAG) -> list[str]: + """Validate that all assignments in the DAG reference valid FlatModel fields. + + Returns a list of error messages (empty if everything is valid). + Does not check value types/constraints -- that is handled at + FlatModel construction time. + """ + valid_fields = get_flat_model_field_names() + errors: list[str] = [] + + for node in dag.nodes: + if isinstance(node, AssignmentNode): + for field_name in node.assignments: + if field_name not in valid_fields: + errors.append( + f"AssignmentNode '{node.id}': unknown FlatModel field '{field_name}'." + ) + elif isinstance(node, ComponentRefNode): + comp_ids = {c.id for c in dag.components} + if node.component_id not in comp_ids: + errors.append( + f"ComponentRefNode '{node.id}': references unknown component '{node.component_id}'." + ) + + for comp in dag.components: + for field_name in comp.assignments: + if field_name not in valid_fields: + errors.append( + f"IntermediateComponent '{comp.id}': unknown FlatModel field '{field_name}'." + ) + + return errors diff --git a/epinterface/sbem/decision_dag/validation.py b/epinterface/sbem/decision_dag/validation.py new file mode 100644 index 0000000..3fda3fc --- /dev/null +++ b/epinterface/sbem/decision_dag/validation.py @@ -0,0 +1,237 @@ +"""Structural validation of a DecisionDAG. + +Checks graph integrity, reference consistency, acyclicity, +field existence, and parameter coverage. +""" + +from __future__ import annotations + +from collections import deque +from typing import Any + +from epinterface.sbem.decision_dag.dag import ( + AssignmentNode, + ComponentRefNode, + ConditionNode, + DecisionDAG, +) +from epinterface.sbem.decision_dag.fields import UserFieldSet +from epinterface.sbem.decision_dag.schema_utils import ( + GEOMETRY_AND_WEATHER_FIELDS, + get_flat_model_field_names, + validate_dag_assignments, +) + + +def validate_dag_structure( + dag: DecisionDAG, + field_set: UserFieldSet | None = None, + require_full_coverage: bool = False, +) -> list[str]: + """Run all structural validation checks on a DAG. + + Args: + dag: The decision DAG to validate. + field_set: If provided, validates that all field references in + conditions exist in the user's field set. + require_full_coverage: If True, checks that every non-geometry/weather + FlatModel field is assigned on at least one path. + + Returns: + A list of error messages (empty if valid). + """ + errors: list[str] = [] + + errors.extend(_validate_node_refs(dag)) + errors.extend(_validate_entry_nodes(dag)) + errors.extend(_validate_component_refs(dag)) + errors.extend(_validate_acyclic(dag)) + errors.extend(validate_dag_assignments(dag)) + + if field_set is not None: + errors.extend(_validate_field_refs(dag, field_set)) + + if require_full_coverage: + errors.extend(_validate_coverage(dag)) + + return errors + + +def _validate_node_refs(dag: DecisionDAG) -> list[str]: + """Check that all target_node_id and next_node_ids reference existing nodes.""" + errors: list[str] = [] + node_ids = {n.id for n in dag.nodes} + + for node in dag.nodes: + if isinstance(node, ConditionNode): + for branch in node.branches: + if branch.target_node_id not in node_ids: + errors.append( + f"ConditionNode '{node.id}': branch target '{branch.target_node_id}' does not exist." + ) + if node.default_target_id and node.default_target_id not in node_ids: + errors.append( + f"ConditionNode '{node.id}': default target '{node.default_target_id}' does not exist." + ) + elif isinstance(node, (AssignmentNode, ComponentRefNode)): + for nid in node.next_node_ids: + if nid not in node_ids: + errors.append( + f"Node '{node.id}': next_node_id '{nid}' does not exist." + ) + + return errors + + +def _validate_entry_nodes(dag: DecisionDAG) -> list[str]: + """Check that all entry_node_ids reference existing nodes.""" + errors: list[str] = [] + node_ids = {n.id for n in dag.nodes} + for eid in dag.entry_node_ids: + if eid not in node_ids: + errors.append(f"entry_node_id '{eid}' does not exist.") + return errors + + +def _validate_component_refs(dag: DecisionDAG) -> list[str]: + """Check that all ComponentRefNode.component_id values reference existing components.""" + errors: list[str] = [] + comp_ids = {c.id for c in dag.components} + for node in dag.nodes: + if isinstance(node, ComponentRefNode) and node.component_id not in comp_ids: + errors.append( + f"ComponentRefNode '{node.id}': references unknown component '{node.component_id}'." + ) + return errors + + +def _get_successors(node: Any) -> list[str]: + """Get all successor node IDs from a node.""" + if isinstance(node, ConditionNode): + targets = [b.target_node_id for b in node.branches] + if node.default_target_id: + targets.append(node.default_target_id) + return targets + if isinstance(node, (AssignmentNode, ComponentRefNode)): + return list(node.next_node_ids) + return [] + + +def _validate_acyclic(dag: DecisionDAG) -> list[str]: + """Check that the DAG has no cycles using DFS-based topological ordering.""" + errors: list[str] = [] + node_map = {n.id: n for n in dag.nodes} + + WHITE, GRAY, BLACK = 0, 1, 2 + color: dict[str, int] = dict.fromkeys(node_map, WHITE) + + def dfs(nid: str) -> bool: + color[nid] = GRAY + node = node_map.get(nid) + if node is not None: + for succ_id in _get_successors(node): + if succ_id not in color: + continue + if color[succ_id] == GRAY: + errors.append( + f"Cycle detected involving node '{nid}' -> '{succ_id}'." + ) + return True + if color[succ_id] == WHITE and dfs(succ_id): + return True + color[nid] = BLACK + return False + + for nid in node_map: + if color[nid] == WHITE: + dfs(nid) + + return errors + + +def _validate_field_refs(dag: DecisionDAG, field_set: UserFieldSet) -> list[str]: + """Check that all field references in conditions exist in the user's field set.""" + errors: list[str] = [] + user_fields = {f.name for f in field_set.fields} + + for node in dag.nodes: + if isinstance(node, ConditionNode): + for branch in node.branches: + if branch.condition.field not in user_fields: + errors.append( + f"ConditionNode '{node.id}': references unknown user field '{branch.condition.field}'." + ) + + return errors + + +def _validate_coverage(dag: DecisionDAG) -> list[str]: + """Check that every non-geometry/weather FlatModel field is assigned somewhere in the DAG. + + This is a conservative check: it verifies that each field appears + in at least one assignment node or component, not that every + execution path covers it. + """ + errors: list[str] = [] + required = get_flat_model_field_names() - GEOMETRY_AND_WEATHER_FIELDS + + assigned: set[str] = set() + for node in dag.nodes: + if isinstance(node, AssignmentNode): + assigned.update(node.assignments.keys()) + + comp_map = {c.id: c for c in dag.components} + for node in dag.nodes: + if isinstance(node, ComponentRefNode): + comp = comp_map.get(node.component_id) + if comp is not None: + assigned.update(comp.assignments.keys()) + + missing = sorted(required - assigned) + if missing: + errors.append(f"The following FlatModel fields are never assigned: {missing}") + + return errors + + +def _collect_reachable_assignments(dag: DecisionDAG) -> dict[str, set[str]]: + """For each entry node, collect the set of FlatModel fields potentially assigned. + + Traverses all possible paths via BFS (following all branches). + Returns a mapping of entry_node_id -> set of field names. + """ + node_map = {n.id: n for n in dag.nodes} + comp_map = {c.id: c for c in dag.components} + result: dict[str, set[str]] = {} + + for entry_id in dag.entry_node_ids: + fields: set[str] = set() + visited: set[str] = set() + queue: deque[str] = deque([entry_id]) + + while queue: + nid = queue.popleft() + if nid in visited: + continue + visited.add(nid) + node = node_map.get(nid) + if node is None: + continue + + if isinstance(node, AssignmentNode): + fields.update(node.assignments.keys()) + queue.extend(node.next_node_ids) + elif isinstance(node, ComponentRefNode): + comp = comp_map.get(node.component_id) + if comp is not None: + fields.update(comp.assignments.keys()) + queue.extend(node.next_node_ids) + elif isinstance(node, ConditionNode): + for branch in node.branches: + queue.append(branch.target_node_id) + if node.default_target_id: + queue.append(node.default_target_id) + + result[entry_id] = fields + + return result diff --git a/epinterface/sbem/decision_dag/visualize.py b/epinterface/sbem/decision_dag/visualize.py new file mode 100644 index 0000000..75237c8 --- /dev/null +++ b/epinterface/sbem/decision_dag/visualize.py @@ -0,0 +1,289 @@ +"""Visualize a DecisionDAG as a Markdown document with Mermaid diagrams. + +Generates a readable report including a graph diagram, component +inventory, validation results, and coverage analysis. +""" + +from __future__ import annotations + +from pathlib import Path + +import yaml + +from epinterface.sbem.decision_dag.dag import ( + AssignmentNode, + ComponentRefNode, + ConditionNode, + DecisionDAG, +) +from epinterface.sbem.decision_dag.fields import UserFieldSet +from epinterface.sbem.decision_dag.schema_utils import _FIELD_GROUPS +from epinterface.sbem.decision_dag.validation import ( + _collect_reachable_assignments, + validate_dag_structure, +) + + +def _sanitize_mermaid_id(node_id: str) -> str: + """Make a node ID safe for mermaid (no hyphens, dots, etc.).""" + return node_id.replace("-", "_").replace(".", "_").replace(" ", "_") + + +def _escape_mermaid_label(text: str) -> str: + """Escape a label string for safe use in mermaid node definitions.""" + return text.replace('"', "'").replace("\n", " ") + + +def _truncate(text: str, max_len: int = 50) -> str: + if len(text) <= max_len: + return text + return text[: max_len - 3] + "..." + + +def _build_mermaid_diagram(dag: DecisionDAG) -> str: + """Build a mermaid flowchart string from a DecisionDAG.""" + lines: list[str] = ["flowchart TD"] + + entry_set = set(dag.entry_node_ids) + comp_map = {c.id: c for c in dag.components} + + for node in dag.nodes: + sid = _sanitize_mermaid_id(node.id) + prefix = "ENTRY: " if node.id in entry_set else "" + + if isinstance(node, ConditionNode): + label = _escape_mermaid_label(f"{prefix}{node.description}") + lines.append(f" {sid}{{{{{label}}}}}") + + for i, branch in enumerate(node.branches): + tsid = _sanitize_mermaid_id(branch.target_node_id) + cond = branch.condition + if cond.value is not None: + edge_label = f"{cond.field} {cond.operator.value} {_truncate(str(cond.value), 30)}" + else: + edge_label = f"{cond.field} {cond.operator.value}" + edge_label = _escape_mermaid_label(edge_label) + lines.append(f' {sid} -->|"{edge_label}"| {tsid}') + + if node.default_target_id: + dsid = _sanitize_mermaid_id(node.default_target_id) + lines.append(f' {sid} -->|"default"| {dsid}') + + elif isinstance(node, AssignmentNode): + n_fields = len(node.assignments) + label = _escape_mermaid_label( + f"{prefix}{node.description} ({n_fields} fields)" + ) + lines.append(f' {sid}["{label}"]') + + for nid in node.next_node_ids: + lines.append(f" {sid} --> {_sanitize_mermaid_id(nid)}") + + elif isinstance(node, ComponentRefNode): + comp = comp_map.get(node.component_id) + comp_name = comp.name if comp else node.component_id + n_fields = len(comp.assignments) if comp else "?" + label = _escape_mermaid_label(f"{prefix}{comp_name} ({n_fields} fields)") + lines.append(f' {sid}(["{label}"])') + + for nid in node.next_node_ids: + lines.append(f" {sid} --> {_sanitize_mermaid_id(nid)}") + + return "\n".join(lines) + + +def _build_component_table(dag: DecisionDAG) -> str: + """Build a markdown table summarizing intermediate components.""" + lines: list[str] = [ + "| ID | Name | Fields | Description |", + "|---|---|---|---|", + ] + for comp in dag.components: + field_list = ", ".join(f"`{k}`" for k in sorted(comp.assignments.keys())) + desc = _truncate(comp.description, 80) + lines.append(f"| `{comp.id}` | {comp.name} | {field_list} | {desc} |") + return "\n".join(lines) + + +def _build_component_details(dag: DecisionDAG) -> str: + """Build detailed component assignment listings.""" + sections: list[str] = [] + for comp in dag.components: + lines = [f"#### {comp.name} (`{comp.id}`)", "", comp.description, ""] + for k, v in comp.assignments.items(): + lines.append(f"- `{k}` = `{v}`") + lines.append("") + sections.append("\n".join(lines)) + return "\n".join(sections) + + +def _build_coverage_section(dag: DecisionDAG) -> str: + """Build a coverage analysis section showing which groups are assigned.""" + reachable = _collect_reachable_assignments(dag) + all_assigned: set[str] = set() + for fields in reachable.values(): + all_assigned.update(fields) + + lines: list[str] = [] + for group_name, field_names in _FIELD_GROUPS.items(): + covered = [f for f in field_names if f in all_assigned] + missing = [f for f in field_names if f not in all_assigned] + total = len(field_names) + n_covered = len(covered) + + if n_covered == total: + status = "FULL" + elif n_covered == 0: + status = "NONE" + else: + status = "PARTIAL" + + lines.append(f"- **{group_name}**: {n_covered}/{total} ({status})") + if missing and status != "NONE": + lines.append(f" - Missing: {', '.join(f'`{f}`' for f in missing)}") + + return "\n".join(lines) + + +def _build_validation_section(dag: DecisionDAG, field_set: UserFieldSet | None) -> str: + """Build a validation results section.""" + errors = validate_dag_structure( + dag, field_set=field_set, require_full_coverage=True + ) + if not errors: + return "All structural validation checks passed." + + lines = [f"Found **{len(errors)}** issue(s):", ""] + for e in errors: + lines.append(f"- {e}") + return "\n".join(lines) + + +def _build_node_inventory(dag: DecisionDAG) -> str: + """Build a summary of all nodes.""" + entry_set = set(dag.entry_node_ids) + lines: list[str] = [ + "| ID | Type | Description | Entry? |", + "|---|---|---|---|", + ] + for node in dag.nodes: + ntype = node.node_type + desc = _truncate(node.description, 60) + entry = "yes" if node.id in entry_set else "" + lines.append(f"| `{node.id}` | {ntype} | {desc} | {entry} |") + return "\n".join(lines) + + +def visualize_dag( + dag: DecisionDAG, + field_set: UserFieldSet | None = None, +) -> str: + """Generate a Markdown document visualizing a DecisionDAG. + + Args: + dag: The decision DAG to visualize. + field_set: Optional user field set for validation context. + + Returns: + A complete Markdown string with mermaid diagrams and analysis. + """ + sections: list[str] = [] + + sections.append("# Decision DAG Visualization") + sections.append("") + sections.append(f"> {dag.description}") + sections.append("") + + sections.append("## Summary") + sections.append("") + sections.append(f"- **Components**: {len(dag.components)}") + sections.append(f"- **Nodes**: {len(dag.nodes)}") + n_condition = sum(1 for n in dag.nodes if isinstance(n, ConditionNode)) + n_assign = sum(1 for n in dag.nodes if isinstance(n, AssignmentNode)) + n_ref = sum(1 for n in dag.nodes if isinstance(n, ComponentRefNode)) + sections.append( + f" - Condition: {n_condition}, Assignment: {n_assign}, ComponentRef: {n_ref}" + ) + sections.append( + f"- **Entry points**: {len(dag.entry_node_ids)} ({', '.join(f'`{e}`' for e in dag.entry_node_ids)})" + ) + sections.append("") + + sections.append("## Graph") + sections.append("") + sections.append("```mermaid") + sections.append(_build_mermaid_diagram(dag)) + sections.append("```") + sections.append("") + + sections.append("## Node Inventory") + sections.append("") + sections.append(_build_node_inventory(dag)) + sections.append("") + + sections.append("## Intermediate Components") + sections.append("") + sections.append(_build_component_table(dag)) + sections.append("") + + sections.append("### Component Details") + sections.append("") + sections.append(_build_component_details(dag)) + + sections.append("## Parameter Coverage") + sections.append("") + sections.append(_build_coverage_section(dag)) + sections.append("") + + sections.append("## Validation") + sections.append("") + sections.append(_build_validation_section(dag, field_set)) + sections.append("") + + if field_set is not None: + sections.append("## User Fields") + sections.append("") + for f in field_set.fields: + sections.append(f"- **{f.name}** ({f.field_type.value}): {f.description}") + if f.data_quality_description: + sections.append(f" - Data quality: {f.data_quality_description}") + sections.append("") + + return "\n".join(sections) + + +def visualize_dag_from_files( + dag_path: str | Path, + field_set_path: str | Path | None = None, + output_path: str | Path | None = None, +) -> str: + """Load a DAG and optional field set from files, generate visualization. + + Args: + dag_path: Path to a DecisionDAG JSON file. + field_set_path: Optional path to a UserFieldSet YAML file. + output_path: Optional path to write the output Markdown. + If None, defaults to the same directory as dag_path + with the name ``visualized_dag.md``. + + Returns: + The generated Markdown string. + """ + dag_path = Path(dag_path) + dag = DecisionDAG.model_validate_json(dag_path.read_text()) + + field_set: UserFieldSet | None = None + if field_set_path is not None: + field_set_path = Path(field_set_path) + raw = yaml.safe_load(field_set_path.read_text()) + field_set = UserFieldSet.model_validate(raw) + + md = visualize_dag(dag, field_set=field_set) + + if output_path is None: + output_path = dag_path.parent / "visualized_dag.md" + else: + output_path = Path(output_path) + + output_path.write_text(md, encoding="utf-8") + return md diff --git a/epinterface/sbem/flat_model.py b/epinterface/sbem/flat_model.py index 36a0f0f..7e6161c 100644 --- a/epinterface/sbem/flat_model.py +++ b/epinterface/sbem/flat_model.py @@ -3,9 +3,9 @@ from collections.abc import Callable from pathlib import Path -from archetypal import IDF from pydantic import BaseModel, Field +from archetypal import IDF from epinterface.analysis.overheating import OverheatingAnalysisConfig from epinterface.geometry import ShoeboxGeometry from epinterface.sbem.builder import AtticAssumptions, BasementAssumptions, Model @@ -56,10 +56,6 @@ SemiFlatRoofConstruction, SemiFlatSlabConstruction, SemiFlatWallConstruction, - WallExteriorFinish, - WallInteriorFinish, - WallStructuralSystem, - build_envelope_assemblies, ) from epinterface.sbem.flat_constructions import ( SlabExteriorFinish as SlabExteriorFinishType, @@ -73,6 +69,12 @@ from epinterface.sbem.flat_constructions import ( SlabStructuralSystem as SlabStructuralSystemType, ) +from epinterface.sbem.flat_constructions import ( + WallExteriorFinish, + WallInteriorFinish, + WallStructuralSystem, + build_envelope_assemblies, +) from epinterface.weather import WeatherUrl @@ -713,26 +715,98 @@ class FlatModel(BaseModel): # OccupancyRegularWeekendAfternoon: float = Field(ge=0, le=1) # OccupancyRegularWeekendEvening: float = Field(ge=0, le=1) - EquipmentBase: float = Field(ge=0, le=1) - EquipmentAMInterp: float = Field(ge=0, le=1) - EquipmentLunchInterp: float = Field(ge=0, le=1) - EquipmentPMInterp: float = Field(ge=0, le=1) - EquipmentWeekendPeakInterp: float = Field(ge=0, le=1) - EquipmentSummerPeakInterp: float = Field(ge=0, le=1) - - LightingBase: float = Field(ge=0, le=1) - LightingAMInterp: float = Field(ge=0, le=1) - LightingLunchInterp: float = Field(ge=0, le=1) - LightingPMInterp: float = Field(ge=0, le=1) - LightingWeekendPeakInterp: float = Field(ge=0, le=1) - LightingSummerPeakInterp: float = Field(ge=0, le=1) - - OccupancyBase: float = Field(ge=0, le=1) - OccupancyAMInterp: float = Field(ge=0, le=1) - OccupancyLunchInterp: float = Field(ge=0, le=1) - OccupancyPMInterp: float = Field(ge=0, le=1) - OccupancyWeekendPeakInterp: float = Field(ge=0, le=1) - OccupancySummerPeakInterp: float = Field(ge=0, le=1) + EquipmentBase: float = Field( + ge=0, + le=1, + description="Overnight baseload fraction for equipment schedule [0-1].", + ) + EquipmentAMInterp: float = Field( + ge=0, + le=1, + description="Morning peak interpolation fraction for equipment schedule (6-9am) [0-1].", + ) + EquipmentLunchInterp: float = Field( + ge=0, + le=1, + description="Lunch period interpolation fraction for equipment schedule (12-1pm) [0-1].", + ) + EquipmentPMInterp: float = Field( + ge=0, + le=1, + description="Evening peak interpolation fraction for equipment schedule (6-8pm) [0-1].", + ) + EquipmentWeekendPeakInterp: float = Field( + ge=0, + le=1, + description="Weekend peak interpolation fraction for equipment schedule [0-1].", + ) + EquipmentSummerPeakInterp: float = Field( + ge=0, + le=1, + description="Summer peak interpolation fraction for equipment schedule [0-1].", + ) + + LightingBase: float = Field( + ge=0, + le=1, + description="Overnight baseload fraction for lighting schedule [0-1].", + ) + LightingAMInterp: float = Field( + ge=0, + le=1, + description="Morning peak interpolation fraction for lighting schedule (6-9am) [0-1].", + ) + LightingLunchInterp: float = Field( + ge=0, + le=1, + description="Lunch period interpolation fraction for lighting schedule (12-1pm) [0-1].", + ) + LightingPMInterp: float = Field( + ge=0, + le=1, + description="Evening peak interpolation fraction for lighting schedule (6-8pm) [0-1].", + ) + LightingWeekendPeakInterp: float = Field( + ge=0, + le=1, + description="Weekend peak interpolation fraction for lighting schedule [0-1].", + ) + LightingSummerPeakInterp: float = Field( + ge=0, + le=1, + description="Summer peak interpolation fraction for lighting schedule [0-1].", + ) + + OccupancyBase: float = Field( + ge=0, + le=1, + description="Overnight baseload fraction for occupancy schedule [0-1].", + ) + OccupancyAMInterp: float = Field( + ge=0, + le=1, + description="Morning peak interpolation fraction for occupancy schedule (6-9am) [0-1].", + ) + OccupancyLunchInterp: float = Field( + ge=0, + le=1, + description="Lunch period interpolation fraction for occupancy schedule (12-1pm) [0-1].", + ) + OccupancyPMInterp: float = Field( + ge=0, + le=1, + description="Evening peak interpolation fraction for occupancy schedule (6-8pm) [0-1].", + ) + OccupancyWeekendPeakInterp: float = Field( + ge=0, + le=1, + description="Weekend peak interpolation fraction for occupancy schedule [0-1].", + ) + OccupancySummerPeakInterp: float = Field( + ge=0, + le=1, + description="Summer peak interpolation fraction for occupancy schedule [0-1].", + ) # HSPRegularWeekdayWorkhours: float = Field(ge=0, le=23) # HSPRegularWeekdayNight: float = Field(ge=0, le=23) @@ -748,71 +822,180 @@ class FlatModel(BaseModel): # CSPWeekendWorkhours: float = Field(ge=20, le=30) # CSPWeekendNight: float = Field(ge=20, le=30) - HeatingSetpointBase: float = Field(ge=0, le=23) - SetpointDeadband: float = Field(ge=0, le=10) - HeatingSetpointSetback: float = Field(ge=0, le=10) - CoolingSetpointSetback: float = Field(ge=0, le=10) - NightSetback: float = Field(ge=0, le=1) - WeekendSetback: float = Field(ge=0, le=1) - SummerSetback: float = Field(ge=0, le=1) + HeatingSetpointBase: float = Field( + ge=0, le=23, description="Base heating setpoint temperature [degC]." + ) + SetpointDeadband: float = Field( + ge=0, + le=10, + description="Temperature deadband between heating and cooling setpoints [degC].", + ) + HeatingSetpointSetback: float = Field( + ge=0, + le=10, + description="Heating setpoint setback amount during unoccupied periods [degC].", + ) + CoolingSetpointSetback: float = Field( + ge=0, + le=10, + description="Cooling setpoint setback amount during unoccupied periods [degC].", + ) + NightSetback: float = Field( + ge=0, + le=1, + description="Night setback factor applied to thermostat schedules [0-1].", + ) + WeekendSetback: float = Field( + ge=0, + le=1, + description="Weekend setback factor applied to thermostat schedules [0-1].", + ) + SummerSetback: float = Field( + ge=0, + le=1, + description="Summer setback factor applied to thermostat schedules [0-1].", + ) + + HeatingFuel: FuelType = Field(description="Fuel type for the heating system.") + CoolingFuel: FuelType = Field(description="Fuel type for the cooling system.") + HeatingSystemCOP: float = Field( + description="Coefficient of performance for the heating system [dimensionless]." + ) + CoolingSystemCOP: float = Field( + description="Coefficient of performance for the cooling system [dimensionless]." + ) + HeatingDistributionCOP: float = Field( + description="Distribution efficiency for the heating system [dimensionless, 0-1]." + ) + CoolingDistributionCOP: float = Field( + description="Distribution efficiency for the cooling system [dimensionless, 0-1]." + ) + + EquipmentPowerDensity: float = Field( + ge=0, le=200, description="Internal equipment power density [W/m2]." + ) + LightingPowerDensity: float = Field( + ge=0, le=100, description="Lighting power density [W/m2]." + ) + OccupantDensity: float = Field( + ge=0, le=50, description="Occupant density [people/m2]." + ) + + VentFlowRatePerPerson: float = Field( + description="Outdoor air ventilation flow rate per person [m3/s/person]." + ) + VentFlowRatePerArea: float = Field( + description="Outdoor air ventilation flow rate per floor area [m3/s/m2]." + ) + VentProvider: VentilationProvider = Field( + description="Ventilation provider type (None, Natural, Mechanical, or Both)." + ) + VentHRV: HRVMethod = Field( + description="Heat recovery ventilation method (NoHRV, Sensible, or Enthalpy)." + ) + VentEconomizer: EconomizerMethod = Field( + description="Economizer method (NoEconomizer, DifferentialDryBulb, or DifferentialEnthalpy)." + ) + VentDCV: DCVMethod = Field( + description="Demand-controlled ventilation method (NoDCV, OccupancySchedule, or CO2Setpoint)." + ) + + DHWFlowRatePerPerson: float = Field( + description="Domestic hot water flow rate per person [m3/s/person]." + ) + DHWFuel: DHWFuelType = Field( + description="Fuel type for the domestic hot water system." + ) + DHWSystemCOP: float = Field( + description="Coefficient of performance for the DHW system [dimensionless]." + ) + DHWDistributionCOP: float = Field( + description="Distribution efficiency for the DHW system [dimensionless, 0-1]." + ) + + InfiltrationACH: float = Field( + description="Envelope infiltration rate [air changes per hour]." + ) + + WindowUValue: float = Field(description="Window assembly U-value [W/m2K].") + WindowSHGF: float = Field(description="Window solar heat gain factor [0-1].") + WindowTVis: float = Field(description="Window visible light transmittance [0-1].") - HeatingFuel: FuelType - CoolingFuel: FuelType - HeatingSystemCOP: float - CoolingSystemCOP: float - HeatingDistributionCOP: float - CoolingDistributionCOP: float - - EquipmentPowerDensity: float = Field(ge=0, le=200) - LightingPowerDensity: float = Field(ge=0, le=100) - OccupantDensity: float = Field(ge=0, le=50) - - VentFlowRatePerPerson: float - VentFlowRatePerArea: float - VentProvider: VentilationProvider - VentHRV: HRVMethod - VentEconomizer: EconomizerMethod - VentDCV: DCVMethod - - DHWFlowRatePerPerson: float - DHWFuel: DHWFuelType - DHWSystemCOP: float - DHWDistributionCOP: float - - InfiltrationACH: float - - WindowUValue: float - WindowSHGF: float - WindowTVis: float - - FacadeStructuralSystem: WallStructuralSystem = "cmu" - FacadeCavityInsulationRValue: float = Field(default=0, ge=0) - FacadeExteriorInsulationRValue: float = Field(default=0, ge=0) - FacadeInteriorInsulationRValue: float = Field(default=0, ge=0) - FacadeInteriorFinish: WallInteriorFinish = "drywall" - FacadeExteriorFinish: WallExteriorFinish = "none" - - RoofStructuralSystem: RoofStructuralSystemType = "poured_concrete" - RoofCavityInsulationRValue: float = Field(default=0, ge=0) - RoofExteriorInsulationRValue: float = Field(default=2.5, ge=0) - RoofInteriorInsulationRValue: float = Field(default=0, ge=0) - RoofInteriorFinish: RoofInteriorFinishType = "gypsum_board" - RoofExteriorFinish: RoofExteriorFinishType = "epdm_membrane" - - SlabStructuralSystem: SlabStructuralSystemType = "slab_on_grade" - SlabInsulationRValue: float = Field(default=1.5, ge=0) - SlabInsulationPlacement: SlabInsulationPlacementType = "auto" - SlabInteriorFinish: SlabInteriorFinishType = "tile" - SlabExteriorFinish: SlabExteriorFinishType = "none" - - WWR: float - F2FHeight: float - NFloors: int - Width: float - Depth: float - Rotation: float - - EPWURI: WeatherUrl | Path + FacadeStructuralSystem: WallStructuralSystem = Field( + default="cmu", description="Structural system type for facade walls." + ) + FacadeCavityInsulationRValue: float = Field( + default=0, ge=0, description="Facade wall cavity insulation R-value [m2K/W]." + ) + FacadeExteriorInsulationRValue: float = Field( + default=0, + ge=0, + description="Facade wall exterior continuous insulation R-value [m2K/W].", + ) + FacadeInteriorInsulationRValue: float = Field( + default=0, ge=0, description="Facade wall interior insulation R-value [m2K/W]." + ) + FacadeInteriorFinish: WallInteriorFinish = Field( + default="drywall", description="Interior finish material for facade walls." + ) + FacadeExteriorFinish: WallExteriorFinish = Field( + default="none", + description="Exterior finish/cladding material for facade walls.", + ) + + RoofStructuralSystem: RoofStructuralSystemType = Field( + default="poured_concrete", + description="Structural system type for the roof assembly.", + ) + RoofCavityInsulationRValue: float = Field( + default=0, ge=0, description="Roof cavity insulation R-value [m2K/W]." + ) + RoofExteriorInsulationRValue: float = Field( + default=2.5, + ge=0, + description="Roof exterior continuous insulation R-value [m2K/W].", + ) + RoofInteriorInsulationRValue: float = Field( + default=0, ge=0, description="Roof interior insulation R-value [m2K/W]." + ) + RoofInteriorFinish: RoofInteriorFinishType = Field( + default="gypsum_board", + description="Interior finish material for the roof assembly.", + ) + RoofExteriorFinish: RoofExteriorFinishType = Field( + default="epdm_membrane", + description="Exterior finish/membrane for the roof assembly.", + ) + + SlabStructuralSystem: SlabStructuralSystemType = Field( + default="slab_on_grade", + description="Structural system type for the floor slab.", + ) + SlabInsulationRValue: float = Field( + default=1.5, ge=0, description="Slab insulation R-value [m2K/W]." + ) + SlabInsulationPlacement: SlabInsulationPlacementType = Field( + default="auto", + description="Placement of slab insulation (auto, under_slab, or above_slab).", + ) + SlabInteriorFinish: SlabInteriorFinishType = Field( + default="tile", description="Interior finish material for the floor slab." + ) + SlabExteriorFinish: SlabExteriorFinishType = Field( + default="none", + description="Exterior/underside finish material for the floor slab.", + ) + + WWR: float = Field(description="Window-to-wall ratio [0-1].") + F2FHeight: float = Field(description="Floor-to-floor height [m].") + NFloors: int = Field(description="Number of above-grade floors.") + Width: float = Field(description="Building width [m].") + Depth: float = Field(description="Building depth [m].") + Rotation: float = Field(description="Building rotation angle from north [degrees].") + + EPWURI: WeatherUrl | Path = Field( + description="EPW weather file URI or local file path." + ) @property def facade_wall(self) -> SemiFlatWallConstruction: @@ -1889,7 +2072,7 @@ def simulate( Rotation=45, WWR=0.3, NFloors=2, - FacadeStructuralSystem="cmu", + FacadeStructuralSystem="light_gauge_steel", FacadeCavityInsulationRValue=1.2, FacadeExteriorInsulationRValue=1.0, FacadeInteriorInsulationRValue=0.0, diff --git a/pyproject.toml b/pyproject.toml index 99876eb..ffa71bf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,10 +8,10 @@ authors = [ ] requires-python =">=3.10,<3.13" dependencies = [ - "archetypal==2.18.10", + "archetypal>=2.18.10", "click==8.1.7", "geopandas~=1.0.1", - "httpx~=0.27.2", + "httpx>=0.27.2", "ladybug-core>=0.44.30", "openpyxl~=3.1.5", "pandas>=2.2,<2.3", @@ -27,6 +27,9 @@ epi = "epinterface.cli:cli" # for extras [project.optional-dependencies] +llm = [ + "pydantic-ai>=1.62", +] [dependency-groups] dev = [ @@ -50,6 +53,7 @@ docs = [ [tool.uv.sources] # archetypal = { git = "https://github.com/samuelduchesne/archetypal", branch = "main" } +archetypal = { path = "archetypal" } [build-system] requires = ["hatchling"] diff --git a/tests/test_decision_dag/__init__.py b/tests/test_decision_dag/__init__.py new file mode 100644 index 0000000..c52f287 --- /dev/null +++ b/tests/test_decision_dag/__init__.py @@ -0,0 +1 @@ +"""Tests for the decision_dag module.""" diff --git a/tests/test_decision_dag/_last_dag.json b/tests/test_decision_dag/_last_dag.json new file mode 100644 index 0000000..edcef02 --- /dev/null +++ b/tests/test_decision_dag/_last_dag.json @@ -0,0 +1,570 @@ +{ + "description": "Decision DAG for Massachusetts (CZ5A) residential buildings. Organized into parallel sub-DAGs: (1) Weather default; (2) Schedules & internal loads by typology; (3) Thermostats; (4) Envelope by era with weatherization override; (5) Windows by era; (6) HVAC by era (dominant system) with deterministic mapping; (7) Ventilation by era/weatherization. Operators corrected to valid schema (eq, neq, lt, lte, gt, gte, in). All required FlatModel parameters are assigned via components on every path with sensible MA defaults.", + "components": [ + { + "id": "res_sched_sf", + "name": "Residential Schedule - Single Family", + "description": "Typical MA single-family occupancy patterns.", + "assignments": { + "EquipmentBase": 0.3, + "EquipmentAMInterp": 0.6, + "EquipmentLunchInterp": 0.5, + "EquipmentPMInterp": 0.9, + "EquipmentWeekendPeakInterp": 0.95, + "EquipmentSummerPeakInterp": 0.95, + "LightingBase": 0.1, + "LightingAMInterp": 0.5, + "LightingLunchInterp": 0.4, + "LightingPMInterp": 0.95, + "LightingWeekendPeakInterp": 0.95, + "LightingSummerPeakInterp": 0.9, + "OccupancyBase": 0.8, + "OccupancyAMInterp": 0.6, + "OccupancyLunchInterp": 0.5, + "OccupancyPMInterp": 0.95, + "OccupancyWeekendPeakInterp": 0.98, + "OccupancySummerPeakInterp": 0.98 + } + }, + { + "id": "res_sched_mf", + "name": "Residential Schedule - Multifamily", + "description": "Multifamily with slightly higher daytime occupancy.", + "assignments": { + "EquipmentBase": 0.35, + "EquipmentAMInterp": 0.65, + "EquipmentLunchInterp": 0.6, + "EquipmentPMInterp": 0.95, + "EquipmentWeekendPeakInterp": 0.98, + "EquipmentSummerPeakInterp": 0.98, + "LightingBase": 0.15, + "LightingAMInterp": 0.55, + "LightingLunchInterp": 0.5, + "LightingPMInterp": 0.98, + "LightingWeekendPeakInterp": 0.98, + "LightingSummerPeakInterp": 0.92, + "OccupancyBase": 0.85, + "OccupancyAMInterp": 0.7, + "OccupancyLunchInterp": 0.65, + "OccupancyPMInterp": 0.98, + "OccupancyWeekendPeakInterp": 0.99, + "OccupancySummerPeakInterp": 0.99 + } + }, + { + "id": "loads_sf", + "name": "Internal Loads - Single Family", + "description": "Typical MA single-family densities.", + "assignments": { + "EquipmentPowerDensity": 6.0, + "LightingPowerDensity": 5.0, + "OccupantDensity": 0.03, + "DHWFlowRatePerPerson": 0.00003 + } + }, + { + "id": "loads_mf", + "name": "Internal Loads - Multifamily", + "description": "Higher densities for multifamily.", + "assignments": { + "EquipmentPowerDensity": 7.5, + "LightingPowerDensity": 6.0, + "OccupantDensity": 0.05, + "DHWFlowRatePerPerson": 0.000035 + } + }, + { + "id": "thermostat_default", + "name": "Residential Thermostat Default", + "description": "Heating-dominated CZ5A residential setpoints.", + "assignments": { + "HeatingSetpointBase": 21.0, + "SetpointDeadband": 3.0, + "HeatingSetpointSetback": 3.0, + "CoolingSetpointSetback": 2.0, + "NightSetback": 0.9, + "WeekendSetback": 0.95, + "SummerSetback": 0.9 + } + }, + { + "id": "env_pre1940", + "name": "Envelope Pre-1940 Unweatherized", + "description": "Uninsulated, very leaky.", + "assignments": { + "FacadeStructuralSystem": "woodframe", + "FacadeCavityInsulationRValue": 0.5, + "FacadeExteriorInsulationRValue": 0.0, + "FacadeInteriorInsulationRValue": 0.0, + "InfiltrationACH": 1.1, + "RoofStructuralSystem": "light_wood_truss", + "RoofCavityInsulationRValue": 2.0, + "RoofExteriorInsulationRValue": 0.0, + "SlabStructuralSystem": "slab_on_grade", + "SlabInsulationRValue": 0.5 + } + }, + { + "id": "env_1940_1970", + "name": "Envelope 1940-1970 Unweatherized", + "description": "Minimal cavity insulation.", + "assignments": { + "FacadeStructuralSystem": "woodframe", + "FacadeCavityInsulationRValue": 1.5, + "FacadeExteriorInsulationRValue": 0.0, + "FacadeInteriorInsulationRValue": 0.0, + "InfiltrationACH": 0.7, + "RoofStructuralSystem": "light_wood_truss", + "RoofCavityInsulationRValue": 3.5, + "RoofExteriorInsulationRValue": 0.0, + "SlabStructuralSystem": "slab_on_grade", + "SlabInsulationRValue": 0.8 + } + }, + { + "id": "env_1970_2000", + "name": "Envelope 1970-2000 Unweatherized", + "description": "Improved cavity insulation.", + "assignments": { + "FacadeStructuralSystem": "woodframe", + "FacadeCavityInsulationRValue": 2.5, + "FacadeExteriorInsulationRValue": 0.5, + "FacadeInteriorInsulationRValue": 0.0, + "InfiltrationACH": 0.45, + "RoofStructuralSystem": "light_wood_truss", + "RoofCavityInsulationRValue": 5.0, + "RoofExteriorInsulationRValue": 0.5, + "SlabStructuralSystem": "slab_on_grade", + "SlabInsulationRValue": 1.2 + } + }, + { + "id": "env_post2000", + "name": "Envelope Post-2000 Code-Level", + "description": "IECC-era construction.", + "assignments": { + "FacadeStructuralSystem": "woodframe", + "FacadeCavityInsulationRValue": 3.5, + "FacadeExteriorInsulationRValue": 1.0, + "FacadeInteriorInsulationRValue": 0.0, + "InfiltrationACH": 0.25, + "RoofStructuralSystem": "light_wood_truss", + "RoofCavityInsulationRValue": 8.0, + "RoofExteriorInsulationRValue": 1.5, + "SlabStructuralSystem": "slab_on_grade", + "SlabInsulationRValue": 2.0 + } + }, + { + "id": "weatherization_upgrade", + "name": "Weatherization Upgrade", + "description": "Air sealing and insulation improvements.", + "assignments": { + "FacadeCavityInsulationRValue": 3.0, + "RoofCavityInsulationRValue": 8.0, + "SlabInsulationRValue": 1.5, + "InfiltrationACH": 0.5 + } + }, + { + "id": "windows_pre2000", + "name": "Windows Pre-2000 Double Pane", + "description": "Older double-pane.", + "assignments": { + "WindowUValue": 2.7, + "WindowSHGF": 0.55, + "WindowTVis": 0.6 + } + }, + { + "id": "windows_post2000", + "name": "Windows Post-2000 Low-E", + "description": "Low-e double pane.", + "assignments": { + "WindowUValue": 1.8, + "WindowSHGF": 0.4, + "WindowTVis": 0.55 + } + }, + { + "id": "hvac_gas_furnace", + "name": "Gas Furnace", + "description": "Standard gas furnace with AC.", + "assignments": { + "HeatingFuel": "NaturalGas", + "HeatingSystemCOP": 0.85, + "HeatingDistributionCOP": 0.8, + "CoolingFuel": "Electricity", + "CoolingSystemCOP": 3.0, + "CoolingDistributionCOP": 0.8, + "DHWFuel": "NaturalGas", + "DHWSystemCOP": 0.6, + "DHWDistributionCOP": 0.8 + } + }, + { + "id": "hvac_heat_pump", + "name": "Cold Climate Heat Pump", + "description": "Modern ASHP.", + "assignments": { + "HeatingFuel": "Electricity", + "HeatingSystemCOP": 3.0, + "HeatingDistributionCOP": 0.95, + "CoolingFuel": "Electricity", + "CoolingSystemCOP": 3.2, + "CoolingDistributionCOP": 0.95, + "DHWFuel": "Electricity", + "DHWSystemCOP": 2.5, + "DHWDistributionCOP": 0.9 + } + }, + { + "id": "vent_natural", + "name": "Natural Ventilation Only", + "description": "Infiltration-driven.", + "assignments": { + "VentFlowRatePerPerson": 0.0, + "VentFlowRatePerArea": 0.0002, + "VentProvider": "Natural", + "VentHRV": "NoHRV", + "VentEconomizer": "NoEconomizer", + "VentDCV": "NoDCV" + } + }, + { + "id": "vent_mech_exhaust", + "name": "Mechanical Exhaust", + "description": "Basic exhaust.", + "assignments": { + "VentFlowRatePerPerson": 0.0003, + "VentFlowRatePerArea": 0.0001, + "VentProvider": "Mechanical", + "VentHRV": "NoHRV", + "VentEconomizer": "NoEconomizer", + "VentDCV": "NoDCV" + } + }, + { + "id": "ma_weather", + "name": "Massachusetts Weather Default", + "description": "Boston Logan TMY3.", + "assignments": { + "EPWURI": "USA_MA_Boston-Logan.Intl.AP.725090_TMY3.epw" + } + } + ], + "nodes": [ + { + "node_type": "component_ref", + "id": "n_weather", + "description": "Apply MA weather.", + "component_id": "ma_weather", + "next_node_ids": [] + }, + { + "node_type": "condition", + "id": "n_typology_sched", + "description": "Schedule by typology.", + "branches": [ + { + "condition": { + "field": "building_typology", + "operator": "in", + "value": [ + "single_family_detached", + "single_family_attached" + ] + }, + "target_node_id": "n_sched_sf" + }, + { + "condition": { + "field": "building_typology", + "operator": "in", + "value": [ + "small_multifamily_2_4", + "medium_multifamily_5_20", + "large_multifamily_20_plus" + ] + }, + "target_node_id": "n_sched_mf" + } + ], + "default_target_id": "n_sched_sf" + }, + { + "node_type": "component_ref", + "id": "n_sched_sf", + "description": "SF schedule.", + "component_id": "res_sched_sf", + "next_node_ids": [] + }, + { + "node_type": "component_ref", + "id": "n_sched_mf", + "description": "MF schedule.", + "component_id": "res_sched_mf", + "next_node_ids": [] + }, + { + "node_type": "condition", + "id": "n_typology_loads", + "description": "Loads by typology.", + "branches": [ + { + "condition": { + "field": "building_typology", + "operator": "in", + "value": [ + "single_family_detached", + "single_family_attached" + ] + }, + "target_node_id": "n_loads_sf" + }, + { + "condition": { + "field": "building_typology", + "operator": "in", + "value": [ + "small_multifamily_2_4", + "medium_multifamily_5_20", + "large_multifamily_20_plus" + ] + }, + "target_node_id": "n_loads_mf" + } + ], + "default_target_id": "n_loads_sf" + }, + { + "node_type": "component_ref", + "id": "n_loads_sf", + "description": "SF loads.", + "component_id": "loads_sf", + "next_node_ids": [] + }, + { + "node_type": "component_ref", + "id": "n_loads_mf", + "description": "MF loads.", + "component_id": "loads_mf", + "next_node_ids": [] + }, + { + "node_type": "component_ref", + "id": "n_thermostat", + "description": "Thermostat defaults.", + "component_id": "thermostat_default", + "next_node_ids": [] + }, + { + "node_type": "condition", + "id": "n_year_env", + "description": "Envelope by era.", + "branches": [ + { + "condition": { + "field": "year_built", + "operator": "lt", + "value": 1940 + }, + "target_node_id": "n_env_pre1940" + }, + { + "condition": { + "field": "year_built", + "operator": "lt", + "value": 1970 + }, + "target_node_id": "n_env_1940_1970" + }, + { + "condition": { + "field": "year_built", + "operator": "lt", + "value": 2000 + }, + "target_node_id": "n_env_1970_2000" + }, + { + "condition": { + "field": "year_built", + "operator": "gte", + "value": 2000 + }, + "target_node_id": "n_env_post2000" + } + ], + "default_target_id": "n_env_1940_1970" + }, + { + "node_type": "component_ref", + "id": "n_env_pre1940", + "description": "Pre-1940 envelope.", + "component_id": "env_pre1940", + "next_node_ids": [ + "n_weatherization" + ] + }, + { + "node_type": "component_ref", + "id": "n_env_1940_1970", + "description": "1940-1970 envelope.", + "component_id": "env_1940_1970", + "next_node_ids": [ + "n_weatherization" + ] + }, + { + "node_type": "component_ref", + "id": "n_env_1970_2000", + "description": "1970-2000 envelope.", + "component_id": "env_1970_2000", + "next_node_ids": [ + "n_weatherization" + ] + }, + { + "node_type": "component_ref", + "id": "n_env_post2000", + "description": "Post-2000 envelope.", + "component_id": "env_post2000", + "next_node_ids": [ + "n_weatherization" + ] + }, + { + "node_type": "condition", + "id": "n_weatherization", + "description": "Weatherization override.", + "branches": [ + { + "condition": { + "field": "weatherization_status", + "operator": "eq", + "value": "weatherized" + }, + "target_node_id": "n_weatherized_apply" + } + ], + "default_target_id": "n_windows_by_year" + }, + { + "node_type": "component_ref", + "id": "n_weatherized_apply", + "description": "Apply weatherization.", + "component_id": "weatherization_upgrade", + "next_node_ids": [ + "n_windows_by_year" + ] + }, + { + "node_type": "condition", + "id": "n_windows_by_year", + "description": "Windows by era.", + "branches": [ + { + "condition": { + "field": "year_built", + "operator": "gte", + "value": 2000 + }, + "target_node_id": "n_windows_post2000" + } + ], + "default_target_id": "n_windows_pre2000" + }, + { + "node_type": "component_ref", + "id": "n_windows_pre2000", + "description": "Pre-2000 windows.", + "component_id": "windows_pre2000", + "next_node_ids": [] + }, + { + "node_type": "component_ref", + "id": "n_windows_post2000", + "description": "Post-2000 windows.", + "component_id": "windows_post2000", + "next_node_ids": [] + }, + { + "node_type": "condition", + "id": "n_hvac_by_year", + "description": "HVAC by era.", + "branches": [ + { + "condition": { + "field": "year_built", + "operator": "gte", + "value": 2000 + }, + "target_node_id": "n_hvac_post2000" + } + ], + "default_target_id": "n_hvac_gas" + }, + { + "node_type": "component_ref", + "id": "n_hvac_gas", + "description": "Gas furnace default.", + "component_id": "hvac_gas_furnace", + "next_node_ids": [] + }, + { + "node_type": "component_ref", + "id": "n_hvac_post2000", + "description": "Heat pump default.", + "component_id": "hvac_heat_pump", + "next_node_ids": [] + }, + { + "node_type": "condition", + "id": "n_vent_by_era", + "description": "Ventilation by era/weatherization.", + "branches": [ + { + "condition": { + "field": "year_built", + "operator": "gte", + "value": 2000 + }, + "target_node_id": "n_vent_mech" + }, + { + "condition": { + "field": "weatherization_status", + "operator": "eq", + "value": "weatherized" + }, + "target_node_id": "n_vent_mech" + } + ], + "default_target_id": "n_vent_nat" + }, + { + "node_type": "component_ref", + "id": "n_vent_nat", + "description": "Natural ventilation.", + "component_id": "vent_natural", + "next_node_ids": [] + }, + { + "node_type": "component_ref", + "id": "n_vent_mech", + "description": "Mechanical exhaust.", + "component_id": "vent_mech_exhaust", + "next_node_ids": [] + } + ], + "entry_node_ids": [ + "n_weather", + "n_typology_sched", + "n_typology_loads", + "n_thermostat", + "n_year_env", + "n_hvac_by_year", + "n_vent_by_era" + ] +} \ No newline at end of file diff --git a/tests/test_decision_dag/_last_user_field_set.yaml b/tests/test_decision_dag/_last_user_field_set.yaml new file mode 100644 index 0000000..96fc906 --- /dev/null +++ b/tests/test_decision_dag/_last_user_field_set.yaml @@ -0,0 +1,104 @@ +fields: +- name: income + field_type: numeric + description: Annual household income in USD. Correlates loosely with ability to + invest in energy upgrades. + data_quality_description: Self-reported on utility assistance applications. About + 30% of rows are missing. + categories: null + min_value: 0.0 + max_value: 500000.0 + unit: USD/year +- name: year_built + field_type: numeric + description: Year the building was originally constructed. + data_quality_description: From assessor records; generally reliable, though some + entries are approximate decades (e.g. 1900 for anything pre-1910). + categories: null + min_value: 1700.0 + max_value: 2025.0 + unit: year +- name: building_typology + field_type: categorical + description: Building typology classification from assessor data. + data_quality_description: Assessor-derived, reliable. + categories: + - single_family_detached + - single_family_attached + - small_multifamily_2_4 + - medium_multifamily_5_20 + - large_multifamily_20_plus + min_value: null + max_value: null + unit: null +- name: weatherization_status + field_type: categorical + description: Whether the building has been through a weatherization assistance program. + data_quality_description: From state WAP records. Only captures state-funded programs; + private weatherization is not tracked. About 60% of rows are missing (unknown + status). + categories: + - weatherized + - not_weatherized + - unknown + min_value: null + max_value: null + unit: null +- name: last_renovation + field_type: categorical + description: Approximate timeframe of last known major renovation or retrofit. + data_quality_description: From permit records where available. Very sparse -- roughly + 70% missing. + categories: + - never + - before_1980 + - '1980_2000' + - '2000_2010' + - 2010_present + min_value: null + max_value: null + unit: null +context_description: We are building energy models for a portfolio of ~5,000 residential + buildings in Massachusetts for a utility-funded energy efficiency program. The goal + is to estimate building energy use and identify retrofit opportunities. Data is + sparse and of mixed quality. +region_description: Massachusetts, USA. IECC Climate Zone 5A. Cold winters, warm humid + summers. Heating-dominated climate with ~5,500 HDD65 and ~700 CDD65. State energy + code is based on IECC 2021 for new construction. +building_stock_description: Predominantly older housing stock. Roughly 60% of buildings + were built before 1960. Mix of wood-frame (most common for single-family), triple-decker + multi-family (very common in urban MA), and some masonry construction in older urban + cores. Natural gas heating dominates (~65%), followed by oil (~20%), and electric/heat + pump (~15%). Many older buildings have minimal insulation, especially in walls. +supplementary_context: +- title: Heating System Distribution by Building Age + content: "{\n \"pre_1940\": {\n \"gas_furnace\": 0.45,\n \"oil_boiler\":\ + \ 0.35,\n \"steam\": 0.1,\n \"electric_resistance\": 0.05,\n \"heat_pump\"\ + : 0.05\n },\n \"1940_1970\": {\n \"gas_furnace\": 0.55,\n \"oil_boiler\"\ + : 0.25,\n \"electric_resistance\": 0.1,\n \"heat_pump\": 0.1\n },\n \"\ + 1970_2000\": {\n \"gas_furnace\": 0.6,\n \"oil_boiler\": 0.15,\n \"electric_resistance\"\ + : 0.1,\n \"heat_pump\": 0.15\n },\n \"post_2000\": {\n \"gas_furnace\"\ + : 0.4,\n \"oil_boiler\": 0.05,\n \"electric_resistance\": 0.05,\n \"\ + heat_pump\": 0.5\n }\n}" + format_hint: json +- title: Typical Wall Construction by Era + content: 'Pre-1940: Double-wythe brick or balloon-frame wood with no insulation, + plaster interior. Infiltration is very high (often 1.0+ ACH). + + 1940-1970: Platform-frame wood, often with minimal batt insulation (R-7 to R-11 + cavities), some with aluminum siding over original clapboard. Infiltration moderate + (0.5-0.8 ACH). + + 1970-2000: Wood frame with R-11 to R-19 cavity insulation, vinyl or wood siding, + some continuous insulation in later builds. Infiltration moderate (0.3-0.6 ACH). + + Post-2000: Wood frame with R-19+ cavity, often R-5 to R-10 continuous exterior + insulation, air sealing. Infiltration low (0.15-0.35 ACH).' + format_hint: plaintext +- title: Massachusetts Weatherization Program Notes + content: 'The MA WAP program typically performs: air sealing (blower-door guided), + attic insulation to R-38 minimum, wall insulation (dense-pack cellulose) where + feasible, and sometimes basement/crawlspace insulation. Weatherized homes see + roughly a 20-30% reduction in infiltration and improved wall/attic R-values compared + to un-weatherized homes of the same era.' + format_hint: plaintext diff --git a/tests/test_decision_dag/_last_user_message.txt b/tests/test_decision_dag/_last_user_message.txt new file mode 100644 index 0000000..83579e7 --- /dev/null +++ b/tests/test_decision_dag/_last_user_message.txt @@ -0,0 +1,92 @@ +## Project Context + +We are building energy models for a portfolio of ~5,000 residential buildings in Massachusetts for a utility-funded energy efficiency program. The goal is to estimate building energy use and identify retrofit opportunities. Data is sparse and of mixed quality. + +## Region & Climate + +Massachusetts, USA. IECC Climate Zone 5A. Cold winters, warm humid summers. Heating-dominated climate with ~5,500 HDD65 and ~700 CDD65. State energy code is based on IECC 2021 for new construction. + +## Building Stock + +Predominantly older housing stock. Roughly 60% of buildings were built before 1960. Mix of wood-frame (most common for single-family), triple-decker multi-family (very common in urban MA), and some masonry construction in older urban cores. Natural gas heating dominates (~65%), followed by oil (~20%), and electric/heat pump (~15%). Many older buildings have minimal insulation, especially in walls. + +## Available Data Fields + + +### income +- Type: numeric +- Description: Annual household income in USD. Correlates loosely with ability to invest in energy upgrades. +- Data quality: Self-reported on utility assistance applications. About 30% of rows are missing. +- Range: 0.0 to 500000.0 USD/year + +### year_built +- Type: numeric +- Description: Year the building was originally constructed. +- Data quality: From assessor records; generally reliable, though some entries are approximate decades (e.g. 1900 for anything pre-1910). +- Range: 1700.0 to 2025.0 year + +### building_typology +- Type: categorical +- Description: Building typology classification from assessor data. +- Data quality: Assessor-derived, reliable. +- Categories: ['single_family_detached', 'single_family_attached', 'small_multifamily_2_4', 'medium_multifamily_5_20', 'large_multifamily_20_plus'] + +### weatherization_status +- Type: categorical +- Description: Whether the building has been through a weatherization assistance program. +- Data quality: From state WAP records. Only captures state-funded programs; private weatherization is not tracked. About 60% of rows are missing (unknown status). +- Categories: ['weatherized', 'not_weatherized', 'unknown'] + +### last_renovation +- Type: categorical +- Description: Approximate timeframe of last known major renovation or retrofit. +- Data quality: From permit records where available. Very sparse -- roughly 70% missing. +- Categories: ['never', 'before_1980', '1980_2000', '2000_2010', '2010_present'] + +## Supplementary Context + + +### Heating System Distribution by Building Age (format: json) + +{ + "pre_1940": { + "gas_furnace": 0.45, + "oil_boiler": 0.35, + "steam": 0.1, + "electric_resistance": 0.05, + "heat_pump": 0.05 + }, + "1940_1970": { + "gas_furnace": 0.55, + "oil_boiler": 0.25, + "electric_resistance": 0.1, + "heat_pump": 0.1 + }, + "1970_2000": { + "gas_furnace": 0.6, + "oil_boiler": 0.15, + "electric_resistance": 0.1, + "heat_pump": 0.15 + }, + "post_2000": { + "gas_furnace": 0.4, + "oil_boiler": 0.05, + "electric_resistance": 0.05, + "heat_pump": 0.5 + } +} + +### Typical Wall Construction by Era (format: plaintext) + +Pre-1940: Double-wythe brick or balloon-frame wood with no insulation, plaster interior. Infiltration is very high (often 1.0+ ACH). +1940-1970: Platform-frame wood, often with minimal batt insulation (R-7 to R-11 cavities), some with aluminum siding over original clapboard. Infiltration moderate (0.5-0.8 ACH). +1970-2000: Wood frame with R-11 to R-19 cavity insulation, vinyl or wood siding, some continuous insulation in later builds. Infiltration moderate (0.3-0.6 ACH). +Post-2000: Wood frame with R-19+ cavity, often R-5 to R-10 continuous exterior insulation, air sealing. Infiltration low (0.15-0.35 ACH). + +### Massachusetts Weatherization Program Notes (format: plaintext) + +The MA WAP program typically performs: air sealing (blower-door guided), attic insulation to R-38 minimum, wall insulation (dense-pack cellulose) where feasible, and sometimes basement/crawlspace insulation. Weatherized homes see roughly a 20-30% reduction in infiltration and improved wall/attic R-values compared to un-weatherized homes of the same era. + +## Task + +Based on the above field definitions, context, and supplementary information, create a DecisionDAG that maps these user data fields to all required FlatModel parameters. Use intermediate components for common parameter bundles, handle missing data gracefully, and apply regionally appropriate defaults. \ No newline at end of file diff --git a/tests/test_decision_dag/test_dag.py b/tests/test_decision_dag/test_dag.py new file mode 100644 index 0000000..20c7419 --- /dev/null +++ b/tests/test_decision_dag/test_dag.py @@ -0,0 +1,214 @@ +"""Tests for decision_dag.dag module -- serialization and schema validation.""" + +import pytest + +from epinterface.sbem.decision_dag.dag import ( + AssignmentNode, + ComparisonOperator, + ComponentRefNode, + ConditionalBranch, + ConditionNode, + DecisionDAG, + FieldCondition, + IntermediateComponent, +) + + +class TestFieldCondition: + """Tests for FieldCondition.""" + + def test_eq_condition(self): + cond = FieldCondition( + field="building_type", + operator=ComparisonOperator.EQ, + value="residential", + ) + assert cond.field == "building_type" + assert cond.operator == ComparisonOperator.EQ + + def test_is_missing_no_value_needed(self): + cond = FieldCondition( + field="renovation_year", + operator=ComparisonOperator.IS_MISSING, + ) + assert cond.value is None + + def test_numeric_comparison(self): + cond = FieldCondition( + field="year_built", + operator=ComparisonOperator.LTE, + value=1950, + ) + assert cond.value == 1950 + + +class TestNodes: + """Tests for DAG node types.""" + + def test_condition_node(self): + node = ConditionNode( + id="check_type", + description="Check building type", + branches=[ + ConditionalBranch( + condition=FieldCondition( + field="building_type", + operator=ComparisonOperator.EQ, + value="residential", + ), + target_node_id="residential_path", + ), + ], + default_target_id="default_path", + ) + assert node.node_type == "condition" + assert len(node.branches) == 1 + + def test_assignment_node(self): + node = AssignmentNode( + id="set_defaults", + description="Set default HVAC parameters", + assignments={ + "HeatingFuel": "NaturalGas", + "HeatingSystemCOP": 0.85, + }, + next_node_ids=["next_step"], + ) + assert node.node_type == "assignment" + assert node.assignments["HeatingFuel"] == "NaturalGas" + + def test_component_ref_node(self): + node = ComponentRefNode( + id="apply_wall", + description="Apply high-perf wall component", + component_id="high_perf_wall", + next_node_ids=[], + ) + assert node.node_type == "component_ref" + + def test_assignment_node_default_next_nodes(self): + node = AssignmentNode( + id="leaf", + description="Terminal assignment", + assignments={"InfiltrationACH": 0.5}, + ) + assert node.next_node_ids == [] + + +class TestIntermediateComponent: + """Tests for IntermediateComponent.""" + + def test_create_component(self): + comp = IntermediateComponent( + id="old_leaky_wall", + name="Old Leaky SF Wall", + description="Pre-1950 uninsulated wood frame wall", + assignments={ + "FacadeStructuralSystem": "woodframe", + "FacadeCavityInsulationRValue": 0.0, + "FacadeExteriorInsulationRValue": 0.0, + "InfiltrationACH": 1.2, + }, + ) + assert comp.name == "Old Leaky SF Wall" + assert len(comp.assignments) == 4 + + +class TestDecisionDAG: + """Tests for DecisionDAG serialization and structure.""" + + @pytest.fixture() + def simple_dag(self) -> DecisionDAG: + """A minimal DAG for testing.""" + return DecisionDAG( + description="Simple test DAG", + components=[ + IntermediateComponent( + id="default_envelope", + name="Default Envelope", + description="Baseline envelope assumptions", + assignments={ + "FacadeStructuralSystem": "cmu", + "FacadeCavityInsulationRValue": 2.0, + "InfiltrationACH": 0.6, + }, + ), + ], + nodes=[ + ConditionNode( + id="check_age", + description="Check building age", + branches=[ + ConditionalBranch( + condition=FieldCondition( + field="year_built", + operator=ComparisonOperator.LTE, + value=1960, + ), + target_node_id="old_building", + ), + ], + default_target_id="new_building", + ), + AssignmentNode( + id="old_building", + description="Old building defaults", + assignments={"InfiltrationACH": 1.5}, + ), + ComponentRefNode( + id="new_building", + description="New building uses default envelope", + component_id="default_envelope", + ), + ], + entry_node_ids=["check_age"], + ) + + def test_dag_structure(self, simple_dag: DecisionDAG): + assert len(simple_dag.nodes) == 3 + assert len(simple_dag.components) == 1 + assert simple_dag.entry_node_ids == ["check_age"] + + def test_dag_serialization_roundtrip(self, simple_dag: DecisionDAG): + data = simple_dag.model_dump() + dag2 = DecisionDAG.model_validate(data) + assert dag2.description == simple_dag.description + assert len(dag2.nodes) == len(simple_dag.nodes) + assert len(dag2.components) == len(simple_dag.components) + + def test_dag_json_roundtrip(self, simple_dag: DecisionDAG): + json_str = simple_dag.model_dump_json() + dag2 = DecisionDAG.model_validate_json(json_str) + assert dag2.entry_node_ids == simple_dag.entry_node_ids + + def test_discriminated_union_deserialization(self): + """Ensure node_type discriminator works correctly from raw dicts.""" + dag_data = { + "description": "test", + "components": [], + "nodes": [ + { + "node_type": "condition", + "id": "c1", + "description": "cond", + "branches": [], + }, + { + "node_type": "assignment", + "id": "a1", + "description": "assign", + "assignments": {"HeatingFuel": "Electricity"}, + }, + { + "node_type": "component_ref", + "id": "r1", + "description": "ref", + "component_id": "comp1", + }, + ], + "entry_node_ids": ["c1"], + } + dag = DecisionDAG.model_validate(dag_data) + assert isinstance(dag.nodes[0], ConditionNode) + assert isinstance(dag.nodes[1], AssignmentNode) + assert isinstance(dag.nodes[2], ComponentRefNode) diff --git a/tests/test_decision_dag/test_executor.py b/tests/test_decision_dag/test_executor.py new file mode 100644 index 0000000..b92a333 --- /dev/null +++ b/tests/test_decision_dag/test_executor.py @@ -0,0 +1,303 @@ +"""Tests for decision_dag.executor module.""" + +import pytest + +from epinterface.sbem.decision_dag.dag import ( + AssignmentNode, + ComparisonOperator, + ComponentRefNode, + ConditionalBranch, + ConditionNode, + DecisionDAG, + FieldCondition, + IntermediateComponent, +) +from epinterface.sbem.decision_dag.executor import DAGExecutor, _evaluate_condition + + +class TestEvaluateCondition: + """Tests for individual condition evaluation.""" + + def test_eq_match(self): + cond = FieldCondition( + field="type", operator=ComparisonOperator.EQ, value="residential" + ) + assert _evaluate_condition(cond, {"type": "residential"}) is True + + def test_eq_no_match(self): + cond = FieldCondition( + field="type", operator=ComparisonOperator.EQ, value="residential" + ) + assert _evaluate_condition(cond, {"type": "commercial"}) is False + + def test_neq(self): + cond = FieldCondition( + field="type", operator=ComparisonOperator.NEQ, value="residential" + ) + assert _evaluate_condition(cond, {"type": "commercial"}) is True + + def test_lt(self): + cond = FieldCondition(field="year", operator=ComparisonOperator.LT, value=1960) + assert _evaluate_condition(cond, {"year": 1950}) is True + assert _evaluate_condition(cond, {"year": 1960}) is False + + def test_lte(self): + cond = FieldCondition(field="year", operator=ComparisonOperator.LTE, value=1960) + assert _evaluate_condition(cond, {"year": 1960}) is True + + def test_gt(self): + cond = FieldCondition(field="year", operator=ComparisonOperator.GT, value=2000) + assert _evaluate_condition(cond, {"year": 2010}) is True + + def test_gte(self): + cond = FieldCondition(field="year", operator=ComparisonOperator.GTE, value=2000) + assert _evaluate_condition(cond, {"year": 2000}) is True + + def test_in_operator(self): + cond = FieldCondition( + field="type", operator=ComparisonOperator.IN, value=["a", "b"] + ) + assert _evaluate_condition(cond, {"type": "a"}) is True + assert _evaluate_condition(cond, {"type": "c"}) is False + + def test_not_in_operator(self): + cond = FieldCondition( + field="type", operator=ComparisonOperator.NOT_IN, value=["a", "b"] + ) + assert _evaluate_condition(cond, {"type": "c"}) is True + + def test_contains(self): + cond = FieldCondition( + field="notes", operator=ComparisonOperator.CONTAINS, value="renovated" + ) + assert _evaluate_condition(cond, {"notes": "recently renovated home"}) is True + assert _evaluate_condition(cond, {"notes": "original condition"}) is False + + def test_is_missing_true(self): + cond = FieldCondition(field="income", operator=ComparisonOperator.IS_MISSING) + assert _evaluate_condition(cond, {}) is True + assert _evaluate_condition(cond, {"income": None}) is True + + def test_is_missing_false(self): + cond = FieldCondition(field="income", operator=ComparisonOperator.IS_MISSING) + assert _evaluate_condition(cond, {"income": 50000}) is False + + def test_is_not_missing(self): + cond = FieldCondition( + field="income", operator=ComparisonOperator.IS_NOT_MISSING + ) + assert _evaluate_condition(cond, {"income": 50000}) is True + assert _evaluate_condition(cond, {}) is False + + def test_missing_field_returns_false_for_comparison(self): + cond = FieldCondition(field="year", operator=ComparisonOperator.LT, value=2000) + assert _evaluate_condition(cond, {}) is False + + +@pytest.fixture() +def branching_dag() -> DecisionDAG: + """A DAG with branching conditions, components, and assignments.""" + return DecisionDAG( + description="Test DAG with branching", + components=[ + IntermediateComponent( + id="high_perf_wall", + name="High Performance Wall", + description="Well-insulated wall assembly", + assignments={ + "FacadeStructuralSystem": "woodframe", + "FacadeCavityInsulationRValue": 3.5, + "FacadeExteriorInsulationRValue": 2.0, + "InfiltrationACH": 0.3, + }, + ), + IntermediateComponent( + id="old_wall", + name="Old Uninsulated Wall", + description="Pre-1960 uninsulated wall", + assignments={ + "FacadeStructuralSystem": "masonry", + "FacadeCavityInsulationRValue": 0.0, + "FacadeExteriorInsulationRValue": 0.0, + "InfiltrationACH": 1.2, + }, + ), + ], + nodes=[ + ConditionNode( + id="check_age", + description="Check building age", + branches=[ + ConditionalBranch( + condition=FieldCondition( + field="year_built", + operator=ComparisonOperator.LTE, + value=1960, + ), + target_node_id="apply_old_wall", + ), + ConditionalBranch( + condition=FieldCondition( + field="year_built", + operator=ComparisonOperator.GT, + value=1960, + ), + target_node_id="apply_high_perf_wall", + ), + ], + default_target_id="apply_old_wall", + ), + ComponentRefNode( + id="apply_old_wall", + description="Apply old wall component", + component_id="old_wall", + next_node_ids=["set_hvac"], + ), + ComponentRefNode( + id="apply_high_perf_wall", + description="Apply high performance wall component", + component_id="high_perf_wall", + next_node_ids=["set_hvac"], + ), + AssignmentNode( + id="set_hvac", + description="Set default HVAC", + assignments={ + "HeatingFuel": "NaturalGas", + "HeatingSystemCOP": 0.85, + "CoolingFuel": "Electricity", + "CoolingSystemCOP": 3.0, + }, + ), + ], + entry_node_ids=["check_age"], + ) + + +class TestDAGExecutor: + """Tests for DAGExecutor.""" + + def test_old_building_path(self, branching_dag: DecisionDAG): + executor = DAGExecutor(branching_dag) + result = executor.execute({"year_built": 1940}) + + assert result.assignments["FacadeStructuralSystem"] == "masonry" + assert result.assignments["InfiltrationACH"] == 1.2 + assert result.assignments["HeatingFuel"] == "NaturalGas" + assert "apply_old_wall" in result.trace.visited_node_ids + assert "old_wall" in result.trace.applied_component_ids + + def test_new_building_path(self, branching_dag: DecisionDAG): + executor = DAGExecutor(branching_dag) + result = executor.execute({"year_built": 2005}) + + assert result.assignments["FacadeStructuralSystem"] == "woodframe" + assert result.assignments["FacadeCavityInsulationRValue"] == 3.5 + assert result.assignments["InfiltrationACH"] == 0.3 + assert "apply_high_perf_wall" in result.trace.visited_node_ids + assert "high_perf_wall" in result.trace.applied_component_ids + + def test_missing_field_uses_default(self, branching_dag: DecisionDAG): + executor = DAGExecutor(branching_dag) + result = executor.execute({}) + + assert result.assignments["FacadeStructuralSystem"] == "masonry" + assert "apply_old_wall" in result.trace.visited_node_ids + + def test_hvac_always_set(self, branching_dag: DecisionDAG): + executor = DAGExecutor(branching_dag) + for row in [{"year_built": 1940}, {"year_built": 2005}, {}]: + result = executor.execute(row) + assert "HeatingFuel" in result.assignments + assert "CoolingSystemCOP" in result.assignments + + def test_trace_records_all_visited(self, branching_dag: DecisionDAG): + executor = DAGExecutor(branching_dag) + result = executor.execute({"year_built": 1940}) + assert "check_age" in result.trace.visited_node_ids + assert "apply_old_wall" in result.trace.visited_node_ids + assert "set_hvac" in result.trace.visited_node_ids + + def test_cycle_protection(self): + """Nodes referencing each other should not cause infinite loops.""" + dag = DecisionDAG( + description="Cyclic DAG for testing", + components=[], + nodes=[ + AssignmentNode( + id="a", + description="Node A", + assignments={"HeatingFuel": "Electricity"}, + next_node_ids=["b"], + ), + AssignmentNode( + id="b", + description="Node B", + assignments={"CoolingFuel": "Electricity"}, + next_node_ids=["a"], + ), + ], + entry_node_ids=["a"], + ) + executor = DAGExecutor(dag) + result = executor.execute({}) + assert result.assignments["HeatingFuel"] == "Electricity" + assert result.assignments["CoolingFuel"] == "Electricity" + + def test_multiple_entry_nodes(self): + """Independent sub-DAGs for different parameter groups.""" + dag = DecisionDAG( + description="Multi-entry DAG", + components=[], + nodes=[ + AssignmentNode( + id="envelope", + description="Set envelope params", + assignments={"InfiltrationACH": 0.5, "WindowUValue": 2.0}, + ), + AssignmentNode( + id="hvac", + description="Set HVAC params", + assignments={ + "HeatingFuel": "NaturalGas", + "CoolingFuel": "Electricity", + }, + ), + ], + entry_node_ids=["envelope", "hvac"], + ) + executor = DAGExecutor(dag) + result = executor.execute({}) + assert result.assignments["InfiltrationACH"] == 0.5 + assert result.assignments["HeatingFuel"] == "NaturalGas" + + def test_later_assignments_override_earlier(self): + """Refinement chain: later nodes override earlier values.""" + dag = DecisionDAG( + description="Override test", + components=[], + nodes=[ + AssignmentNode( + id="defaults", + description="Broad defaults", + assignments={"InfiltrationACH": 0.6, "HeatingFuel": "NaturalGas"}, + next_node_ids=["override"], + ), + AssignmentNode( + id="override", + description="Override infiltration", + assignments={"InfiltrationACH": 0.2}, + ), + ], + entry_node_ids=["defaults"], + ) + executor = DAGExecutor(dag) + result = executor.execute({}) + assert result.assignments["InfiltrationACH"] == 0.2 + assert result.assignments["HeatingFuel"] == "NaturalGas" + + def test_unresolved_fields_tracked(self, branching_dag: DecisionDAG): + executor = DAGExecutor(branching_dag) + result = executor.execute({"year_built": 2005}) + assert len(result.trace.unresolved_fields) > 0 + assert "WindowUValue" in result.trace.unresolved_fields diff --git a/tests/test_decision_dag/test_fields.py b/tests/test_decision_dag/test_fields.py new file mode 100644 index 0000000..4d759ea --- /dev/null +++ b/tests/test_decision_dag/test_fields.py @@ -0,0 +1,198 @@ +"""Tests for decision_dag.fields module.""" + +import pytest +from pydantic import ValidationError + +from epinterface.sbem.decision_dag.fields import ( + FieldType, + SupplementaryContext, + UserFieldDefinition, + UserFieldSet, +) + + +class TestUserFieldDefinition: + """Tests for UserFieldDefinition validation.""" + + def test_categorical_field_valid(self): + field = UserFieldDefinition( + name="building_type", + field_type=FieldType.CATEGORICAL, + description="Type of building", + categories=["residential", "commercial", "industrial"], + ) + assert field.categories == ["residential", "commercial", "industrial"] + + def test_categorical_field_missing_categories(self): + with pytest.raises(ValidationError, match="categorical fields must specify"): + UserFieldDefinition( + name="building_type", + field_type=FieldType.CATEGORICAL, + description="Type of building", + ) + + def test_numeric_field_valid(self): + field = UserFieldDefinition( + name="year_built", + field_type=FieldType.NUMERIC, + description="Year the building was constructed", + min_value=1800, + max_value=2025, + unit="year", + ) + assert field.min_value == 1800 + assert field.max_value == 2025 + + def test_numeric_field_missing_bounds(self): + with pytest.raises(ValidationError, match="numeric fields must specify"): + UserFieldDefinition( + name="year_built", + field_type=FieldType.NUMERIC, + description="Year the building was constructed", + ) + + def test_numeric_field_missing_max(self): + with pytest.raises(ValidationError, match="numeric fields must specify"): + UserFieldDefinition( + name="year_built", + field_type=FieldType.NUMERIC, + description="Year the building was constructed", + min_value=1800, + ) + + def test_plaintext_field_valid(self): + field = UserFieldDefinition( + name="notes", + field_type=FieldType.PLAINTEXT, + description="Free-text notes about the building", + ) + assert field.field_type == FieldType.PLAINTEXT + assert field.categories is None + assert field.min_value is None + + def test_data_quality_description(self): + field = UserFieldDefinition( + name="wall_r_value", + field_type=FieldType.NUMERIC, + description="Wall R-value", + data_quality_description="Self-reported, unreliable for pre-1980 buildings", + min_value=0, + max_value=40, + unit="m2K/W", + ) + assert ( + field.data_quality_description + == "Self-reported, unreliable for pre-1980 buildings" + ) + + +class TestSupplementaryContext: + """Tests for SupplementaryContext.""" + + def test_plaintext_context(self): + ctx = SupplementaryContext( + title="Regional construction practices", + content="Pre-1940 buildings have double-wythe brick walls.", + ) + assert ctx.format_hint == "plaintext" + + def test_json_context(self): + ctx = SupplementaryContext( + title="HVAC distribution", + content='{"gas_furnace": 0.6, "heat_pump": 0.3, "electric_resistance": 0.1}', + format_hint="json", + ) + assert ctx.format_hint == "json" + + +class TestUserFieldSet: + """Tests for UserFieldSet validation.""" + + def test_valid_field_set(self): + fs = UserFieldSet( + fields=[ + UserFieldDefinition( + name="building_type", + field_type=FieldType.CATEGORICAL, + description="Type of building", + categories=["residential", "commercial"], + ), + UserFieldDefinition( + name="year_built", + field_type=FieldType.NUMERIC, + description="Construction year", + min_value=1800, + max_value=2025, + ), + ], + context_description="Energy audit project", + region_description="Boston, MA, Climate Zone 5A", + ) + assert len(fs.fields) == 2 + + def test_duplicate_field_names_rejected(self): + with pytest.raises(ValidationError, match="Duplicate field names"): + UserFieldSet( + fields=[ + UserFieldDefinition( + name="building_type", + field_type=FieldType.CATEGORICAL, + description="Type A", + categories=["a"], + ), + UserFieldDefinition( + name="building_type", + field_type=FieldType.CATEGORICAL, + description="Type B", + categories=["b"], + ), + ], + ) + + def test_supplementary_context(self): + fs = UserFieldSet( + fields=[ + UserFieldDefinition( + name="typology", + field_type=FieldType.CATEGORICAL, + description="Building typology", + categories=["SF", "MF"], + ), + ], + supplementary_context=[ + SupplementaryContext( + title="Wall types", + content="Most SF homes are wood-frame, MF are masonry.", + ), + ], + ) + assert len(fs.supplementary_context) == 1 + + def test_empty_fields_allowed(self): + fs = UserFieldSet(fields=[]) + assert len(fs.fields) == 0 + + def test_serialization_roundtrip(self): + fs = UserFieldSet( + fields=[ + UserFieldDefinition( + name="income", + field_type=FieldType.NUMERIC, + description="Household income", + min_value=0, + max_value=500000, + unit="USD", + ), + ], + region_description="Northeast US", + supplementary_context=[ + SupplementaryContext( + title="Income data", + content="Median income is $65,000", + ), + ], + ) + data = fs.model_dump() + fs2 = UserFieldSet.model_validate(data) + assert fs2.fields[0].name == "income" + assert len(fs2.supplementary_context) == 1 diff --git a/tests/test_decision_dag/test_llm_integration.py b/tests/test_decision_dag/test_llm_integration.py new file mode 100644 index 0000000..b6371bf --- /dev/null +++ b/tests/test_decision_dag/test_llm_integration.py @@ -0,0 +1,291 @@ +"""Integration test: generate a DecisionDAG via an LLM for a Massachusetts building stock. + +Run with: + uv run --env-file .env python tests/test_decision_dag/test_llm_integration.py +""" + +from __future__ import annotations + +import asyncio +import json + +from epinterface.sbem.decision_dag.agent import build_user_message, generate_dag +from epinterface.sbem.decision_dag.executor import DAGExecutor +from epinterface.sbem.decision_dag.fields import ( + FieldType, + SupplementaryContext, + UserFieldDefinition, + UserFieldSet, +) +from epinterface.sbem.decision_dag.validation import validate_dag_structure + +FIELD_SET = UserFieldSet( + fields=[ + UserFieldDefinition( + name="income", + field_type=FieldType.NUMERIC, + description="Annual household income in USD. Correlates loosely with ability to invest in energy upgrades.", + data_quality_description="Self-reported on utility assistance applications. About 30% of rows are missing.", + min_value=0, + max_value=500_000, + unit="USD/year", + ), + UserFieldDefinition( + name="year_built", + field_type=FieldType.NUMERIC, + description="Year the building was originally constructed.", + data_quality_description="From assessor records; generally reliable, though some entries are approximate decades (e.g. 1900 for anything pre-1910).", + min_value=1700, + max_value=2025, + unit="year", + ), + UserFieldDefinition( + name="building_typology", + field_type=FieldType.CATEGORICAL, + description="Building typology classification from assessor data.", + data_quality_description="Assessor-derived, reliable.", + categories=[ + "single_family_detached", + "single_family_attached", + "small_multifamily_2_4", + "medium_multifamily_5_20", + "large_multifamily_20_plus", + ], + ), + UserFieldDefinition( + name="weatherization_status", + field_type=FieldType.CATEGORICAL, + description="Whether the building has been through a weatherization assistance program.", + data_quality_description="From state WAP records. Only captures state-funded programs; private weatherization is not tracked. About 60% of rows are missing (unknown status).", + categories=["weatherized", "not_weatherized", "unknown"], + ), + UserFieldDefinition( + name="last_renovation", + field_type=FieldType.CATEGORICAL, + description="Approximate timeframe of last known major renovation or retrofit.", + data_quality_description="From permit records where available. Very sparse -- roughly 70% missing.", + categories=[ + "never", + "before_1980", + "1980_2000", + "2000_2010", + "2010_present", + ], + ), + ], + context_description=( + "We are building energy models for a portfolio of ~5,000 residential buildings " + "in Massachusetts for a utility-funded energy efficiency program. The goal is to " + "estimate building energy use and identify retrofit opportunities. Data is sparse " + "and of mixed quality." + ), + region_description=( + "Massachusetts, USA. IECC Climate Zone 5A. Cold winters, warm humid summers. " + "Heating-dominated climate with ~5,500 HDD65 and ~700 CDD65. " + "State energy code is based on IECC 2021 for new construction." + ), + building_stock_description=( + "Predominantly older housing stock. Roughly 60% of buildings were built before 1960. " + "Mix of wood-frame (most common for single-family), triple-decker multi-family " + "(very common in urban MA), and some masonry construction in older urban cores. " + "Natural gas heating dominates (~65%), followed by oil (~20%), and electric/heat pump (~15%). " + "Many older buildings have minimal insulation, especially in walls." + ), + supplementary_context=[ + SupplementaryContext( + title="Heating System Distribution by Building Age", + content=json.dumps( + { + "pre_1940": { + "gas_furnace": 0.45, + "oil_boiler": 0.35, + "steam": 0.10, + "electric_resistance": 0.05, + "heat_pump": 0.05, + }, + "1940_1970": { + "gas_furnace": 0.55, + "oil_boiler": 0.25, + "electric_resistance": 0.10, + "heat_pump": 0.10, + }, + "1970_2000": { + "gas_furnace": 0.60, + "oil_boiler": 0.15, + "electric_resistance": 0.10, + "heat_pump": 0.15, + }, + "post_2000": { + "gas_furnace": 0.40, + "oil_boiler": 0.05, + "electric_resistance": 0.05, + "heat_pump": 0.50, + }, + }, + indent=2, + ), + format_hint="json", + ), + SupplementaryContext( + title="Typical Wall Construction by Era", + content=( + "Pre-1940: Double-wythe brick or balloon-frame wood with no insulation, plaster interior. " + "Infiltration is very high (often 1.0+ ACH).\n" + "1940-1970: Platform-frame wood, often with minimal batt insulation (R-7 to R-11 cavities), " + "some with aluminum siding over original clapboard. Infiltration moderate (0.5-0.8 ACH).\n" + "1970-2000: Wood frame with R-11 to R-19 cavity insulation, vinyl or wood siding, " + "some continuous insulation in later builds. Infiltration moderate (0.3-0.6 ACH).\n" + "Post-2000: Wood frame with R-19+ cavity, often R-5 to R-10 continuous exterior insulation, " + "air sealing. Infiltration low (0.15-0.35 ACH)." + ), + format_hint="plaintext", + ), + SupplementaryContext( + title="Massachusetts Weatherization Program Notes", + content=( + "The MA WAP program typically performs: air sealing (blower-door guided), " + "attic insulation to R-38 minimum, wall insulation (dense-pack cellulose) " + "where feasible, and sometimes basement/crawlspace insulation. " + "Weatherized homes see roughly a 20-30% reduction in infiltration and " + "improved wall/attic R-values compared to un-weatherized homes of the same era." + ), + format_hint="plaintext", + ), + ], +) + +SAMPLE_ROWS = [ + { + "income": 45000, + "year_built": 1925, + "building_typology": "single_family_detached", + "weatherization_status": "not_weatherized", + "last_renovation": "never", + }, + { + "income": 120000, + "year_built": 2018, + "building_typology": "single_family_detached", + "weatherization_status": "unknown", + "last_renovation": "2010_present", + }, + { + "year_built": 1955, + "building_typology": "small_multifamily_2_4", + "weatherization_status": "weatherized", + }, + { + "building_typology": "large_multifamily_20_plus", + }, + {}, +] + +DIRECT_VALUES = { + "WWR": 0.15, + "F2FHeight": 3.0, + "NFloors": 2, + "Width": 10.0, + "Depth": 12.0, + "Rotation": 0.0, + "EPWURI": "https://energyplus-weather.s3.amazonaws.com/north_and_central_america_wmo_region_4/USA/MA/USA_MA_Boston-Logan.Intl.AP.725090_TMYx.2007-2021.epw", +} + + +async def main(): + """Run the full integration test.""" + print("=" * 70) + print("Decision DAG LLM Integration Test -- Massachusetts Residential Stock") + print("=" * 70) + + print("\n--- User Message Preview (first 500 chars) ---") + msg = build_user_message(FIELD_SET) + import yaml + + with open("tests/test_decision_dag/_last_user_field_set.yaml", "w") as f: + yaml.dump(FIELD_SET.model_dump(mode="json"), f, indent=2, sort_keys=False) + with open("tests/test_decision_dag/_last_user_message.txt", "w") as f: + f.write(msg) + print(msg[:500] + "...\n") + + print("--- Calling LLM to generate DAG ---") + dag = await generate_dag(FIELD_SET, model="openai:gpt-5.2-chat-latest") + + print(f"\nDAG description: {dag.description}") + print(f"Components: {len(dag.components)}") + print(f"Nodes: {len(dag.nodes)}") + print(f"Entry nodes: {dag.entry_node_ids}") + + print("\n--- Intermediate Components ---") + for comp in dag.components: + print(f" [{comp.id}] {comp.name}") + print(f" {comp.description}") + print( + f" Assigns {len(comp.assignments)} fields: {list(comp.assignments.keys())}" + ) + + print("\n--- Validating DAG ---") + errors = validate_dag_structure( + dag, field_set=FIELD_SET, require_full_coverage=True + ) + if errors: + print(f" Validation found {len(errors)} issue(s):") + for e in errors: + print(f" - {e}") + else: + print(" DAG passed all structural validation checks.") + + print("\n--- Executing DAG Against Sample Rows ---") + executor = DAGExecutor(dag) + for i, row in enumerate(SAMPLE_ROWS): + print(f"\n Row {i + 1}: {row or '(empty)'}") + result = executor.execute(row) + n_assigned = len(result.assignments) + n_unresolved = len(result.trace.unresolved_fields) + print(f" Visited: {result.trace.visited_node_ids}") + print(f" Components applied: {result.trace.applied_component_ids}") + print(f" Assigned {n_assigned} fields, {n_unresolved} unresolved") + + highlights = { + k: result.assignments[k] + for k in [ + "HeatingFuel", + "HeatingSystemCOP", + "InfiltrationACH", + "FacadeStructuralSystem", + "FacadeCavityInsulationRValue", + "WindowUValue", + ] + if k in result.assignments + } + print(f" Key values: {highlights}") + + print("\n--- Attempting FlatModel Construction (Row 1) ---") + try: + flat_model = executor.execute_to_flat_model( + SAMPLE_ROWS[0], direct_values=DIRECT_VALUES + ) + print(" FlatModel created successfully!") + print(f" HeatingFuel={flat_model.HeatingFuel}") + print(f" InfiltrationACH={flat_model.InfiltrationACH}") + print(f" FacadeStructuralSystem={flat_model.FacadeStructuralSystem}") + print( + f" FacadeCavityInsulationRValue={flat_model.FacadeCavityInsulationRValue}" + ) + print(f" WindowUValue={flat_model.WindowUValue}") + except Exception as exc: + print(f" FlatModel construction failed: {exc}") + + print("\n--- Serialized DAG (JSON) ---") + dag_json = dag.model_dump_json(indent=2) + print(f" {len(dag_json)} characters") + print(" (saved to tests/test_decision_dag/_last_dag.json)") + from pathlib import Path + + Path("tests/test_decision_dag/_last_dag.json").write_text(dag_json) + + print("\n" + "=" * 70) + print("Done.") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/tests/test_decision_dag/test_validation.py b/tests/test_decision_dag/test_validation.py new file mode 100644 index 0000000..2c610ad --- /dev/null +++ b/tests/test_decision_dag/test_validation.py @@ -0,0 +1,372 @@ +"""Tests for decision_dag.validation module.""" + +import pytest + +from epinterface.sbem.decision_dag.dag import ( + AssignmentNode, + ComparisonOperator, + ComponentRefNode, + ConditionalBranch, + ConditionNode, + DecisionDAG, + FieldCondition, + IntermediateComponent, +) +from epinterface.sbem.decision_dag.fields import ( + FieldType, + UserFieldDefinition, + UserFieldSet, +) +from epinterface.sbem.decision_dag.schema_utils import ( + get_flat_model_field_names, + get_flat_model_schema_description, + validate_dag_assignments, +) +from epinterface.sbem.decision_dag.validation import ( + _validate_acyclic, + _validate_component_refs, + _validate_coverage, + _validate_entry_nodes, + _validate_field_refs, + _validate_node_refs, + validate_dag_structure, +) + + +@pytest.fixture() +def valid_dag() -> DecisionDAG: + """A structurally valid DAG.""" + return DecisionDAG( + description="Valid test DAG", + components=[ + IntermediateComponent( + id="comp1", + name="Test Component", + description="A test component", + assignments={"HeatingFuel": "NaturalGas"}, + ), + ], + nodes=[ + ConditionNode( + id="root", + description="Root condition", + branches=[ + ConditionalBranch( + condition=FieldCondition( + field="building_type", + operator=ComparisonOperator.EQ, + value="residential", + ), + target_node_id="assign1", + ), + ], + default_target_id="ref1", + ), + AssignmentNode( + id="assign1", + description="Residential assignments", + assignments={"HeatingFuel": "NaturalGas"}, + ), + ComponentRefNode( + id="ref1", + description="Default component", + component_id="comp1", + ), + ], + entry_node_ids=["root"], + ) + + +@pytest.fixture() +def field_set() -> UserFieldSet: + """A simple field set for validation tests.""" + return UserFieldSet( + fields=[ + UserFieldDefinition( + name="building_type", + field_type=FieldType.CATEGORICAL, + description="Building type", + categories=["residential", "commercial"], + ), + UserFieldDefinition( + name="year_built", + field_type=FieldType.NUMERIC, + description="Year built", + min_value=1800, + max_value=2025, + ), + ], + ) + + +class TestNodeRefValidation: + """Tests for _validate_node_refs.""" + + def test_valid_refs(self, valid_dag: DecisionDAG): + assert _validate_node_refs(valid_dag) == [] + + def test_invalid_branch_target(self): + dag = DecisionDAG( + description="test", + components=[], + nodes=[ + ConditionNode( + id="root", + description="Root", + branches=[ + ConditionalBranch( + condition=FieldCondition( + field="x", + operator=ComparisonOperator.EQ, + value="y", + ), + target_node_id="nonexistent", + ), + ], + ), + ], + entry_node_ids=["root"], + ) + errors = _validate_node_refs(dag) + assert any("nonexistent" in e for e in errors) + + def test_invalid_default_target(self): + dag = DecisionDAG( + description="test", + components=[], + nodes=[ + ConditionNode( + id="root", + description="Root", + branches=[], + default_target_id="missing", + ), + ], + entry_node_ids=["root"], + ) + errors = _validate_node_refs(dag) + assert any("missing" in e for e in errors) + + def test_invalid_next_node_id(self): + dag = DecisionDAG( + description="test", + components=[], + nodes=[ + AssignmentNode( + id="a", + description="A", + assignments={}, + next_node_ids=["ghost"], + ), + ], + entry_node_ids=["a"], + ) + errors = _validate_node_refs(dag) + assert any("ghost" in e for e in errors) + + +class TestEntryNodeValidation: + """Tests for _validate_entry_nodes.""" + + def test_valid_entries(self, valid_dag: DecisionDAG): + assert _validate_entry_nodes(valid_dag) == [] + + def test_invalid_entry(self): + dag = DecisionDAG( + description="test", + components=[], + nodes=[], + entry_node_ids=["missing"], + ) + errors = _validate_entry_nodes(dag) + assert len(errors) == 1 + + +class TestComponentRefValidation: + """Tests for _validate_component_refs.""" + + def test_valid_refs(self, valid_dag: DecisionDAG): + assert _validate_component_refs(valid_dag) == [] + + def test_invalid_component_ref(self): + dag = DecisionDAG( + description="test", + components=[], + nodes=[ + ComponentRefNode( + id="ref", + description="Bad ref", + component_id="nonexistent_comp", + ), + ], + entry_node_ids=["ref"], + ) + errors = _validate_component_refs(dag) + assert any("nonexistent_comp" in e for e in errors) + + +class TestAcyclicValidation: + """Tests for _validate_acyclic.""" + + def test_acyclic_dag(self, valid_dag: DecisionDAG): + assert _validate_acyclic(valid_dag) == [] + + def test_cycle_detected(self): + dag = DecisionDAG( + description="cyclic", + components=[], + nodes=[ + AssignmentNode( + id="a", + description="A", + assignments={}, + next_node_ids=["b"], + ), + AssignmentNode( + id="b", + description="B", + assignments={}, + next_node_ids=["a"], + ), + ], + entry_node_ids=["a"], + ) + errors = _validate_acyclic(dag) + assert len(errors) > 0 + assert any("Cycle" in e for e in errors) + + +class TestFieldRefValidation: + """Tests for _validate_field_refs.""" + + def test_valid_field_refs(self, valid_dag: DecisionDAG, field_set: UserFieldSet): + assert _validate_field_refs(valid_dag, field_set) == [] + + def test_unknown_field_ref(self, field_set: UserFieldSet): + dag = DecisionDAG( + description="test", + components=[], + nodes=[ + ConditionNode( + id="root", + description="Root", + branches=[ + ConditionalBranch( + condition=FieldCondition( + field="unknown_field", + operator=ComparisonOperator.EQ, + value="x", + ), + target_node_id="root", + ), + ], + ), + ], + entry_node_ids=["root"], + ) + errors = _validate_field_refs(dag, field_set) + assert any("unknown_field" in e for e in errors) + + +class TestAssignmentValidation: + """Tests for validate_dag_assignments.""" + + def test_valid_assignments(self, valid_dag: DecisionDAG): + assert validate_dag_assignments(valid_dag) == [] + + def test_invalid_field_name_in_assignment(self): + dag = DecisionDAG( + description="test", + components=[], + nodes=[ + AssignmentNode( + id="bad", + description="Bad assignment", + assignments={"NotARealField": 42}, + ), + ], + entry_node_ids=["bad"], + ) + errors = validate_dag_assignments(dag) + assert any("NotARealField" in e for e in errors) + + def test_invalid_field_in_component(self): + dag = DecisionDAG( + description="test", + components=[ + IntermediateComponent( + id="bad_comp", + name="Bad", + description="Bad component", + assignments={"FakeParameter": 99}, + ), + ], + nodes=[], + entry_node_ids=[], + ) + errors = validate_dag_assignments(dag) + assert any("FakeParameter" in e for e in errors) + + +class TestCoverageValidation: + """Tests for _validate_coverage.""" + + def test_incomplete_coverage(self, valid_dag: DecisionDAG): + errors = _validate_coverage(valid_dag) + assert len(errors) > 0 + assert any("never assigned" in e for e in errors) + + +class TestFullValidation: + """Tests for validate_dag_structure (all checks combined).""" + + def test_valid_dag_passes(self, valid_dag: DecisionDAG, field_set: UserFieldSet): + errors = validate_dag_structure(valid_dag, field_set=field_set) + assert errors == [] + + def test_full_validation_catches_multiple_issues(self): + dag = DecisionDAG( + description="broken", + components=[], + nodes=[ + ConditionNode( + id="root", + description="Root", + branches=[ + ConditionalBranch( + condition=FieldCondition( + field="x", + operator=ComparisonOperator.EQ, + value="y", + ), + target_node_id="ghost", + ), + ], + ), + ], + entry_node_ids=["root", "also_missing"], + ) + errors = validate_dag_structure(dag) + assert len(errors) >= 2 + + +class TestSchemaUtils: + """Tests for schema introspection utilities.""" + + def test_get_field_names(self): + names = get_flat_model_field_names() + assert "HeatingFuel" in names + assert "InfiltrationACH" in names + assert "WWR" in names + assert "FacadeStructuralSystem" in names + + def test_schema_description_includes_groups(self): + desc = get_flat_model_schema_description() + assert "HVAC Systems" in desc + assert "Facade Construction" in desc + assert "HeatingFuel" in desc + assert "InfiltrationACH" in desc + + def test_schema_description_includes_constraints(self): + desc = get_flat_model_schema_description() + assert "ge=" in desc or "le=" in desc diff --git a/tests/test_decision_dag/tester.ipynb b/tests/test_decision_dag/tester.ipynb new file mode 100644 index 0000000..f9597a5 --- /dev/null +++ b/tests/test_decision_dag/tester.ipynb @@ -0,0 +1,334 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 8, + "id": "d0e9ef9a", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Integration test: generate a DecisionDAG via an LLM for a Massachusetts building stock.\n", + "\n", + "Run with:\n", + " uv run --env-file .env python tests/test_decision_dag/test_llm_integration.py\n", + "\"\"\"\n", + "\n", + "from __future__ import annotations\n", + "\n", + "from epinterface.sbem.decision_dag.agent import generate_dag\n", + "from epinterface.sbem.decision_dag.executor import DAGExecutor\n", + "from epinterface.sbem.decision_dag.fields import (\n", + " UserFieldSet,\n", + ")\n", + "from epinterface.sbem.decision_dag.validation import validate_dag_structure\n", + "\n", + "SAMPLE_ROWS = [\n", + " {\n", + " \"income\": 45000,\n", + " \"year_built\": 1925,\n", + " \"building_typology\": \"single_family_detached\",\n", + " \"weatherization_status\": \"not_weatherized\",\n", + " \"last_renovation\": \"never\",\n", + " },\n", + " {\n", + " \"income\": 120000,\n", + " \"year_built\": 2018,\n", + " \"building_typology\": \"single_family_detached\",\n", + " \"weatherization_status\": \"unknown\",\n", + " \"last_renovation\": \"2010_present\",\n", + " },\n", + " {\n", + " \"year_built\": 1955,\n", + " \"building_typology\": \"small_multifamily_2_4\",\n", + " \"weatherization_status\": \"weatherized\",\n", + " },\n", + " {\n", + " \"building_typology\": \"large_multifamily_20_plus\",\n", + " },\n", + " {},\n", + "]\n", + "\n", + "DIRECT_VALUES = {\n", + " \"WWR\": 0.15,\n", + " \"F2FHeight\": 3.0,\n", + " \"NFloors\": 2,\n", + " \"Width\": 10.0,\n", + " \"Depth\": 12.0,\n", + " \"Rotation\": 0.0,\n", + " \"EPWURI\": \"https://energyplus-weather.s3.amazonaws.com/north_and_central_america_wmo_region_4/USA/MA/USA_MA_Boston-Logan.Intl.AP.725090_TMYx.2007-2021.epw\",\n", + "}\n", + "\n", + "\n", + "async def main(FIELD_SET: UserFieldSet, dag_output_path: str):\n", + " \"\"\"Run the full integration test.\"\"\"\n", + " dag = await generate_dag(FIELD_SET, model=\"openai:gpt-5.2-chat-latest\")\n", + "\n", + " errors = validate_dag_structure(\n", + " dag, field_set=FIELD_SET, require_full_coverage=True\n", + " )\n", + " if errors:\n", + " print(f\" Validation found {len(errors)} issue(s):\")\n", + " for e in errors:\n", + " print(f\" - {e}\")\n", + " else:\n", + " print(\" DAG passed all structural validation checks.\")\n", + "\n", + " executor = DAGExecutor(dag)\n", + " for i, row in enumerate(SAMPLE_ROWS):\n", + " print(f\"\\n Row {i + 1}: {row or '(empty)'}\")\n", + " result = executor.execute(row)\n", + " with open(f\"result_{i}.json\", \"w\") as f:\n", + " f.write(result.model_dump_json(indent=2))\n", + "\n", + " highlights = {\n", + " k: result.assignments[k]\n", + " for k in [\n", + " \"HeatingFuel\",\n", + " \"HeatingSystemCOP\",\n", + " \"InfiltrationACH\",\n", + " \"FacadeStructuralSystem\",\n", + " \"FacadeCavityInsulationRValue\",\n", + " \"WindowUValue\",\n", + " ]\n", + " if k in result.assignments\n", + " }\n", + " print(f\" Key values: {highlights}\")\n", + "\n", + " # print(\"\\n--- Attempting FlatModel Construction (Row 1) ---\")\n", + " # try:\n", + " # flat_model = executor.execute_to_flat_model(\n", + " # SAMPLE_ROWS[0], direct_values=DIRECT_VALUES\n", + " # )\n", + " # print(\" FlatModel created successfully!\")\n", + " # print(f\" HeatingFuel={flat_model.HeatingFuel}\")\n", + " # print(f\" InfiltrationACH={flat_model.InfiltrationACH}\")\n", + " # print(f\" FacadeStructuralSystem={flat_model.FacadeStructuralSystem}\")\n", + " # print(\n", + " # f\" FacadeCavityInsulationRValue={flat_model.FacadeCavityInsulationRValue}\"\n", + " # )\n", + " # print(f\" WindowUValue={flat_model.WindowUValue}\")\n", + " # except Exception as exc:\n", + " # print(f\" FlatModel construction failed: {exc}\")\n", + "\n", + " # print(\"\\n--- Serialized DAG (JSON) ---\")\n", + " dag_json = dag.model_dump_json(indent=2)\n", + " from pathlib import Path\n", + "\n", + " Path(dag_output_path).write_text(dag_json)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e27d9b7c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# FlatModel Parameters\n", + "\n", + "## Equipment Schedule\n", + " - EquipmentBase (float) [ge=0, le=1] default=PydanticUndefined -- Overnight baseload fraction for equipment schedule [0-1].\n", + " - EquipmentAMInterp (float) [ge=0, le=1] default=PydanticUndefined -- Morning peak interpolation fraction for equipment schedule (6-9am) [0-1].\n", + " - EquipmentLunchInterp (float) [ge=0, le=1] default=PydanticUndefined -- Lunch period interpolation fraction for equipment schedule (12-1pm) [0-1].\n", + " - EquipmentPMInterp (float) [ge=0, le=1] default=PydanticUndefined -- Evening peak interpolation fraction for equipment schedule (6-8pm) [0-1].\n", + " - EquipmentWeekendPeakInterp (float) [ge=0, le=1] default=PydanticUndefined -- Weekend peak interpolation fraction for equipment schedule [0-1].\n", + " - EquipmentSummerPeakInterp (float) [ge=0, le=1] default=PydanticUndefined -- Summer peak interpolation fraction for equipment schedule [0-1].\n", + "\n", + "## Lighting Schedule\n", + " - LightingBase (float) [ge=0, le=1] default=PydanticUndefined -- Overnight baseload fraction for lighting schedule [0-1].\n", + " - LightingAMInterp (float) [ge=0, le=1] default=PydanticUndefined -- Morning peak interpolation fraction for lighting schedule (6-9am) [0-1].\n", + " - LightingLunchInterp (float) [ge=0, le=1] default=PydanticUndefined -- Lunch period interpolation fraction for lighting schedule (12-1pm) [0-1].\n", + " - LightingPMInterp (float) [ge=0, le=1] default=PydanticUndefined -- Evening peak interpolation fraction for lighting schedule (6-8pm) [0-1].\n", + " - LightingWeekendPeakInterp (float) [ge=0, le=1] default=PydanticUndefined -- Weekend peak interpolation fraction for lighting schedule [0-1].\n", + " - LightingSummerPeakInterp (float) [ge=0, le=1] default=PydanticUndefined -- Summer peak interpolation fraction for lighting schedule [0-1].\n", + "\n", + "## Occupancy Schedule\n", + " - OccupancyBase (float) [ge=0, le=1] default=PydanticUndefined -- Overnight baseload fraction for occupancy schedule [0-1].\n", + " - OccupancyAMInterp (float) [ge=0, le=1] default=PydanticUndefined -- Morning peak interpolation fraction for occupancy schedule (6-9am) [0-1].\n", + " - OccupancyLunchInterp (float) [ge=0, le=1] default=PydanticUndefined -- Lunch period interpolation fraction for occupancy schedule (12-1pm) [0-1].\n", + " - OccupancyPMInterp (float) [ge=0, le=1] default=PydanticUndefined -- Evening peak interpolation fraction for occupancy schedule (6-8pm) [0-1].\n", + " - OccupancyWeekendPeakInterp (float) [ge=0, le=1] default=PydanticUndefined -- Weekend peak interpolation fraction for occupancy schedule [0-1].\n", + " - OccupancySummerPeakInterp (float) [ge=0, le=1] default=PydanticUndefined -- Summer peak interpolation fraction for occupancy schedule [0-1].\n", + "\n", + "## Thermostat Setpoints\n", + " - HeatingSetpointBase (float) [ge=0, le=23] default=PydanticUndefined -- Base heating setpoint temperature [degC].\n", + " - SetpointDeadband (float) [ge=0, le=10] default=PydanticUndefined -- Temperature deadband between heating and cooling setpoints [degC].\n", + " - HeatingSetpointSetback (float) [ge=0, le=10] default=PydanticUndefined -- Heating setpoint setback amount during unoccupied periods [degC].\n", + " - CoolingSetpointSetback (float) [ge=0, le=10] default=PydanticUndefined -- Cooling setpoint setback amount during unoccupied periods [degC].\n", + " - NightSetback (float) [ge=0, le=1] default=PydanticUndefined -- Night setback factor applied to thermostat schedules [0-1].\n", + " - WeekendSetback (float) [ge=0, le=1] default=PydanticUndefined -- Weekend setback factor applied to thermostat schedules [0-1].\n", + " - SummerSetback (float) [ge=0, le=1] default=PydanticUndefined -- Summer setback factor applied to thermostat schedules [0-1].\n", + "\n", + "## HVAC Systems\n", + " - HeatingFuel (one of: ['Electricity', 'NaturalGas', 'Propane', 'FuelOil', 'WoodPellets', 'Coal', 'Gasoline', 'Diesel', 'CustomFuel', 'Steam', 'ChilledWater']) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Fuel type for the heating system.\n", + " - CoolingFuel (one of: ['Electricity', 'NaturalGas', 'Propane', 'FuelOil', 'WoodPellets', 'Coal', 'Gasoline', 'Diesel', 'CustomFuel', 'Steam', 'ChilledWater']) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Fuel type for the cooling system.\n", + " - HeatingSystemCOP (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Coefficient of performance for the heating system [dimensionless].\n", + " - CoolingSystemCOP (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Coefficient of performance for the cooling system [dimensionless].\n", + " - HeatingDistributionCOP (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Distribution efficiency for the heating system [dimensionless, 0-1].\n", + " - CoolingDistributionCOP (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Distribution efficiency for the cooling system [dimensionless, 0-1].\n", + "\n", + "## Space Use\n", + " - EquipmentPowerDensity (float) [ge=0, le=200] default=PydanticUndefined -- Internal equipment power density [W/m2].\n", + " - LightingPowerDensity (float) [ge=0, le=100] default=PydanticUndefined -- Lighting power density [W/m2].\n", + " - OccupantDensity (float) [ge=0, le=50] default=PydanticUndefined -- Occupant density [people/m2].\n", + "\n", + "## Ventilation\n", + " - VentFlowRatePerPerson (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Outdoor air ventilation flow rate per person [m3/s/person].\n", + " - VentFlowRatePerArea (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Outdoor air ventilation flow rate per floor area [m3/s/m2].\n", + " - VentProvider (one of: ['None', 'Natural', 'Mechanical', 'Both']) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Ventilation provider type (None, Natural, Mechanical, or Both).\n", + " - VentHRV (one of: ['NoHRV', 'Sensible', 'Enthalpy']) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Heat recovery ventilation method (NoHRV, Sensible, or Enthalpy).\n", + " - VentEconomizer (one of: ['NoEconomizer', 'DifferentialDryBulb', 'DifferentialEnthalpy']) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Economizer method (NoEconomizer, DifferentialDryBulb, or DifferentialEnthalpy).\n", + " - VentDCV (one of: ['NoDCV', 'OccupancySchedule', 'CO2Setpoint']) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Demand-controlled ventilation method (NoDCV, OccupancySchedule, or CO2Setpoint).\n", + "\n", + "## Domestic Hot Water\n", + " - DHWFlowRatePerPerson (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Domestic hot water flow rate per person [m3/s/person].\n", + " - DHWFuel (one of: ['Electricity', 'NaturalGas', 'Propane', 'FuelOil', 'Steam']) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Fuel type for the domestic hot water system.\n", + " - DHWSystemCOP (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Coefficient of performance for the DHW system [dimensionless].\n", + " - DHWDistributionCOP (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Distribution efficiency for the DHW system [dimensionless, 0-1].\n", + "\n", + "## Envelope\n", + " - InfiltrationACH (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Envelope infiltration rate [air changes per hour].\n", + "\n", + "## Windows\n", + " - WindowUValue (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Window assembly U-value [W/m2K].\n", + " - WindowSHGF (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Window solar heat gain factor [0-1].\n", + " - WindowTVis (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Window visible light transmittance [0-1].\n", + "\n", + "## Facade Construction\n", + " - FacadeStructuralSystem (one of: ['none', 'sheet_metal', 'light_gauge_steel', 'structural_steel', 'woodframe', 'deep_woodframe', 'woodframe_24oc', 'deep_woodframe_24oc', 'engineered_timber', 'timber_panel', 'cmu', 'double_layer_cmu', 'precast_concrete', 'poured_concrete', 'masonry', 'cavity_masonry', 'rammed_earth', 'thick_rammed_earth', 'reinforced_concrete', 'sip', 'icf', 'aac', 'thick_aac', 'hollow_clay_block', 'thick_hollow_clay_block', 'sandcrete_block', 'thick_sandcrete_block', 'stabilized_soil_block', 'wattle_and_daub']) [ge=[], gt=[], le=[], lt=[]] default=cmu -- Structural system type for facade walls.\n", + " - FacadeCavityInsulationRValue (float) [ge=0] default=0 -- Facade wall cavity insulation R-value [m2K/W].\n", + " - FacadeExteriorInsulationRValue (float) [ge=0] default=0 -- Facade wall exterior continuous insulation R-value [m2K/W].\n", + " - FacadeInteriorInsulationRValue (float) [ge=0] default=0 -- Facade wall interior insulation R-value [m2K/W].\n", + " - FacadeInteriorFinish (one of: ['none', 'drywall', 'plaster', 'cement_plaster', 'wood_panel']) [ge=[], gt=[], le=[], lt=[]] default=drywall -- Interior finish material for facade walls.\n", + " - FacadeExteriorFinish (one of: ['none', 'brick_veneer', 'stucco', 'fiber_cement', 'metal_panel', 'vinyl_siding', 'wood_siding', 'stone_veneer']) [ge=[], gt=[], le=[], lt=[]] default=none -- Exterior finish/cladding material for facade walls.\n", + "\n", + "## Roof Construction\n", + " - RoofStructuralSystem (one of: ['none', 'light_wood_truss', 'deep_wood_truss', 'steel_joist', 'metal_deck', 'mass_timber', 'precast_concrete', 'poured_concrete', 'reinforced_concrete', 'sip']) [ge=[], gt=[], le=[], lt=[]] default=poured_concrete -- Structural system type for the roof assembly.\n", + " - RoofCavityInsulationRValue (float) [ge=0] default=0 -- Roof cavity insulation R-value [m2K/W].\n", + " - RoofExteriorInsulationRValue (float) [ge=0] default=2.5 -- Roof exterior continuous insulation R-value [m2K/W].\n", + " - RoofInteriorInsulationRValue (float) [ge=0] default=0 -- Roof interior insulation R-value [m2K/W].\n", + " - RoofInteriorFinish (one of: ['none', 'gypsum_board', 'acoustic_tile', 'wood_panel']) [ge=[], gt=[], le=[], lt=[]] default=gypsum_board -- Interior finish material for the roof assembly.\n", + " - RoofExteriorFinish (one of: ['none', 'epdm_membrane', 'cool_membrane', 'built_up_roof', 'metal_roof', 'tile_roof', 'asphalt_shingle', 'wood_shake', 'thatch', 'fiber_cement_sheet']) [ge=[], gt=[], le=[], lt=[]] default=epdm_membrane -- Exterior finish/membrane for the roof assembly.\n", + "\n", + "## Slab Construction\n", + " - SlabStructuralSystem (one of: ['none', 'slab_on_grade', 'thickened_edge_slab', 'reinforced_concrete_suspended', 'precast_hollow_core', 'mass_timber_deck', 'sip_floor', 'compacted_earth_floor']) [ge=[], gt=[], le=[], lt=[]] default=slab_on_grade -- Structural system type for the floor slab.\n", + " - SlabInsulationRValue (float) [ge=0] default=1.5 -- Slab insulation R-value [m2K/W].\n", + " - SlabInsulationPlacement (one of: ['auto', 'under_slab', 'above_slab']) [ge=[], gt=[], le=[], lt=[]] default=auto -- Placement of slab insulation (auto, under_slab, or above_slab).\n", + " - SlabInteriorFinish (one of: ['none', 'polished_concrete', 'tile', 'carpet', 'wood_floor', 'cement_screed']) [ge=[], gt=[], le=[], lt=[]] default=tile -- Interior finish material for the floor slab.\n", + " - SlabExteriorFinish (one of: ['none', 'gypsum_board', 'plaster']) [ge=[], gt=[], le=[], lt=[]] default=none -- Exterior/underside finish material for the floor slab.\n", + "\n", + "## Geometry\n", + " - WWR (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Window-to-wall ratio [0-1].\n", + " - F2FHeight (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Floor-to-floor height [m].\n", + " - NFloors (int) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Number of above-grade floors.\n", + " - Width (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Building width [m].\n", + " - Depth (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Building depth [m].\n", + " - Rotation (float) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- Building rotation angle from north [degrees].\n", + "\n", + "## Weather\n", + " - EPWURI (AnyUrl | Path) [ge=[], gt=[], le=[], lt=[]] default=PydanticUndefined -- EPW weather file URI or local file path.\n", + "\n" + ] + } + ], + "source": [ + "from epinterface.sbem.decision_dag.schema_utils import get_flat_model_schema_description\n", + "\n", + "print(get_flat_model_schema_description())" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "1f7013b9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " DAG passed all structural validation checks.\n", + "\n", + " Row 1: {'income': 45000, 'year_built': 1925, 'building_typology': 'single_family_detached', 'weatherization_status': 'not_weatherized', 'last_renovation': 'never'}\n", + " Key values: {'HeatingFuel': 'FuelOil', 'HeatingSystemCOP': 0.82, 'InfiltrationACH': 1.0, 'FacadeStructuralSystem': 'woodframe', 'FacadeCavityInsulationRValue': 0.5, 'WindowUValue': 2.8}\n", + "\n", + " Row 2: {'income': 120000, 'year_built': 2018, 'building_typology': 'single_family_detached', 'weatherization_status': 'unknown', 'last_renovation': '2010_present'}\n", + " Key values: {'HeatingFuel': 'Electricity', 'HeatingSystemCOP': 3.0, 'InfiltrationACH': 0.5, 'FacadeStructuralSystem': 'woodframe', 'FacadeCavityInsulationRValue': 4.0, 'WindowUValue': 1.9}\n", + "\n", + " Row 3: {'year_built': 1955, 'building_typology': 'small_multifamily_2_4', 'weatherization_status': 'weatherized'}\n", + " Key values: {'HeatingFuel': 'FuelOil', 'HeatingSystemCOP': 0.82, 'InfiltrationACH': 0.5, 'FacadeStructuralSystem': 'woodframe', 'FacadeCavityInsulationRValue': 4.0, 'WindowUValue': 2.8}\n", + "\n", + " Row 4: {'building_typology': 'large_multifamily_20_plus'}\n", + " Key values: {'HeatingFuel': 'NaturalGas', 'HeatingSystemCOP': 0.85, 'InfiltrationACH': 0.65, 'FacadeStructuralSystem': 'woodframe', 'FacadeCavityInsulationRValue': 1.8, 'WindowUValue': 2.8}\n", + "\n", + " Row 5: (empty)\n", + " Key values: {'HeatingFuel': 'NaturalGas', 'HeatingSystemCOP': 0.85, 'InfiltrationACH': 0.65, 'FacadeStructuralSystem': 'woodframe', 'FacadeCavityInsulationRValue': 1.8, 'WindowUValue': 2.8}\n" + ] + }, + { + "data": { + "text/plain": [ + "'# Decision DAG Visualization\\n\\n> Decision DAG for Massachusetts (IECC 5A) residential buildings. Organized into independent subgraphs for schedules, thermostats, envelope (era-based with weatherization refinement), windows, HVAC & DHW, and space use/ventilation. Missing data is handled with sensible defaults (e.g., unknown weatherization treated as not weatherized unless recent renovation 2010_present). All required FlatModel parameters are assigned on every execution path via base components and refinements.\\n\\n## Summary\\n\\n- **Components**: 17\\n- **Nodes**: 25\\n - Condition: 7, Assignment: 1, ComponentRef: 17\\n- **Entry points**: 5 (`schedule_by_typology`, `thermostat_node`, `envelope_by_era`, `hvac_by_era`, `space_use_defaults`)\\n\\n## Graph\\n\\n```mermaid\\nflowchart TD\\n schedule_by_typology{{ENTRY: Schedules by typology.}}\\n schedule_by_typology -->|\"building_typology in [\\'single_family_detached\\', ...\"| apply_schedule_sf\\n schedule_by_typology -->|\"building_typology in [\\'small_multifamily_2_4\\', \\'...\"| apply_schedule_mf\\n schedule_by_typology -->|\"default\"| apply_schedule_sf\\n apply_schedule_sf([\"Residential Schedule - Single Family (18 fields)\"])\\n apply_schedule_mf([\"Residential Schedule - Multifamily (18 fields)\"])\\n thermostat_node{{ENTRY: Thermostat behavior.}}\\n thermostat_node -->|\"has_smart_thermostat eq yes\"| apply_thermostat_smart\\n thermostat_node -->|\"has_smart_thermostat eq no\"| apply_thermostat_constant\\n thermostat_node -->|\"default\"| apply_thermostat_constant\\n apply_thermostat_smart([\"Smart Thermostat (7 fields)\"])\\n apply_thermostat_constant([\"Constant Setpoint Thermostat (7 fields)\"])\\n envelope_by_era{{ENTRY: Envelope by year built.}}\\n envelope_by_era -->|\"year_built lt 1940\"| env_pre1940\\n envelope_by_era -->|\"year_built lt 1970\"| env_1940_1970\\n envelope_by_era -->|\"year_built lt 2000\"| env_1970_2000\\n envelope_by_era -->|\"year_built gte 2000\"| env_post2000\\n envelope_by_era -->|\"default\"| env_1940_1970\\n env_pre1940([\"Pre-1940 Uninsulated Envelope (18 fields)\"])\\n env_pre1940 --> weatherization_check\\n env_1940_1970([\"1940-1970 Minimal Insulation (18 fields)\"])\\n env_1940_1970 --> weatherization_check\\n env_1970_2000([\"1970-2000 Moderate Insulation (18 fields)\"])\\n env_1970_2000 --> weatherization_check\\n env_post2000([\"Post-2000 Code Envelope (18 fields)\"])\\n env_post2000 --> weatherization_check\\n weatherization_check{{Weatherization or recent renovation.}}\\n weatherization_check -->|\"weatherization_status eq weatherized\"| apply_weatherization\\n weatherization_check -->|\"last_renovation eq 2010_present\"| apply_weatherization\\n weatherization_check -->|\"default\"| windows_by_era\\n apply_weatherization([\"Weatherization Upgrade (4 fields)\"])\\n apply_weatherization --> windows_by_era\\n windows_by_era{{Windows by era.}}\\n windows_by_era -->|\"year_built gte 2000\"| win_post2000\\n windows_by_era -->|\"default\"| win_pre2000\\n win_pre2000([\"Pre-2000 Windows (3 fields)\"])\\n win_post2000([\"Post-2000 Windows (3 fields)\"])\\n hvac_by_era{{ENTRY: HVAC selection.}}\\n hvac_by_era -->|\"year_built gte 2010\"| hvac_hp\\n hvac_by_era -->|\"last_renovation eq 2010_present\"| hvac_hp\\n hvac_by_era -->|\"year_built lt 1970\"| hvac_oil\\n hvac_by_era -->|\"default\"| hvac_gas\\n hvac_gas([\"Gas Furnace + AC (6 fields)\"])\\n hvac_gas --> dhw_by_heating\\n hvac_oil([\"Oil Boiler (6 fields)\"])\\n hvac_oil --> dhw_by_heating\\n hvac_hp([\"Cold Climate Heat Pump (6 fields)\"])\\n hvac_hp --> dhw_electric_node\\n dhw_by_heating{{DHW fuel by era proxy.}}\\n dhw_by_heating -->|\"year_built lt 1970\"| apply_dhw_oil\\n dhw_by_heating -->|\"default\"| apply_dhw_gas\\n apply_dhw_gas([\"Gas DHW (3 fields)\"])\\n apply_dhw_oil([\"Oil DHW (3 fields)\"])\\n dhw_electric_node([\"Electric DHW (3 fields)\"])\\n space_use_defaults[\"ENTRY: Internal loads and ventilation defaults. (10 fields)\"]\\n```\\n\\n## Node Inventory\\n\\n| ID | Type | Description | Entry? |\\n|---|---|---|---|\\n| `schedule_by_typology` | condition | Schedules by typology. | yes |\\n| `apply_schedule_sf` | component_ref | SF schedule. | |\\n| `apply_schedule_mf` | component_ref | MF schedule. | |\\n| `thermostat_node` | condition | Thermostat behavior. | yes |\\n| `apply_thermostat_smart` | component_ref | Smart thermostat. | |\\n| `apply_thermostat_constant` | component_ref | Constant thermostat. | |\\n| `envelope_by_era` | condition | Envelope by year built. | yes |\\n| `env_pre1940` | component_ref | Pre-1940 envelope. | |\\n| `env_1940_1970` | component_ref | 1940-1970 envelope. | |\\n| `env_1970_2000` | component_ref | 1970-2000 envelope. | |\\n| `env_post2000` | component_ref | Post-2000 envelope. | |\\n| `weatherization_check` | condition | Weatherization or recent renovation. | |\\n| `apply_weatherization` | component_ref | Apply WAP. | |\\n| `windows_by_era` | condition | Windows by era. | |\\n| `win_pre2000` | component_ref | Older windows. | |\\n| `win_post2000` | component_ref | Newer windows. | |\\n| `hvac_by_era` | condition | HVAC selection. | yes |\\n| `hvac_gas` | component_ref | Gas system. | |\\n| `hvac_oil` | component_ref | Oil system. | |\\n| `hvac_hp` | component_ref | Heat pump. | |\\n| `dhw_by_heating` | condition | DHW fuel by era proxy. | |\\n| `apply_dhw_gas` | component_ref | Gas DHW. | |\\n| `apply_dhw_oil` | component_ref | Oil DHW. | |\\n| `dhw_electric_node` | component_ref | Electric DHW. | |\\n| `space_use_defaults` | assignment | Internal loads and ventilation defaults. | yes |\\n\\n## Intermediate Components\\n\\n| ID | Name | Fields | Description |\\n|---|---|---|---|\\n| `residential_schedule_single_family` | Residential Schedule - Single Family | `EquipmentAMInterp`, `EquipmentBase`, `EquipmentLunchInterp`, `EquipmentPMInterp`, `EquipmentSummerPeakInterp`, `EquipmentWeekendPeakInterp`, `LightingAMInterp`, `LightingBase`, `LightingLunchInterp`, `LightingPMInterp`, `LightingSummerPeakInterp`, `LightingWeekendPeakInterp`, `OccupancyAMInterp`, `OccupancyBase`, `OccupancyLunchInterp`, `OccupancyPMInterp`, `OccupancySummerPeakInterp`, `OccupancyWeekendPeakInterp` | Typical MA single-family occupancy patterns with strong evening peaks and mod... |\\n| `residential_schedule_multifamily` | Residential Schedule - Multifamily | `EquipmentAMInterp`, `EquipmentBase`, `EquipmentLunchInterp`, `EquipmentPMInterp`, `EquipmentSummerPeakInterp`, `EquipmentWeekendPeakInterp`, `LightingAMInterp`, `LightingBase`, `LightingLunchInterp`, `LightingPMInterp`, `LightingSummerPeakInterp`, `LightingWeekendPeakInterp`, `OccupancyAMInterp`, `OccupancyBase`, `OccupancyLunchInterp`, `OccupancyPMInterp`, `OccupancySummerPeakInterp`, `OccupancyWeekendPeakInterp` | Multifamily schedules with slightly higher daytime occupancy. |\\n| `thermostat_constant` | Constant Setpoint Thermostat | `CoolingSetpointSetback`, `HeatingSetpointBase`, `HeatingSetpointSetback`, `NightSetback`, `SetpointDeadband`, `SummerSetback`, `WeekendSetback` | No smart thermostat; constant setpoints. |\\n| `thermostat_smart` | Smart Thermostat | `CoolingSetpointSetback`, `HeatingSetpointBase`, `HeatingSetpointSetback`, `NightSetback`, `SetpointDeadband`, `SummerSetback`, `WeekendSetback` | Smart thermostat with moderate setbacks. |\\n| `envelope_pre1940_base` | Pre-1940 Uninsulated Envelope | `FacadeCavityInsulationRValue`, `FacadeExteriorFinish`, `FacadeExteriorInsulationRValue`, `FacadeInteriorFinish`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorFinish`, `RoofExteriorInsulationRValue`, `RoofInteriorFinish`, `RoofInteriorInsulationRValue`, `RoofStructuralSystem`, `SlabExteriorFinish`, `SlabInsulationPlacement`, `SlabInsulationRValue`, `SlabInteriorFinish`, `SlabStructuralSystem` | Balloon-frame/masonry, high infiltration. |\\n| `envelope_1940_1970_base` | 1940-1970 Minimal Insulation | `FacadeCavityInsulationRValue`, `FacadeExteriorFinish`, `FacadeExteriorInsulationRValue`, `FacadeInteriorFinish`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorFinish`, `RoofExteriorInsulationRValue`, `RoofInteriorFinish`, `RoofInteriorInsulationRValue`, `RoofStructuralSystem`, `SlabExteriorFinish`, `SlabInsulationPlacement`, `SlabInsulationRValue`, `SlabInteriorFinish`, `SlabStructuralSystem` | Low cavity insulation, moderate infiltration. |\\n| `envelope_1970_2000_base` | 1970-2000 Moderate Insulation | `FacadeCavityInsulationRValue`, `FacadeExteriorFinish`, `FacadeExteriorInsulationRValue`, `FacadeInteriorFinish`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorFinish`, `RoofExteriorInsulationRValue`, `RoofInteriorFinish`, `RoofInteriorInsulationRValue`, `RoofStructuralSystem`, `SlabExteriorFinish`, `SlabInsulationPlacement`, `SlabInsulationRValue`, `SlabInteriorFinish`, `SlabStructuralSystem` | Improved insulation and air sealing. |\\n| `envelope_post2000_base` | Post-2000 Code Envelope | `FacadeCavityInsulationRValue`, `FacadeExteriorFinish`, `FacadeExteriorInsulationRValue`, `FacadeInteriorFinish`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorFinish`, `RoofExteriorInsulationRValue`, `RoofInteriorFinish`, `RoofInteriorInsulationRValue`, `RoofStructuralSystem`, `SlabExteriorFinish`, `SlabInsulationPlacement`, `SlabInsulationRValue`, `SlabInteriorFinish`, `SlabStructuralSystem` | IECC-era construction. |\\n| `weatherization_upgrade` | Weatherization Upgrade | `FacadeCavityInsulationRValue`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `SlabInsulationRValue` | WAP improvements. |\\n| `windows_pre2000` | Pre-2000 Windows | `WindowSHGF`, `WindowTVis`, `WindowUValue` | Older double-pane. |\\n| `windows_post2000` | Post-2000 Windows | `WindowSHGF`, `WindowTVis`, `WindowUValue` | Low-e double-pane. |\\n| `hvac_gas_furnace` | Gas Furnace + AC | `CoolingDistributionCOP`, `CoolingFuel`, `CoolingSystemCOP`, `HeatingDistributionCOP`, `HeatingFuel`, `HeatingSystemCOP` | Typical MA gas system. |\\n| `hvac_oil_boiler` | Oil Boiler | `CoolingDistributionCOP`, `CoolingFuel`, `CoolingSystemCOP`, `HeatingDistributionCOP`, `HeatingFuel`, `HeatingSystemCOP` | Oil heat, limited AC. |\\n| `hvac_heat_pump` | Cold Climate Heat Pump | `CoolingDistributionCOP`, `CoolingFuel`, `CoolingSystemCOP`, `HeatingDistributionCOP`, `HeatingFuel`, `HeatingSystemCOP` | Modern heat pump. |\\n| `dhw_gas` | Gas DHW | `DHWDistributionCOP`, `DHWFuel`, `DHWSystemCOP` | Gas storage water heater. |\\n| `dhw_oil` | Oil DHW | `DHWDistributionCOP`, `DHWFuel`, `DHWSystemCOP` | Oil water heater. |\\n| `dhw_electric` | Electric DHW | `DHWDistributionCOP`, `DHWFuel`, `DHWSystemCOP` | Electric resistance water heater. |\\n\\n### Component Details\\n\\n#### Residential Schedule - Single Family (`residential_schedule_single_family`)\\n\\nTypical MA single-family occupancy patterns with strong evening peaks and moderate weekend activity.\\n\\n- `EquipmentBase` = `0.3`\\n- `EquipmentAMInterp` = `0.6`\\n- `EquipmentLunchInterp` = `0.5`\\n- `EquipmentPMInterp` = `0.9`\\n- `EquipmentWeekendPeakInterp` = `0.8`\\n- `EquipmentSummerPeakInterp` = `0.95`\\n- `LightingBase` = `0.2`\\n- `LightingAMInterp` = `0.5`\\n- `LightingLunchInterp` = `0.4`\\n- `LightingPMInterp` = `0.95`\\n- `LightingWeekendPeakInterp` = `0.85`\\n- `LightingSummerPeakInterp` = `0.9`\\n- `OccupancyBase` = `0.8`\\n- `OccupancyAMInterp` = `0.6`\\n- `OccupancyLunchInterp` = `0.7`\\n- `OccupancyPMInterp` = `0.95`\\n- `OccupancyWeekendPeakInterp` = `0.95`\\n- `OccupancySummerPeakInterp` = `1.0`\\n\\n#### Residential Schedule - Multifamily (`residential_schedule_multifamily`)\\n\\nMultifamily schedules with slightly higher daytime occupancy.\\n\\n- `EquipmentBase` = `0.35`\\n- `EquipmentAMInterp` = `0.6`\\n- `EquipmentLunchInterp` = `0.55`\\n- `EquipmentPMInterp` = `0.9`\\n- `EquipmentWeekendPeakInterp` = `0.85`\\n- `EquipmentSummerPeakInterp` = `0.95`\\n- `LightingBase` = `0.25`\\n- `LightingAMInterp` = `0.5`\\n- `LightingLunchInterp` = `0.45`\\n- `LightingPMInterp` = `0.95`\\n- `LightingWeekendPeakInterp` = `0.9`\\n- `LightingSummerPeakInterp` = `0.9`\\n- `OccupancyBase` = `0.85`\\n- `OccupancyAMInterp` = `0.65`\\n- `OccupancyLunchInterp` = `0.75`\\n- `OccupancyPMInterp` = `0.95`\\n- `OccupancyWeekendPeakInterp` = `0.98`\\n- `OccupancySummerPeakInterp` = `1.0`\\n\\n#### Constant Setpoint Thermostat (`thermostat_constant`)\\n\\nNo smart thermostat; constant setpoints.\\n\\n- `HeatingSetpointBase` = `21.0`\\n- `SetpointDeadband` = `3.0`\\n- `HeatingSetpointSetback` = `0.0`\\n- `CoolingSetpointSetback` = `0.0`\\n- `NightSetback` = `0.0`\\n- `WeekendSetback` = `0.0`\\n- `SummerSetback` = `0.0`\\n\\n#### Smart Thermostat (`thermostat_smart`)\\n\\nSmart thermostat with moderate setbacks.\\n\\n- `HeatingSetpointBase` = `21.0`\\n- `SetpointDeadband` = `3.0`\\n- `HeatingSetpointSetback` = `3.0`\\n- `CoolingSetpointSetback` = `2.0`\\n- `NightSetback` = `0.8`\\n- `WeekendSetback` = `0.9`\\n- `SummerSetback` = `0.9`\\n\\n#### Pre-1940 Uninsulated Envelope (`envelope_pre1940_base`)\\n\\nBalloon-frame/masonry, high infiltration.\\n\\n- `FacadeStructuralSystem` = `woodframe`\\n- `FacadeCavityInsulationRValue` = `0.5`\\n- `FacadeExteriorInsulationRValue` = `0.0`\\n- `FacadeInteriorInsulationRValue` = `0.0`\\n- `FacadeInteriorFinish` = `plaster`\\n- `FacadeExteriorFinish` = `wood_siding`\\n- `RoofStructuralSystem` = `light_wood_truss`\\n- `RoofCavityInsulationRValue` = `2.0`\\n- `RoofExteriorInsulationRValue` = `0.0`\\n- `RoofInteriorInsulationRValue` = `0.0`\\n- `RoofInteriorFinish` = `gypsum_board`\\n- `RoofExteriorFinish` = `asphalt_shingle`\\n- `SlabStructuralSystem` = `slab_on_grade`\\n- `SlabInsulationRValue` = `0.5`\\n- `SlabInsulationPlacement` = `under_slab`\\n- `SlabInteriorFinish` = `wood_floor`\\n- `SlabExteriorFinish` = `none`\\n- `InfiltrationACH` = `1.0`\\n\\n#### 1940-1970 Minimal Insulation (`envelope_1940_1970_base`)\\n\\nLow cavity insulation, moderate infiltration.\\n\\n- `FacadeStructuralSystem` = `woodframe`\\n- `FacadeCavityInsulationRValue` = `1.8`\\n- `FacadeExteriorInsulationRValue` = `0.0`\\n- `FacadeInteriorInsulationRValue` = `0.0`\\n- `FacadeInteriorFinish` = `drywall`\\n- `FacadeExteriorFinish` = `vinyl_siding`\\n- `RoofStructuralSystem` = `light_wood_truss`\\n- `RoofCavityInsulationRValue` = `3.5`\\n- `RoofExteriorInsulationRValue` = `0.0`\\n- `RoofInteriorInsulationRValue` = `0.0`\\n- `RoofInteriorFinish` = `gypsum_board`\\n- `RoofExteriorFinish` = `asphalt_shingle`\\n- `SlabStructuralSystem` = `slab_on_grade`\\n- `SlabInsulationRValue` = `1.0`\\n- `SlabInsulationPlacement` = `under_slab`\\n- `SlabInteriorFinish` = `wood_floor`\\n- `SlabExteriorFinish` = `none`\\n- `InfiltrationACH` = `0.65`\\n\\n#### 1970-2000 Moderate Insulation (`envelope_1970_2000_base`)\\n\\nImproved insulation and air sealing.\\n\\n- `FacadeStructuralSystem` = `woodframe`\\n- `FacadeCavityInsulationRValue` = `3.0`\\n- `FacadeExteriorInsulationRValue` = `0.5`\\n- `FacadeInteriorInsulationRValue` = `0.0`\\n- `FacadeInteriorFinish` = `drywall`\\n- `FacadeExteriorFinish` = `vinyl_siding`\\n- `RoofStructuralSystem` = `light_wood_truss`\\n- `RoofCavityInsulationRValue` = `5.0`\\n- `RoofExteriorInsulationRValue` = `0.0`\\n- `RoofInteriorInsulationRValue` = `0.0`\\n- `RoofInteriorFinish` = `gypsum_board`\\n- `RoofExteriorFinish` = `asphalt_shingle`\\n- `SlabStructuralSystem` = `slab_on_grade`\\n- `SlabInsulationRValue` = `1.5`\\n- `SlabInsulationPlacement` = `under_slab`\\n- `SlabInteriorFinish` = `wood_floor`\\n- `SlabExteriorFinish` = `none`\\n- `InfiltrationACH` = `0.45`\\n\\n#### Post-2000 Code Envelope (`envelope_post2000_base`)\\n\\nIECC-era construction.\\n\\n- `FacadeStructuralSystem` = `woodframe`\\n- `FacadeCavityInsulationRValue` = `3.5`\\n- `FacadeExteriorInsulationRValue` = `1.0`\\n- `FacadeInteriorInsulationRValue` = `0.0`\\n- `FacadeInteriorFinish` = `drywall`\\n- `FacadeExteriorFinish` = `vinyl_siding`\\n- `RoofStructuralSystem` = `light_wood_truss`\\n- `RoofCavityInsulationRValue` = `8.0`\\n- `RoofExteriorInsulationRValue` = `0.5`\\n- `RoofInteriorInsulationRValue` = `0.0`\\n- `RoofInteriorFinish` = `gypsum_board`\\n- `RoofExteriorFinish` = `asphalt_shingle`\\n- `SlabStructuralSystem` = `slab_on_grade`\\n- `SlabInsulationRValue` = `2.0`\\n- `SlabInsulationPlacement` = `under_slab`\\n- `SlabInteriorFinish` = `wood_floor`\\n- `SlabExteriorFinish` = `none`\\n- `InfiltrationACH` = `0.25`\\n\\n#### Weatherization Upgrade (`weatherization_upgrade`)\\n\\nWAP improvements.\\n\\n- `FacadeCavityInsulationRValue` = `4.0`\\n- `RoofCavityInsulationRValue` = `10.0`\\n- `SlabInsulationRValue` = `2.0`\\n- `InfiltrationACH` = `0.5`\\n\\n#### Pre-2000 Windows (`windows_pre2000`)\\n\\nOlder double-pane.\\n\\n- `WindowUValue` = `2.8`\\n- `WindowSHGF` = `0.6`\\n- `WindowTVis` = `0.6`\\n\\n#### Post-2000 Windows (`windows_post2000`)\\n\\nLow-e double-pane.\\n\\n- `WindowUValue` = `1.9`\\n- `WindowSHGF` = `0.4`\\n- `WindowTVis` = `0.55`\\n\\n#### Gas Furnace + AC (`hvac_gas_furnace`)\\n\\nTypical MA gas system.\\n\\n- `HeatingFuel` = `NaturalGas`\\n- `CoolingFuel` = `Electricity`\\n- `HeatingSystemCOP` = `0.85`\\n- `CoolingSystemCOP` = `3.0`\\n- `HeatingDistributionCOP` = `0.85`\\n- `CoolingDistributionCOP` = `0.9`\\n\\n#### Oil Boiler (`hvac_oil_boiler`)\\n\\nOil heat, limited AC.\\n\\n- `HeatingFuel` = `FuelOil`\\n- `CoolingFuel` = `Electricity`\\n- `HeatingSystemCOP` = `0.82`\\n- `CoolingSystemCOP` = `2.5`\\n- `HeatingDistributionCOP` = `0.8`\\n- `CoolingDistributionCOP` = `0.8`\\n\\n#### Cold Climate Heat Pump (`hvac_heat_pump`)\\n\\nModern heat pump.\\n\\n- `HeatingFuel` = `Electricity`\\n- `CoolingFuel` = `Electricity`\\n- `HeatingSystemCOP` = `3.0`\\n- `CoolingSystemCOP` = `3.5`\\n- `HeatingDistributionCOP` = `0.95`\\n- `CoolingDistributionCOP` = `0.95`\\n\\n#### Gas DHW (`dhw_gas`)\\n\\nGas storage water heater.\\n\\n- `DHWFuel` = `NaturalGas`\\n- `DHWSystemCOP` = `0.65`\\n- `DHWDistributionCOP` = `0.8`\\n\\n#### Oil DHW (`dhw_oil`)\\n\\nOil water heater.\\n\\n- `DHWFuel` = `FuelOil`\\n- `DHWSystemCOP` = `0.6`\\n- `DHWDistributionCOP` = `0.75`\\n\\n#### Electric DHW (`dhw_electric`)\\n\\nElectric resistance water heater.\\n\\n- `DHWFuel` = `Electricity`\\n- `DHWSystemCOP` = `0.95`\\n- `DHWDistributionCOP` = `0.9`\\n\\n## Parameter Coverage\\n\\n- **Equipment Schedule**: 6/6 (FULL)\\n- **Lighting Schedule**: 6/6 (FULL)\\n- **Occupancy Schedule**: 6/6 (FULL)\\n- **Thermostat Setpoints**: 7/7 (FULL)\\n- **HVAC Systems**: 6/6 (FULL)\\n- **Space Use**: 3/3 (FULL)\\n- **Ventilation**: 6/6 (FULL)\\n- **Domestic Hot Water**: 4/4 (FULL)\\n- **Envelope**: 1/1 (FULL)\\n- **Windows**: 3/3 (FULL)\\n- **Facade Construction**: 6/6 (FULL)\\n- **Roof Construction**: 6/6 (FULL)\\n- **Slab Construction**: 5/5 (FULL)\\n- **Geometry**: 0/6 (NONE)\\n- **Weather**: 0/1 (NONE)\\n\\n## Validation\\n\\nAll structural validation checks passed.\\n\\n## User Fields\\n\\n- **income** (numeric): Annual household income in USD. Correlates loosely with ability to invest in energy upgrades.\\n - Data quality: Self-reported on utility assistance applications. About 30% of rows are missing.\\n- **year_built** (numeric): Year the building was originally constructed.\\n - Data quality: From assessor records; generally reliable, though some entries are approximate decades (e.g. 1900 for anything pre-1910).\\n- **building_typology** (categorical): Building typology classification from assessor data.\\n - Data quality: Assessor-derived, reliable.\\n- **weatherization_status** (categorical): Whether the building has been through a weatherization assistance program.\\n - Data quality: From state WAP records. Only captures state-funded programs; private weatherization is not tracked. About 60% of rows are missing (unknown status).\\n- **last_renovation** (categorical): Approximate timeframe of last known major renovation or retrofit.\\n - Data quality: From permit records where available. Very sparse -- roughly 70% missing.\\n- **has_smart_thermostat** (categorical): Whether the building has a smart thermostat.\\n - Data quality: We conducted a survey of all of the buildings and know precisely if it has a smart thermostat.\\n'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import yaml\n", + "\n", + "from epinterface.sbem.decision_dag.visualize import visualize_dag_from_files\n", + "\n", + "fieldset_path = \"working_user_field_set.yaml\"\n", + "outpath = \"working_dag.json\"\n", + "md_viz_path = \"working_dag.md\"\n", + "with open(fieldset_path) as f:\n", + " FIELD_SET = UserFieldSet.model_validate(yaml.safe_load(f))\n", + "\n", + "await main(FIELD_SET, outpath)\n", + "\n", + "visualize_dag_from_files(\n", + " dag_path=outpath,\n", + " field_set_path=fieldset_path,\n", + " output_path=md_viz_path,\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d94e692e", + "metadata": {}, + "outputs": [], + "source": [ + "executor" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tests/test_decision_dag/visualized_dag.md b/tests/test_decision_dag/visualized_dag.md new file mode 100644 index 0000000..921e944 --- /dev/null +++ b/tests/test_decision_dag/visualized_dag.md @@ -0,0 +1,375 @@ +# Decision DAG Visualization + +> Decision DAG for Massachusetts (CZ5A) residential buildings. Organized into parallel sub-DAGs: (1) Weather default; (2) Schedules & internal loads by typology; (3) Thermostats; (4) Envelope by era with weatherization override; (5) Windows by era; (6) HVAC by era (dominant system) with deterministic mapping; (7) Ventilation by era/weatherization. Operators corrected to valid schema (eq, neq, lt, lte, gt, gte, in). All required FlatModel parameters are assigned via components on every path with sensible MA defaults. + +## Summary + +- **Components**: 17 +- **Nodes**: 24 + - Condition: 7, Assignment: 0, ComponentRef: 17 +- **Entry points**: 7 (`n_weather`, `n_typology_sched`, `n_typology_loads`, `n_thermostat`, `n_year_env`, `n_hvac_by_year`, `n_vent_by_era`) + +## Graph + +```mermaid +flowchart TD + n_weather(["ENTRY: Massachusetts Weather Default (1 fields)"]) + n_typology_sched{{ENTRY: Schedule by typology.}} + n_typology_sched -->|"building_typology in ['single_family_detached', ..."| n_sched_sf + n_typology_sched -->|"building_typology in ['small_multifamily_2_4', '..."| n_sched_mf + n_typology_sched -->|"default"| n_sched_sf + n_sched_sf(["Residential Schedule - Single Family (18 fields)"]) + n_sched_mf(["Residential Schedule - Multifamily (18 fields)"]) + n_typology_loads{{ENTRY: Loads by typology.}} + n_typology_loads -->|"building_typology in ['single_family_detached', ..."| n_loads_sf + n_typology_loads -->|"building_typology in ['small_multifamily_2_4', '..."| n_loads_mf + n_typology_loads -->|"default"| n_loads_sf + n_loads_sf(["Internal Loads - Single Family (4 fields)"]) + n_loads_mf(["Internal Loads - Multifamily (4 fields)"]) + n_thermostat(["ENTRY: Residential Thermostat Default (7 fields)"]) + n_year_env{{ENTRY: Envelope by era.}} + n_year_env -->|"year_built lt 1940"| n_env_pre1940 + n_year_env -->|"year_built lt 1970"| n_env_1940_1970 + n_year_env -->|"year_built lt 2000"| n_env_1970_2000 + n_year_env -->|"year_built gte 2000"| n_env_post2000 + n_year_env -->|"default"| n_env_1940_1970 + n_env_pre1940(["Envelope Pre-1940 Unweatherized (10 fields)"]) + n_env_pre1940 --> n_weatherization + n_env_1940_1970(["Envelope 1940-1970 Unweatherized (10 fields)"]) + n_env_1940_1970 --> n_weatherization + n_env_1970_2000(["Envelope 1970-2000 Unweatherized (10 fields)"]) + n_env_1970_2000 --> n_weatherization + n_env_post2000(["Envelope Post-2000 Code-Level (10 fields)"]) + n_env_post2000 --> n_weatherization + n_weatherization{{Weatherization override.}} + n_weatherization -->|"weatherization_status eq weatherized"| n_weatherized_apply + n_weatherization -->|"default"| n_windows_by_year + n_weatherized_apply(["Weatherization Upgrade (4 fields)"]) + n_weatherized_apply --> n_windows_by_year + n_windows_by_year{{Windows by era.}} + n_windows_by_year -->|"year_built gte 2000"| n_windows_post2000 + n_windows_by_year -->|"default"| n_windows_pre2000 + n_windows_pre2000(["Windows Pre-2000 Double Pane (3 fields)"]) + n_windows_post2000(["Windows Post-2000 Low-E (3 fields)"]) + n_hvac_by_year{{ENTRY: HVAC by era.}} + n_hvac_by_year -->|"year_built gte 2000"| n_hvac_post2000 + n_hvac_by_year -->|"default"| n_hvac_gas + n_hvac_gas(["Gas Furnace (9 fields)"]) + n_hvac_post2000(["Cold Climate Heat Pump (9 fields)"]) + n_vent_by_era{{ENTRY: Ventilation by era/weatherization.}} + n_vent_by_era -->|"year_built gte 2000"| n_vent_mech + n_vent_by_era -->|"weatherization_status eq weatherized"| n_vent_mech + n_vent_by_era -->|"default"| n_vent_nat + n_vent_nat(["Natural Ventilation Only (6 fields)"]) + n_vent_mech(["Mechanical Exhaust (6 fields)"]) +``` + +## Node Inventory + +| ID | Type | Description | Entry? | +|---|---|---|---| +| `n_weather` | component_ref | Apply MA weather. | yes | +| `n_typology_sched` | condition | Schedule by typology. | yes | +| `n_sched_sf` | component_ref | SF schedule. | | +| `n_sched_mf` | component_ref | MF schedule. | | +| `n_typology_loads` | condition | Loads by typology. | yes | +| `n_loads_sf` | component_ref | SF loads. | | +| `n_loads_mf` | component_ref | MF loads. | | +| `n_thermostat` | component_ref | Thermostat defaults. | yes | +| `n_year_env` | condition | Envelope by era. | yes | +| `n_env_pre1940` | component_ref | Pre-1940 envelope. | | +| `n_env_1940_1970` | component_ref | 1940-1970 envelope. | | +| `n_env_1970_2000` | component_ref | 1970-2000 envelope. | | +| `n_env_post2000` | component_ref | Post-2000 envelope. | | +| `n_weatherization` | condition | Weatherization override. | | +| `n_weatherized_apply` | component_ref | Apply weatherization. | | +| `n_windows_by_year` | condition | Windows by era. | | +| `n_windows_pre2000` | component_ref | Pre-2000 windows. | | +| `n_windows_post2000` | component_ref | Post-2000 windows. | | +| `n_hvac_by_year` | condition | HVAC by era. | yes | +| `n_hvac_gas` | component_ref | Gas furnace default. | | +| `n_hvac_post2000` | component_ref | Heat pump default. | | +| `n_vent_by_era` | condition | Ventilation by era/weatherization. | yes | +| `n_vent_nat` | component_ref | Natural ventilation. | | +| `n_vent_mech` | component_ref | Mechanical exhaust. | | + +## Intermediate Components + +| ID | Name | Fields | Description | +|---|---|---|---| +| `res_sched_sf` | Residential Schedule - Single Family | `EquipmentAMInterp`, `EquipmentBase`, `EquipmentLunchInterp`, `EquipmentPMInterp`, `EquipmentSummerPeakInterp`, `EquipmentWeekendPeakInterp`, `LightingAMInterp`, `LightingBase`, `LightingLunchInterp`, `LightingPMInterp`, `LightingSummerPeakInterp`, `LightingWeekendPeakInterp`, `OccupancyAMInterp`, `OccupancyBase`, `OccupancyLunchInterp`, `OccupancyPMInterp`, `OccupancySummerPeakInterp`, `OccupancyWeekendPeakInterp` | Typical MA single-family occupancy patterns. | +| `res_sched_mf` | Residential Schedule - Multifamily | `EquipmentAMInterp`, `EquipmentBase`, `EquipmentLunchInterp`, `EquipmentPMInterp`, `EquipmentSummerPeakInterp`, `EquipmentWeekendPeakInterp`, `LightingAMInterp`, `LightingBase`, `LightingLunchInterp`, `LightingPMInterp`, `LightingSummerPeakInterp`, `LightingWeekendPeakInterp`, `OccupancyAMInterp`, `OccupancyBase`, `OccupancyLunchInterp`, `OccupancyPMInterp`, `OccupancySummerPeakInterp`, `OccupancyWeekendPeakInterp` | Multifamily with slightly higher daytime occupancy. | +| `loads_sf` | Internal Loads - Single Family | `DHWFlowRatePerPerson`, `EquipmentPowerDensity`, `LightingPowerDensity`, `OccupantDensity` | Typical MA single-family densities. | +| `loads_mf` | Internal Loads - Multifamily | `DHWFlowRatePerPerson`, `EquipmentPowerDensity`, `LightingPowerDensity`, `OccupantDensity` | Higher densities for multifamily. | +| `thermostat_default` | Residential Thermostat Default | `CoolingSetpointSetback`, `HeatingSetpointBase`, `HeatingSetpointSetback`, `NightSetback`, `SetpointDeadband`, `SummerSetback`, `WeekendSetback` | Heating-dominated CZ5A residential setpoints. | +| `env_pre1940` | Envelope Pre-1940 Unweatherized | `FacadeCavityInsulationRValue`, `FacadeExteriorInsulationRValue`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorInsulationRValue`, `RoofStructuralSystem`, `SlabInsulationRValue`, `SlabStructuralSystem` | Uninsulated, very leaky. | +| `env_1940_1970` | Envelope 1940-1970 Unweatherized | `FacadeCavityInsulationRValue`, `FacadeExteriorInsulationRValue`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorInsulationRValue`, `RoofStructuralSystem`, `SlabInsulationRValue`, `SlabStructuralSystem` | Minimal cavity insulation. | +| `env_1970_2000` | Envelope 1970-2000 Unweatherized | `FacadeCavityInsulationRValue`, `FacadeExteriorInsulationRValue`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorInsulationRValue`, `RoofStructuralSystem`, `SlabInsulationRValue`, `SlabStructuralSystem` | Improved cavity insulation. | +| `env_post2000` | Envelope Post-2000 Code-Level | `FacadeCavityInsulationRValue`, `FacadeExteriorInsulationRValue`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorInsulationRValue`, `RoofStructuralSystem`, `SlabInsulationRValue`, `SlabStructuralSystem` | IECC-era construction. | +| `weatherization_upgrade` | Weatherization Upgrade | `FacadeCavityInsulationRValue`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `SlabInsulationRValue` | Air sealing and insulation improvements. | +| `windows_pre2000` | Windows Pre-2000 Double Pane | `WindowSHGF`, `WindowTVis`, `WindowUValue` | Older double-pane. | +| `windows_post2000` | Windows Post-2000 Low-E | `WindowSHGF`, `WindowTVis`, `WindowUValue` | Low-e double pane. | +| `hvac_gas_furnace` | Gas Furnace | `CoolingDistributionCOP`, `CoolingFuel`, `CoolingSystemCOP`, `DHWDistributionCOP`, `DHWFuel`, `DHWSystemCOP`, `HeatingDistributionCOP`, `HeatingFuel`, `HeatingSystemCOP` | Standard gas furnace with AC. | +| `hvac_heat_pump` | Cold Climate Heat Pump | `CoolingDistributionCOP`, `CoolingFuel`, `CoolingSystemCOP`, `DHWDistributionCOP`, `DHWFuel`, `DHWSystemCOP`, `HeatingDistributionCOP`, `HeatingFuel`, `HeatingSystemCOP` | Modern ASHP. | +| `vent_natural` | Natural Ventilation Only | `VentDCV`, `VentEconomizer`, `VentFlowRatePerArea`, `VentFlowRatePerPerson`, `VentHRV`, `VentProvider` | Infiltration-driven. | +| `vent_mech_exhaust` | Mechanical Exhaust | `VentDCV`, `VentEconomizer`, `VentFlowRatePerArea`, `VentFlowRatePerPerson`, `VentHRV`, `VentProvider` | Basic exhaust. | +| `ma_weather` | Massachusetts Weather Default | `EPWURI` | Boston Logan TMY3. | + +### Component Details + +#### Residential Schedule - Single Family (`res_sched_sf`) + +Typical MA single-family occupancy patterns. + +- `EquipmentBase` = `0.3` +- `EquipmentAMInterp` = `0.6` +- `EquipmentLunchInterp` = `0.5` +- `EquipmentPMInterp` = `0.9` +- `EquipmentWeekendPeakInterp` = `0.95` +- `EquipmentSummerPeakInterp` = `0.95` +- `LightingBase` = `0.1` +- `LightingAMInterp` = `0.5` +- `LightingLunchInterp` = `0.4` +- `LightingPMInterp` = `0.95` +- `LightingWeekendPeakInterp` = `0.95` +- `LightingSummerPeakInterp` = `0.9` +- `OccupancyBase` = `0.8` +- `OccupancyAMInterp` = `0.6` +- `OccupancyLunchInterp` = `0.5` +- `OccupancyPMInterp` = `0.95` +- `OccupancyWeekendPeakInterp` = `0.98` +- `OccupancySummerPeakInterp` = `0.98` + +#### Residential Schedule - Multifamily (`res_sched_mf`) + +Multifamily with slightly higher daytime occupancy. + +- `EquipmentBase` = `0.35` +- `EquipmentAMInterp` = `0.65` +- `EquipmentLunchInterp` = `0.6` +- `EquipmentPMInterp` = `0.95` +- `EquipmentWeekendPeakInterp` = `0.98` +- `EquipmentSummerPeakInterp` = `0.98` +- `LightingBase` = `0.15` +- `LightingAMInterp` = `0.55` +- `LightingLunchInterp` = `0.5` +- `LightingPMInterp` = `0.98` +- `LightingWeekendPeakInterp` = `0.98` +- `LightingSummerPeakInterp` = `0.92` +- `OccupancyBase` = `0.85` +- `OccupancyAMInterp` = `0.7` +- `OccupancyLunchInterp` = `0.65` +- `OccupancyPMInterp` = `0.98` +- `OccupancyWeekendPeakInterp` = `0.99` +- `OccupancySummerPeakInterp` = `0.99` + +#### Internal Loads - Single Family (`loads_sf`) + +Typical MA single-family densities. + +- `EquipmentPowerDensity` = `6.0` +- `LightingPowerDensity` = `5.0` +- `OccupantDensity` = `0.03` +- `DHWFlowRatePerPerson` = `3e-05` + +#### Internal Loads - Multifamily (`loads_mf`) + +Higher densities for multifamily. + +- `EquipmentPowerDensity` = `7.5` +- `LightingPowerDensity` = `6.0` +- `OccupantDensity` = `0.05` +- `DHWFlowRatePerPerson` = `3.5e-05` + +#### Residential Thermostat Default (`thermostat_default`) + +Heating-dominated CZ5A residential setpoints. + +- `HeatingSetpointBase` = `21.0` +- `SetpointDeadband` = `3.0` +- `HeatingSetpointSetback` = `3.0` +- `CoolingSetpointSetback` = `2.0` +- `NightSetback` = `0.9` +- `WeekendSetback` = `0.95` +- `SummerSetback` = `0.9` + +#### Envelope Pre-1940 Unweatherized (`env_pre1940`) + +Uninsulated, very leaky. + +- `FacadeStructuralSystem` = `woodframe` +- `FacadeCavityInsulationRValue` = `0.5` +- `FacadeExteriorInsulationRValue` = `0.0` +- `FacadeInteriorInsulationRValue` = `0.0` +- `InfiltrationACH` = `1.1` +- `RoofStructuralSystem` = `light_wood_truss` +- `RoofCavityInsulationRValue` = `2.0` +- `RoofExteriorInsulationRValue` = `0.0` +- `SlabStructuralSystem` = `slab_on_grade` +- `SlabInsulationRValue` = `0.5` + +#### Envelope 1940-1970 Unweatherized (`env_1940_1970`) + +Minimal cavity insulation. + +- `FacadeStructuralSystem` = `woodframe` +- `FacadeCavityInsulationRValue` = `1.5` +- `FacadeExteriorInsulationRValue` = `0.0` +- `FacadeInteriorInsulationRValue` = `0.0` +- `InfiltrationACH` = `0.7` +- `RoofStructuralSystem` = `light_wood_truss` +- `RoofCavityInsulationRValue` = `3.5` +- `RoofExteriorInsulationRValue` = `0.0` +- `SlabStructuralSystem` = `slab_on_grade` +- `SlabInsulationRValue` = `0.8` + +#### Envelope 1970-2000 Unweatherized (`env_1970_2000`) + +Improved cavity insulation. + +- `FacadeStructuralSystem` = `woodframe` +- `FacadeCavityInsulationRValue` = `2.5` +- `FacadeExteriorInsulationRValue` = `0.5` +- `FacadeInteriorInsulationRValue` = `0.0` +- `InfiltrationACH` = `0.45` +- `RoofStructuralSystem` = `light_wood_truss` +- `RoofCavityInsulationRValue` = `5.0` +- `RoofExteriorInsulationRValue` = `0.5` +- `SlabStructuralSystem` = `slab_on_grade` +- `SlabInsulationRValue` = `1.2` + +#### Envelope Post-2000 Code-Level (`env_post2000`) + +IECC-era construction. + +- `FacadeStructuralSystem` = `woodframe` +- `FacadeCavityInsulationRValue` = `3.5` +- `FacadeExteriorInsulationRValue` = `1.0` +- `FacadeInteriorInsulationRValue` = `0.0` +- `InfiltrationACH` = `0.25` +- `RoofStructuralSystem` = `light_wood_truss` +- `RoofCavityInsulationRValue` = `8.0` +- `RoofExteriorInsulationRValue` = `1.5` +- `SlabStructuralSystem` = `slab_on_grade` +- `SlabInsulationRValue` = `2.0` + +#### Weatherization Upgrade (`weatherization_upgrade`) + +Air sealing and insulation improvements. + +- `FacadeCavityInsulationRValue` = `3.0` +- `RoofCavityInsulationRValue` = `8.0` +- `SlabInsulationRValue` = `1.5` +- `InfiltrationACH` = `0.5` + +#### Windows Pre-2000 Double Pane (`windows_pre2000`) + +Older double-pane. + +- `WindowUValue` = `2.7` +- `WindowSHGF` = `0.55` +- `WindowTVis` = `0.6` + +#### Windows Post-2000 Low-E (`windows_post2000`) + +Low-e double pane. + +- `WindowUValue` = `1.8` +- `WindowSHGF` = `0.4` +- `WindowTVis` = `0.55` + +#### Gas Furnace (`hvac_gas_furnace`) + +Standard gas furnace with AC. + +- `HeatingFuel` = `NaturalGas` +- `HeatingSystemCOP` = `0.85` +- `HeatingDistributionCOP` = `0.8` +- `CoolingFuel` = `Electricity` +- `CoolingSystemCOP` = `3.0` +- `CoolingDistributionCOP` = `0.8` +- `DHWFuel` = `NaturalGas` +- `DHWSystemCOP` = `0.6` +- `DHWDistributionCOP` = `0.8` + +#### Cold Climate Heat Pump (`hvac_heat_pump`) + +Modern ASHP. + +- `HeatingFuel` = `Electricity` +- `HeatingSystemCOP` = `3.0` +- `HeatingDistributionCOP` = `0.95` +- `CoolingFuel` = `Electricity` +- `CoolingSystemCOP` = `3.2` +- `CoolingDistributionCOP` = `0.95` +- `DHWFuel` = `Electricity` +- `DHWSystemCOP` = `2.5` +- `DHWDistributionCOP` = `0.9` + +#### Natural Ventilation Only (`vent_natural`) + +Infiltration-driven. + +- `VentFlowRatePerPerson` = `0.0` +- `VentFlowRatePerArea` = `0.0002` +- `VentProvider` = `Natural` +- `VentHRV` = `NoHRV` +- `VentEconomizer` = `NoEconomizer` +- `VentDCV` = `NoDCV` + +#### Mechanical Exhaust (`vent_mech_exhaust`) + +Basic exhaust. + +- `VentFlowRatePerPerson` = `0.0003` +- `VentFlowRatePerArea` = `0.0001` +- `VentProvider` = `Mechanical` +- `VentHRV` = `NoHRV` +- `VentEconomizer` = `NoEconomizer` +- `VentDCV` = `NoDCV` + +#### Massachusetts Weather Default (`ma_weather`) + +Boston Logan TMY3. + +- `EPWURI` = `USA_MA_Boston-Logan.Intl.AP.725090_TMY3.epw` + +## Parameter Coverage + +- **Equipment Schedule**: 6/6 (FULL) +- **Lighting Schedule**: 6/6 (FULL) +- **Occupancy Schedule**: 6/6 (FULL) +- **Thermostat Setpoints**: 7/7 (FULL) +- **HVAC Systems**: 6/6 (FULL) +- **Space Use**: 3/3 (FULL) +- **Ventilation**: 6/6 (FULL) +- **Domestic Hot Water**: 4/4 (FULL) +- **Envelope**: 1/1 (FULL) +- **Windows**: 3/3 (FULL) +- **Facade Construction**: 4/6 (PARTIAL) + - Missing: `FacadeInteriorFinish`, `FacadeExteriorFinish` +- **Roof Construction**: 3/6 (PARTIAL) + - Missing: `RoofInteriorInsulationRValue`, `RoofInteriorFinish`, `RoofExteriorFinish` +- **Slab Construction**: 2/5 (PARTIAL) + - Missing: `SlabInsulationPlacement`, `SlabInteriorFinish`, `SlabExteriorFinish` +- **Geometry**: 0/6 (NONE) +- **Weather**: 1/1 (FULL) + +## Validation + +Found **1** issue(s): + +- The following FlatModel fields are never assigned: ['FacadeExteriorFinish', 'FacadeInteriorFinish', 'RoofExteriorFinish', 'RoofInteriorFinish', 'RoofInteriorInsulationRValue', 'SlabExteriorFinish', 'SlabInsulationPlacement', 'SlabInteriorFinish'] + +## User Fields + +- **income** (numeric): Annual household income in USD. Correlates loosely with ability to invest in energy upgrades. + - Data quality: Self-reported on utility assistance applications. About 30% of rows are missing. +- **year_built** (numeric): Year the building was originally constructed. + - Data quality: From assessor records; generally reliable, though some entries are approximate decades (e.g. 1900 for anything pre-1910). +- **building_typology** (categorical): Building typology classification from assessor data. + - Data quality: Assessor-derived, reliable. +- **weatherization_status** (categorical): Whether the building has been through a weatherization assistance program. + - Data quality: From state WAP records. Only captures state-funded programs; private weatherization is not tracked. About 60% of rows are missing (unknown status). +- **last_renovation** (categorical): Approximate timeframe of last known major renovation or retrofit. + - Data quality: From permit records where available. Very sparse -- roughly 70% missing. diff --git a/tests/test_decision_dag/working_dag.json b/tests/test_decision_dag/working_dag.json new file mode 100644 index 0000000..0cca663 --- /dev/null +++ b/tests/test_decision_dag/working_dag.json @@ -0,0 +1,628 @@ +{ + "description": "Decision DAG for Massachusetts (IECC 5A) residential buildings. Organized into independent subgraphs for schedules, thermostats, envelope (era-based with weatherization refinement), windows, HVAC & DHW, and space use/ventilation. Missing data is handled with sensible defaults (e.g., unknown weatherization treated as not weatherized unless recent renovation 2010_present). All required FlatModel parameters are assigned on every execution path via base components and refinements.", + "components": [ + { + "id": "residential_schedule_single_family", + "name": "Residential Schedule - Single Family", + "description": "Typical MA single-family occupancy patterns with strong evening peaks and moderate weekend activity.", + "assignments": { + "EquipmentBase": 0.3, + "EquipmentAMInterp": 0.6, + "EquipmentLunchInterp": 0.5, + "EquipmentPMInterp": 0.9, + "EquipmentWeekendPeakInterp": 0.8, + "EquipmentSummerPeakInterp": 0.95, + "LightingBase": 0.2, + "LightingAMInterp": 0.5, + "LightingLunchInterp": 0.4, + "LightingPMInterp": 0.95, + "LightingWeekendPeakInterp": 0.85, + "LightingSummerPeakInterp": 0.9, + "OccupancyBase": 0.8, + "OccupancyAMInterp": 0.6, + "OccupancyLunchInterp": 0.7, + "OccupancyPMInterp": 0.95, + "OccupancyWeekendPeakInterp": 0.95, + "OccupancySummerPeakInterp": 1.0 + } + }, + { + "id": "residential_schedule_multifamily", + "name": "Residential Schedule - Multifamily", + "description": "Multifamily schedules with slightly higher daytime occupancy.", + "assignments": { + "EquipmentBase": 0.35, + "EquipmentAMInterp": 0.6, + "EquipmentLunchInterp": 0.55, + "EquipmentPMInterp": 0.9, + "EquipmentWeekendPeakInterp": 0.85, + "EquipmentSummerPeakInterp": 0.95, + "LightingBase": 0.25, + "LightingAMInterp": 0.5, + "LightingLunchInterp": 0.45, + "LightingPMInterp": 0.95, + "LightingWeekendPeakInterp": 0.9, + "LightingSummerPeakInterp": 0.9, + "OccupancyBase": 0.85, + "OccupancyAMInterp": 0.65, + "OccupancyLunchInterp": 0.75, + "OccupancyPMInterp": 0.95, + "OccupancyWeekendPeakInterp": 0.98, + "OccupancySummerPeakInterp": 1.0 + } + }, + { + "id": "thermostat_constant", + "name": "Constant Setpoint Thermostat", + "description": "No smart thermostat; constant setpoints.", + "assignments": { + "HeatingSetpointBase": 21.0, + "SetpointDeadband": 3.0, + "HeatingSetpointSetback": 0.0, + "CoolingSetpointSetback": 0.0, + "NightSetback": 0.0, + "WeekendSetback": 0.0, + "SummerSetback": 0.0 + } + }, + { + "id": "thermostat_smart", + "name": "Smart Thermostat", + "description": "Smart thermostat with moderate setbacks.", + "assignments": { + "HeatingSetpointBase": 21.0, + "SetpointDeadband": 3.0, + "HeatingSetpointSetback": 3.0, + "CoolingSetpointSetback": 2.0, + "NightSetback": 0.8, + "WeekendSetback": 0.9, + "SummerSetback": 0.9 + } + }, + { + "id": "envelope_pre1940_base", + "name": "Pre-1940 Uninsulated Envelope", + "description": "Balloon-frame/masonry, high infiltration.", + "assignments": { + "FacadeStructuralSystem": "woodframe", + "FacadeCavityInsulationRValue": 0.5, + "FacadeExteriorInsulationRValue": 0.0, + "FacadeInteriorInsulationRValue": 0.0, + "FacadeInteriorFinish": "plaster", + "FacadeExteriorFinish": "wood_siding", + "RoofStructuralSystem": "light_wood_truss", + "RoofCavityInsulationRValue": 2.0, + "RoofExteriorInsulationRValue": 0.0, + "RoofInteriorInsulationRValue": 0.0, + "RoofInteriorFinish": "gypsum_board", + "RoofExteriorFinish": "asphalt_shingle", + "SlabStructuralSystem": "slab_on_grade", + "SlabInsulationRValue": 0.5, + "SlabInsulationPlacement": "under_slab", + "SlabInteriorFinish": "wood_floor", + "SlabExteriorFinish": "none", + "InfiltrationACH": 1.0 + } + }, + { + "id": "envelope_1940_1970_base", + "name": "1940-1970 Minimal Insulation", + "description": "Low cavity insulation, moderate infiltration.", + "assignments": { + "FacadeStructuralSystem": "woodframe", + "FacadeCavityInsulationRValue": 1.8, + "FacadeExteriorInsulationRValue": 0.0, + "FacadeInteriorInsulationRValue": 0.0, + "FacadeInteriorFinish": "drywall", + "FacadeExteriorFinish": "vinyl_siding", + "RoofStructuralSystem": "light_wood_truss", + "RoofCavityInsulationRValue": 3.5, + "RoofExteriorInsulationRValue": 0.0, + "RoofInteriorInsulationRValue": 0.0, + "RoofInteriorFinish": "gypsum_board", + "RoofExteriorFinish": "asphalt_shingle", + "SlabStructuralSystem": "slab_on_grade", + "SlabInsulationRValue": 1.0, + "SlabInsulationPlacement": "under_slab", + "SlabInteriorFinish": "wood_floor", + "SlabExteriorFinish": "none", + "InfiltrationACH": 0.65 + } + }, + { + "id": "envelope_1970_2000_base", + "name": "1970-2000 Moderate Insulation", + "description": "Improved insulation and air sealing.", + "assignments": { + "FacadeStructuralSystem": "woodframe", + "FacadeCavityInsulationRValue": 3.0, + "FacadeExteriorInsulationRValue": 0.5, + "FacadeInteriorInsulationRValue": 0.0, + "FacadeInteriorFinish": "drywall", + "FacadeExteriorFinish": "vinyl_siding", + "RoofStructuralSystem": "light_wood_truss", + "RoofCavityInsulationRValue": 5.0, + "RoofExteriorInsulationRValue": 0.0, + "RoofInteriorInsulationRValue": 0.0, + "RoofInteriorFinish": "gypsum_board", + "RoofExteriorFinish": "asphalt_shingle", + "SlabStructuralSystem": "slab_on_grade", + "SlabInsulationRValue": 1.5, + "SlabInsulationPlacement": "under_slab", + "SlabInteriorFinish": "wood_floor", + "SlabExteriorFinish": "none", + "InfiltrationACH": 0.45 + } + }, + { + "id": "envelope_post2000_base", + "name": "Post-2000 Code Envelope", + "description": "IECC-era construction.", + "assignments": { + "FacadeStructuralSystem": "woodframe", + "FacadeCavityInsulationRValue": 3.5, + "FacadeExteriorInsulationRValue": 1.0, + "FacadeInteriorInsulationRValue": 0.0, + "FacadeInteriorFinish": "drywall", + "FacadeExteriorFinish": "vinyl_siding", + "RoofStructuralSystem": "light_wood_truss", + "RoofCavityInsulationRValue": 8.0, + "RoofExteriorInsulationRValue": 0.5, + "RoofInteriorInsulationRValue": 0.0, + "RoofInteriorFinish": "gypsum_board", + "RoofExteriorFinish": "asphalt_shingle", + "SlabStructuralSystem": "slab_on_grade", + "SlabInsulationRValue": 2.0, + "SlabInsulationPlacement": "under_slab", + "SlabInteriorFinish": "wood_floor", + "SlabExteriorFinish": "none", + "InfiltrationACH": 0.25 + } + }, + { + "id": "weatherization_upgrade", + "name": "Weatherization Upgrade", + "description": "WAP improvements.", + "assignments": { + "FacadeCavityInsulationRValue": 4.0, + "RoofCavityInsulationRValue": 10.0, + "SlabInsulationRValue": 2.0, + "InfiltrationACH": 0.5 + } + }, + { + "id": "windows_pre2000", + "name": "Pre-2000 Windows", + "description": "Older double-pane.", + "assignments": { + "WindowUValue": 2.8, + "WindowSHGF": 0.6, + "WindowTVis": 0.6 + } + }, + { + "id": "windows_post2000", + "name": "Post-2000 Windows", + "description": "Low-e double-pane.", + "assignments": { + "WindowUValue": 1.9, + "WindowSHGF": 0.4, + "WindowTVis": 0.55 + } + }, + { + "id": "hvac_gas_furnace", + "name": "Gas Furnace + AC", + "description": "Typical MA gas system.", + "assignments": { + "HeatingFuel": "NaturalGas", + "CoolingFuel": "Electricity", + "HeatingSystemCOP": 0.85, + "CoolingSystemCOP": 3.0, + "HeatingDistributionCOP": 0.85, + "CoolingDistributionCOP": 0.9 + } + }, + { + "id": "hvac_oil_boiler", + "name": "Oil Boiler", + "description": "Oil heat, limited AC.", + "assignments": { + "HeatingFuel": "FuelOil", + "CoolingFuel": "Electricity", + "HeatingSystemCOP": 0.82, + "CoolingSystemCOP": 2.5, + "HeatingDistributionCOP": 0.8, + "CoolingDistributionCOP": 0.8 + } + }, + { + "id": "hvac_heat_pump", + "name": "Cold Climate Heat Pump", + "description": "Modern heat pump.", + "assignments": { + "HeatingFuel": "Electricity", + "CoolingFuel": "Electricity", + "HeatingSystemCOP": 3.0, + "CoolingSystemCOP": 3.5, + "HeatingDistributionCOP": 0.95, + "CoolingDistributionCOP": 0.95 + } + }, + { + "id": "dhw_gas", + "name": "Gas DHW", + "description": "Gas storage water heater.", + "assignments": { + "DHWFuel": "NaturalGas", + "DHWSystemCOP": 0.65, + "DHWDistributionCOP": 0.8 + } + }, + { + "id": "dhw_oil", + "name": "Oil DHW", + "description": "Oil water heater.", + "assignments": { + "DHWFuel": "FuelOil", + "DHWSystemCOP": 0.6, + "DHWDistributionCOP": 0.75 + } + }, + { + "id": "dhw_electric", + "name": "Electric DHW", + "description": "Electric resistance water heater.", + "assignments": { + "DHWFuel": "Electricity", + "DHWSystemCOP": 0.95, + "DHWDistributionCOP": 0.9 + } + } + ], + "nodes": [ + { + "node_type": "condition", + "id": "schedule_by_typology", + "description": "Schedules by typology.", + "branches": [ + { + "condition": { + "field": "building_typology", + "operator": "in", + "value": [ + "single_family_detached", + "single_family_attached" + ] + }, + "target_node_id": "apply_schedule_sf" + }, + { + "condition": { + "field": "building_typology", + "operator": "in", + "value": [ + "small_multifamily_2_4", + "medium_multifamily_5_20", + "large_multifamily_20_plus" + ] + }, + "target_node_id": "apply_schedule_mf" + } + ], + "default_target_id": "apply_schedule_sf" + }, + { + "node_type": "component_ref", + "id": "apply_schedule_sf", + "description": "SF schedule.", + "component_id": "residential_schedule_single_family", + "next_node_ids": [] + }, + { + "node_type": "component_ref", + "id": "apply_schedule_mf", + "description": "MF schedule.", + "component_id": "residential_schedule_multifamily", + "next_node_ids": [] + }, + { + "node_type": "condition", + "id": "thermostat_node", + "description": "Thermostat behavior.", + "branches": [ + { + "condition": { + "field": "has_smart_thermostat", + "operator": "eq", + "value": "yes" + }, + "target_node_id": "apply_thermostat_smart" + }, + { + "condition": { + "field": "has_smart_thermostat", + "operator": "eq", + "value": "no" + }, + "target_node_id": "apply_thermostat_constant" + } + ], + "default_target_id": "apply_thermostat_constant" + }, + { + "node_type": "component_ref", + "id": "apply_thermostat_smart", + "description": "Smart thermostat.", + "component_id": "thermostat_smart", + "next_node_ids": [] + }, + { + "node_type": "component_ref", + "id": "apply_thermostat_constant", + "description": "Constant thermostat.", + "component_id": "thermostat_constant", + "next_node_ids": [] + }, + { + "node_type": "condition", + "id": "envelope_by_era", + "description": "Envelope by year built.", + "branches": [ + { + "condition": { + "field": "year_built", + "operator": "lt", + "value": 1940 + }, + "target_node_id": "env_pre1940" + }, + { + "condition": { + "field": "year_built", + "operator": "lt", + "value": 1970 + }, + "target_node_id": "env_1940_1970" + }, + { + "condition": { + "field": "year_built", + "operator": "lt", + "value": 2000 + }, + "target_node_id": "env_1970_2000" + }, + { + "condition": { + "field": "year_built", + "operator": "gte", + "value": 2000 + }, + "target_node_id": "env_post2000" + } + ], + "default_target_id": "env_1940_1970" + }, + { + "node_type": "component_ref", + "id": "env_pre1940", + "description": "Pre-1940 envelope.", + "component_id": "envelope_pre1940_base", + "next_node_ids": [ + "weatherization_check" + ] + }, + { + "node_type": "component_ref", + "id": "env_1940_1970", + "description": "1940-1970 envelope.", + "component_id": "envelope_1940_1970_base", + "next_node_ids": [ + "weatherization_check" + ] + }, + { + "node_type": "component_ref", + "id": "env_1970_2000", + "description": "1970-2000 envelope.", + "component_id": "envelope_1970_2000_base", + "next_node_ids": [ + "weatherization_check" + ] + }, + { + "node_type": "component_ref", + "id": "env_post2000", + "description": "Post-2000 envelope.", + "component_id": "envelope_post2000_base", + "next_node_ids": [ + "weatherization_check" + ] + }, + { + "node_type": "condition", + "id": "weatherization_check", + "description": "Weatherization or recent renovation.", + "branches": [ + { + "condition": { + "field": "weatherization_status", + "operator": "eq", + "value": "weatherized" + }, + "target_node_id": "apply_weatherization" + }, + { + "condition": { + "field": "last_renovation", + "operator": "eq", + "value": "2010_present" + }, + "target_node_id": "apply_weatherization" + } + ], + "default_target_id": "windows_by_era" + }, + { + "node_type": "component_ref", + "id": "apply_weatherization", + "description": "Apply WAP.", + "component_id": "weatherization_upgrade", + "next_node_ids": [ + "windows_by_era" + ] + }, + { + "node_type": "condition", + "id": "windows_by_era", + "description": "Windows by era.", + "branches": [ + { + "condition": { + "field": "year_built", + "operator": "gte", + "value": 2000 + }, + "target_node_id": "win_post2000" + } + ], + "default_target_id": "win_pre2000" + }, + { + "node_type": "component_ref", + "id": "win_pre2000", + "description": "Older windows.", + "component_id": "windows_pre2000", + "next_node_ids": [] + }, + { + "node_type": "component_ref", + "id": "win_post2000", + "description": "Newer windows.", + "component_id": "windows_post2000", + "next_node_ids": [] + }, + { + "node_type": "condition", + "id": "hvac_by_era", + "description": "HVAC selection.", + "branches": [ + { + "condition": { + "field": "year_built", + "operator": "gte", + "value": 2010 + }, + "target_node_id": "hvac_hp" + }, + { + "condition": { + "field": "last_renovation", + "operator": "eq", + "value": "2010_present" + }, + "target_node_id": "hvac_hp" + }, + { + "condition": { + "field": "year_built", + "operator": "lt", + "value": 1970 + }, + "target_node_id": "hvac_oil" + } + ], + "default_target_id": "hvac_gas" + }, + { + "node_type": "component_ref", + "id": "hvac_gas", + "description": "Gas system.", + "component_id": "hvac_gas_furnace", + "next_node_ids": [ + "dhw_by_heating" + ] + }, + { + "node_type": "component_ref", + "id": "hvac_oil", + "description": "Oil system.", + "component_id": "hvac_oil_boiler", + "next_node_ids": [ + "dhw_by_heating" + ] + }, + { + "node_type": "component_ref", + "id": "hvac_hp", + "description": "Heat pump.", + "component_id": "hvac_heat_pump", + "next_node_ids": [ + "dhw_electric_node" + ] + }, + { + "node_type": "condition", + "id": "dhw_by_heating", + "description": "DHW fuel by era proxy.", + "branches": [ + { + "condition": { + "field": "year_built", + "operator": "lt", + "value": 1970 + }, + "target_node_id": "apply_dhw_oil" + } + ], + "default_target_id": "apply_dhw_gas" + }, + { + "node_type": "component_ref", + "id": "apply_dhw_gas", + "description": "Gas DHW.", + "component_id": "dhw_gas", + "next_node_ids": [] + }, + { + "node_type": "component_ref", + "id": "apply_dhw_oil", + "description": "Oil DHW.", + "component_id": "dhw_oil", + "next_node_ids": [] + }, + { + "node_type": "component_ref", + "id": "dhw_electric_node", + "description": "Electric DHW.", + "component_id": "dhw_electric", + "next_node_ids": [] + }, + { + "node_type": "assignment", + "id": "space_use_defaults", + "description": "Internal loads and ventilation defaults.", + "assignments": { + "EquipmentPowerDensity": 8.0, + "LightingPowerDensity": 6.0, + "OccupantDensity": 0.04, + "VentFlowRatePerPerson": 0.004, + "VentFlowRatePerArea": 0.0003, + "VentProvider": "Natural", + "VentHRV": "NoHRV", + "VentEconomizer": "NoEconomizer", + "VentDCV": "NoDCV", + "DHWFlowRatePerPerson": 0.00002 + }, + "next_node_ids": [] + } + ], + "entry_node_ids": [ + "schedule_by_typology", + "thermostat_node", + "envelope_by_era", + "hvac_by_era", + "space_use_defaults" + ] +} \ No newline at end of file diff --git a/tests/test_decision_dag/working_dag.md b/tests/test_decision_dag/working_dag.md new file mode 100644 index 0000000..f721241 --- /dev/null +++ b/tests/test_decision_dag/working_dag.md @@ -0,0 +1,406 @@ +# Decision DAG Visualization + +> Decision DAG for Massachusetts (IECC 5A) residential buildings. Organized into independent subgraphs for schedules, thermostats, envelope (era-based with weatherization refinement), windows, HVAC & DHW, and space use/ventilation. Missing data is handled with sensible defaults (e.g., unknown weatherization treated as not weatherized unless recent renovation 2010_present). All required FlatModel parameters are assigned on every execution path via base components and refinements. + +## Summary + +- **Components**: 17 +- **Nodes**: 25 + - Condition: 7, Assignment: 1, ComponentRef: 17 +- **Entry points**: 5 (`schedule_by_typology`, `thermostat_node`, `envelope_by_era`, `hvac_by_era`, `space_use_defaults`) + +## Graph + +```mermaid +flowchart TD + schedule_by_typology{{ENTRY: Schedules by typology.}} + schedule_by_typology -->|"building_typology in ['single_family_detached', ..."| apply_schedule_sf + schedule_by_typology -->|"building_typology in ['small_multifamily_2_4', '..."| apply_schedule_mf + schedule_by_typology -->|"default"| apply_schedule_sf + apply_schedule_sf(["Residential Schedule - Single Family (18 fields)"]) + apply_schedule_mf(["Residential Schedule - Multifamily (18 fields)"]) + thermostat_node{{ENTRY: Thermostat behavior.}} + thermostat_node -->|"has_smart_thermostat eq yes"| apply_thermostat_smart + thermostat_node -->|"has_smart_thermostat eq no"| apply_thermostat_constant + thermostat_node -->|"default"| apply_thermostat_constant + apply_thermostat_smart(["Smart Thermostat (7 fields)"]) + apply_thermostat_constant(["Constant Setpoint Thermostat (7 fields)"]) + envelope_by_era{{ENTRY: Envelope by year built.}} + envelope_by_era -->|"year_built lt 1940"| env_pre1940 + envelope_by_era -->|"year_built lt 1970"| env_1940_1970 + envelope_by_era -->|"year_built lt 2000"| env_1970_2000 + envelope_by_era -->|"year_built gte 2000"| env_post2000 + envelope_by_era -->|"default"| env_1940_1970 + env_pre1940(["Pre-1940 Uninsulated Envelope (18 fields)"]) + env_pre1940 --> weatherization_check + env_1940_1970(["1940-1970 Minimal Insulation (18 fields)"]) + env_1940_1970 --> weatherization_check + env_1970_2000(["1970-2000 Moderate Insulation (18 fields)"]) + env_1970_2000 --> weatherization_check + env_post2000(["Post-2000 Code Envelope (18 fields)"]) + env_post2000 --> weatherization_check + weatherization_check{{Weatherization or recent renovation.}} + weatherization_check -->|"weatherization_status eq weatherized"| apply_weatherization + weatherization_check -->|"last_renovation eq 2010_present"| apply_weatherization + weatherization_check -->|"default"| windows_by_era + apply_weatherization(["Weatherization Upgrade (4 fields)"]) + apply_weatherization --> windows_by_era + windows_by_era{{Windows by era.}} + windows_by_era -->|"year_built gte 2000"| win_post2000 + windows_by_era -->|"default"| win_pre2000 + win_pre2000(["Pre-2000 Windows (3 fields)"]) + win_post2000(["Post-2000 Windows (3 fields)"]) + hvac_by_era{{ENTRY: HVAC selection.}} + hvac_by_era -->|"year_built gte 2010"| hvac_hp + hvac_by_era -->|"last_renovation eq 2010_present"| hvac_hp + hvac_by_era -->|"year_built lt 1970"| hvac_oil + hvac_by_era -->|"default"| hvac_gas + hvac_gas(["Gas Furnace + AC (6 fields)"]) + hvac_gas --> dhw_by_heating + hvac_oil(["Oil Boiler (6 fields)"]) + hvac_oil --> dhw_by_heating + hvac_hp(["Cold Climate Heat Pump (6 fields)"]) + hvac_hp --> dhw_electric_node + dhw_by_heating{{DHW fuel by era proxy.}} + dhw_by_heating -->|"year_built lt 1970"| apply_dhw_oil + dhw_by_heating -->|"default"| apply_dhw_gas + apply_dhw_gas(["Gas DHW (3 fields)"]) + apply_dhw_oil(["Oil DHW (3 fields)"]) + dhw_electric_node(["Electric DHW (3 fields)"]) + space_use_defaults["ENTRY: Internal loads and ventilation defaults. (10 fields)"] +``` + +## Node Inventory + +| ID | Type | Description | Entry? | +|---|---|---|---| +| `schedule_by_typology` | condition | Schedules by typology. | yes | +| `apply_schedule_sf` | component_ref | SF schedule. | | +| `apply_schedule_mf` | component_ref | MF schedule. | | +| `thermostat_node` | condition | Thermostat behavior. | yes | +| `apply_thermostat_smart` | component_ref | Smart thermostat. | | +| `apply_thermostat_constant` | component_ref | Constant thermostat. | | +| `envelope_by_era` | condition | Envelope by year built. | yes | +| `env_pre1940` | component_ref | Pre-1940 envelope. | | +| `env_1940_1970` | component_ref | 1940-1970 envelope. | | +| `env_1970_2000` | component_ref | 1970-2000 envelope. | | +| `env_post2000` | component_ref | Post-2000 envelope. | | +| `weatherization_check` | condition | Weatherization or recent renovation. | | +| `apply_weatherization` | component_ref | Apply WAP. | | +| `windows_by_era` | condition | Windows by era. | | +| `win_pre2000` | component_ref | Older windows. | | +| `win_post2000` | component_ref | Newer windows. | | +| `hvac_by_era` | condition | HVAC selection. | yes | +| `hvac_gas` | component_ref | Gas system. | | +| `hvac_oil` | component_ref | Oil system. | | +| `hvac_hp` | component_ref | Heat pump. | | +| `dhw_by_heating` | condition | DHW fuel by era proxy. | | +| `apply_dhw_gas` | component_ref | Gas DHW. | | +| `apply_dhw_oil` | component_ref | Oil DHW. | | +| `dhw_electric_node` | component_ref | Electric DHW. | | +| `space_use_defaults` | assignment | Internal loads and ventilation defaults. | yes | + +## Intermediate Components + +| ID | Name | Fields | Description | +|---|---|---|---| +| `residential_schedule_single_family` | Residential Schedule - Single Family | `EquipmentAMInterp`, `EquipmentBase`, `EquipmentLunchInterp`, `EquipmentPMInterp`, `EquipmentSummerPeakInterp`, `EquipmentWeekendPeakInterp`, `LightingAMInterp`, `LightingBase`, `LightingLunchInterp`, `LightingPMInterp`, `LightingSummerPeakInterp`, `LightingWeekendPeakInterp`, `OccupancyAMInterp`, `OccupancyBase`, `OccupancyLunchInterp`, `OccupancyPMInterp`, `OccupancySummerPeakInterp`, `OccupancyWeekendPeakInterp` | Typical MA single-family occupancy patterns with strong evening peaks and mod... | +| `residential_schedule_multifamily` | Residential Schedule - Multifamily | `EquipmentAMInterp`, `EquipmentBase`, `EquipmentLunchInterp`, `EquipmentPMInterp`, `EquipmentSummerPeakInterp`, `EquipmentWeekendPeakInterp`, `LightingAMInterp`, `LightingBase`, `LightingLunchInterp`, `LightingPMInterp`, `LightingSummerPeakInterp`, `LightingWeekendPeakInterp`, `OccupancyAMInterp`, `OccupancyBase`, `OccupancyLunchInterp`, `OccupancyPMInterp`, `OccupancySummerPeakInterp`, `OccupancyWeekendPeakInterp` | Multifamily schedules with slightly higher daytime occupancy. | +| `thermostat_constant` | Constant Setpoint Thermostat | `CoolingSetpointSetback`, `HeatingSetpointBase`, `HeatingSetpointSetback`, `NightSetback`, `SetpointDeadband`, `SummerSetback`, `WeekendSetback` | No smart thermostat; constant setpoints. | +| `thermostat_smart` | Smart Thermostat | `CoolingSetpointSetback`, `HeatingSetpointBase`, `HeatingSetpointSetback`, `NightSetback`, `SetpointDeadband`, `SummerSetback`, `WeekendSetback` | Smart thermostat with moderate setbacks. | +| `envelope_pre1940_base` | Pre-1940 Uninsulated Envelope | `FacadeCavityInsulationRValue`, `FacadeExteriorFinish`, `FacadeExteriorInsulationRValue`, `FacadeInteriorFinish`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorFinish`, `RoofExteriorInsulationRValue`, `RoofInteriorFinish`, `RoofInteriorInsulationRValue`, `RoofStructuralSystem`, `SlabExteriorFinish`, `SlabInsulationPlacement`, `SlabInsulationRValue`, `SlabInteriorFinish`, `SlabStructuralSystem` | Balloon-frame/masonry, high infiltration. | +| `envelope_1940_1970_base` | 1940-1970 Minimal Insulation | `FacadeCavityInsulationRValue`, `FacadeExteriorFinish`, `FacadeExteriorInsulationRValue`, `FacadeInteriorFinish`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorFinish`, `RoofExteriorInsulationRValue`, `RoofInteriorFinish`, `RoofInteriorInsulationRValue`, `RoofStructuralSystem`, `SlabExteriorFinish`, `SlabInsulationPlacement`, `SlabInsulationRValue`, `SlabInteriorFinish`, `SlabStructuralSystem` | Low cavity insulation, moderate infiltration. | +| `envelope_1970_2000_base` | 1970-2000 Moderate Insulation | `FacadeCavityInsulationRValue`, `FacadeExteriorFinish`, `FacadeExteriorInsulationRValue`, `FacadeInteriorFinish`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorFinish`, `RoofExteriorInsulationRValue`, `RoofInteriorFinish`, `RoofInteriorInsulationRValue`, `RoofStructuralSystem`, `SlabExteriorFinish`, `SlabInsulationPlacement`, `SlabInsulationRValue`, `SlabInteriorFinish`, `SlabStructuralSystem` | Improved insulation and air sealing. | +| `envelope_post2000_base` | Post-2000 Code Envelope | `FacadeCavityInsulationRValue`, `FacadeExteriorFinish`, `FacadeExteriorInsulationRValue`, `FacadeInteriorFinish`, `FacadeInteriorInsulationRValue`, `FacadeStructuralSystem`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `RoofExteriorFinish`, `RoofExteriorInsulationRValue`, `RoofInteriorFinish`, `RoofInteriorInsulationRValue`, `RoofStructuralSystem`, `SlabExteriorFinish`, `SlabInsulationPlacement`, `SlabInsulationRValue`, `SlabInteriorFinish`, `SlabStructuralSystem` | IECC-era construction. | +| `weatherization_upgrade` | Weatherization Upgrade | `FacadeCavityInsulationRValue`, `InfiltrationACH`, `RoofCavityInsulationRValue`, `SlabInsulationRValue` | WAP improvements. | +| `windows_pre2000` | Pre-2000 Windows | `WindowSHGF`, `WindowTVis`, `WindowUValue` | Older double-pane. | +| `windows_post2000` | Post-2000 Windows | `WindowSHGF`, `WindowTVis`, `WindowUValue` | Low-e double-pane. | +| `hvac_gas_furnace` | Gas Furnace + AC | `CoolingDistributionCOP`, `CoolingFuel`, `CoolingSystemCOP`, `HeatingDistributionCOP`, `HeatingFuel`, `HeatingSystemCOP` | Typical MA gas system. | +| `hvac_oil_boiler` | Oil Boiler | `CoolingDistributionCOP`, `CoolingFuel`, `CoolingSystemCOP`, `HeatingDistributionCOP`, `HeatingFuel`, `HeatingSystemCOP` | Oil heat, limited AC. | +| `hvac_heat_pump` | Cold Climate Heat Pump | `CoolingDistributionCOP`, `CoolingFuel`, `CoolingSystemCOP`, `HeatingDistributionCOP`, `HeatingFuel`, `HeatingSystemCOP` | Modern heat pump. | +| `dhw_gas` | Gas DHW | `DHWDistributionCOP`, `DHWFuel`, `DHWSystemCOP` | Gas storage water heater. | +| `dhw_oil` | Oil DHW | `DHWDistributionCOP`, `DHWFuel`, `DHWSystemCOP` | Oil water heater. | +| `dhw_electric` | Electric DHW | `DHWDistributionCOP`, `DHWFuel`, `DHWSystemCOP` | Electric resistance water heater. | + +### Component Details + +#### Residential Schedule - Single Family (`residential_schedule_single_family`) + +Typical MA single-family occupancy patterns with strong evening peaks and moderate weekend activity. + +- `EquipmentBase` = `0.3` +- `EquipmentAMInterp` = `0.6` +- `EquipmentLunchInterp` = `0.5` +- `EquipmentPMInterp` = `0.9` +- `EquipmentWeekendPeakInterp` = `0.8` +- `EquipmentSummerPeakInterp` = `0.95` +- `LightingBase` = `0.2` +- `LightingAMInterp` = `0.5` +- `LightingLunchInterp` = `0.4` +- `LightingPMInterp` = `0.95` +- `LightingWeekendPeakInterp` = `0.85` +- `LightingSummerPeakInterp` = `0.9` +- `OccupancyBase` = `0.8` +- `OccupancyAMInterp` = `0.6` +- `OccupancyLunchInterp` = `0.7` +- `OccupancyPMInterp` = `0.95` +- `OccupancyWeekendPeakInterp` = `0.95` +- `OccupancySummerPeakInterp` = `1.0` + +#### Residential Schedule - Multifamily (`residential_schedule_multifamily`) + +Multifamily schedules with slightly higher daytime occupancy. + +- `EquipmentBase` = `0.35` +- `EquipmentAMInterp` = `0.6` +- `EquipmentLunchInterp` = `0.55` +- `EquipmentPMInterp` = `0.9` +- `EquipmentWeekendPeakInterp` = `0.85` +- `EquipmentSummerPeakInterp` = `0.95` +- `LightingBase` = `0.25` +- `LightingAMInterp` = `0.5` +- `LightingLunchInterp` = `0.45` +- `LightingPMInterp` = `0.95` +- `LightingWeekendPeakInterp` = `0.9` +- `LightingSummerPeakInterp` = `0.9` +- `OccupancyBase` = `0.85` +- `OccupancyAMInterp` = `0.65` +- `OccupancyLunchInterp` = `0.75` +- `OccupancyPMInterp` = `0.95` +- `OccupancyWeekendPeakInterp` = `0.98` +- `OccupancySummerPeakInterp` = `1.0` + +#### Constant Setpoint Thermostat (`thermostat_constant`) + +No smart thermostat; constant setpoints. + +- `HeatingSetpointBase` = `21.0` +- `SetpointDeadband` = `3.0` +- `HeatingSetpointSetback` = `0.0` +- `CoolingSetpointSetback` = `0.0` +- `NightSetback` = `0.0` +- `WeekendSetback` = `0.0` +- `SummerSetback` = `0.0` + +#### Smart Thermostat (`thermostat_smart`) + +Smart thermostat with moderate setbacks. + +- `HeatingSetpointBase` = `21.0` +- `SetpointDeadband` = `3.0` +- `HeatingSetpointSetback` = `3.0` +- `CoolingSetpointSetback` = `2.0` +- `NightSetback` = `0.8` +- `WeekendSetback` = `0.9` +- `SummerSetback` = `0.9` + +#### Pre-1940 Uninsulated Envelope (`envelope_pre1940_base`) + +Balloon-frame/masonry, high infiltration. + +- `FacadeStructuralSystem` = `woodframe` +- `FacadeCavityInsulationRValue` = `0.5` +- `FacadeExteriorInsulationRValue` = `0.0` +- `FacadeInteriorInsulationRValue` = `0.0` +- `FacadeInteriorFinish` = `plaster` +- `FacadeExteriorFinish` = `wood_siding` +- `RoofStructuralSystem` = `light_wood_truss` +- `RoofCavityInsulationRValue` = `2.0` +- `RoofExteriorInsulationRValue` = `0.0` +- `RoofInteriorInsulationRValue` = `0.0` +- `RoofInteriorFinish` = `gypsum_board` +- `RoofExteriorFinish` = `asphalt_shingle` +- `SlabStructuralSystem` = `slab_on_grade` +- `SlabInsulationRValue` = `0.5` +- `SlabInsulationPlacement` = `under_slab` +- `SlabInteriorFinish` = `wood_floor` +- `SlabExteriorFinish` = `none` +- `InfiltrationACH` = `1.0` + +#### 1940-1970 Minimal Insulation (`envelope_1940_1970_base`) + +Low cavity insulation, moderate infiltration. + +- `FacadeStructuralSystem` = `woodframe` +- `FacadeCavityInsulationRValue` = `1.8` +- `FacadeExteriorInsulationRValue` = `0.0` +- `FacadeInteriorInsulationRValue` = `0.0` +- `FacadeInteriorFinish` = `drywall` +- `FacadeExteriorFinish` = `vinyl_siding` +- `RoofStructuralSystem` = `light_wood_truss` +- `RoofCavityInsulationRValue` = `3.5` +- `RoofExteriorInsulationRValue` = `0.0` +- `RoofInteriorInsulationRValue` = `0.0` +- `RoofInteriorFinish` = `gypsum_board` +- `RoofExteriorFinish` = `asphalt_shingle` +- `SlabStructuralSystem` = `slab_on_grade` +- `SlabInsulationRValue` = `1.0` +- `SlabInsulationPlacement` = `under_slab` +- `SlabInteriorFinish` = `wood_floor` +- `SlabExteriorFinish` = `none` +- `InfiltrationACH` = `0.65` + +#### 1970-2000 Moderate Insulation (`envelope_1970_2000_base`) + +Improved insulation and air sealing. + +- `FacadeStructuralSystem` = `woodframe` +- `FacadeCavityInsulationRValue` = `3.0` +- `FacadeExteriorInsulationRValue` = `0.5` +- `FacadeInteriorInsulationRValue` = `0.0` +- `FacadeInteriorFinish` = `drywall` +- `FacadeExteriorFinish` = `vinyl_siding` +- `RoofStructuralSystem` = `light_wood_truss` +- `RoofCavityInsulationRValue` = `5.0` +- `RoofExteriorInsulationRValue` = `0.0` +- `RoofInteriorInsulationRValue` = `0.0` +- `RoofInteriorFinish` = `gypsum_board` +- `RoofExteriorFinish` = `asphalt_shingle` +- `SlabStructuralSystem` = `slab_on_grade` +- `SlabInsulationRValue` = `1.5` +- `SlabInsulationPlacement` = `under_slab` +- `SlabInteriorFinish` = `wood_floor` +- `SlabExteriorFinish` = `none` +- `InfiltrationACH` = `0.45` + +#### Post-2000 Code Envelope (`envelope_post2000_base`) + +IECC-era construction. + +- `FacadeStructuralSystem` = `woodframe` +- `FacadeCavityInsulationRValue` = `3.5` +- `FacadeExteriorInsulationRValue` = `1.0` +- `FacadeInteriorInsulationRValue` = `0.0` +- `FacadeInteriorFinish` = `drywall` +- `FacadeExteriorFinish` = `vinyl_siding` +- `RoofStructuralSystem` = `light_wood_truss` +- `RoofCavityInsulationRValue` = `8.0` +- `RoofExteriorInsulationRValue` = `0.5` +- `RoofInteriorInsulationRValue` = `0.0` +- `RoofInteriorFinish` = `gypsum_board` +- `RoofExteriorFinish` = `asphalt_shingle` +- `SlabStructuralSystem` = `slab_on_grade` +- `SlabInsulationRValue` = `2.0` +- `SlabInsulationPlacement` = `under_slab` +- `SlabInteriorFinish` = `wood_floor` +- `SlabExteriorFinish` = `none` +- `InfiltrationACH` = `0.25` + +#### Weatherization Upgrade (`weatherization_upgrade`) + +WAP improvements. + +- `FacadeCavityInsulationRValue` = `4.0` +- `RoofCavityInsulationRValue` = `10.0` +- `SlabInsulationRValue` = `2.0` +- `InfiltrationACH` = `0.5` + +#### Pre-2000 Windows (`windows_pre2000`) + +Older double-pane. + +- `WindowUValue` = `2.8` +- `WindowSHGF` = `0.6` +- `WindowTVis` = `0.6` + +#### Post-2000 Windows (`windows_post2000`) + +Low-e double-pane. + +- `WindowUValue` = `1.9` +- `WindowSHGF` = `0.4` +- `WindowTVis` = `0.55` + +#### Gas Furnace + AC (`hvac_gas_furnace`) + +Typical MA gas system. + +- `HeatingFuel` = `NaturalGas` +- `CoolingFuel` = `Electricity` +- `HeatingSystemCOP` = `0.85` +- `CoolingSystemCOP` = `3.0` +- `HeatingDistributionCOP` = `0.85` +- `CoolingDistributionCOP` = `0.9` + +#### Oil Boiler (`hvac_oil_boiler`) + +Oil heat, limited AC. + +- `HeatingFuel` = `FuelOil` +- `CoolingFuel` = `Electricity` +- `HeatingSystemCOP` = `0.82` +- `CoolingSystemCOP` = `2.5` +- `HeatingDistributionCOP` = `0.8` +- `CoolingDistributionCOP` = `0.8` + +#### Cold Climate Heat Pump (`hvac_heat_pump`) + +Modern heat pump. + +- `HeatingFuel` = `Electricity` +- `CoolingFuel` = `Electricity` +- `HeatingSystemCOP` = `3.0` +- `CoolingSystemCOP` = `3.5` +- `HeatingDistributionCOP` = `0.95` +- `CoolingDistributionCOP` = `0.95` + +#### Gas DHW (`dhw_gas`) + +Gas storage water heater. + +- `DHWFuel` = `NaturalGas` +- `DHWSystemCOP` = `0.65` +- `DHWDistributionCOP` = `0.8` + +#### Oil DHW (`dhw_oil`) + +Oil water heater. + +- `DHWFuel` = `FuelOil` +- `DHWSystemCOP` = `0.6` +- `DHWDistributionCOP` = `0.75` + +#### Electric DHW (`dhw_electric`) + +Electric resistance water heater. + +- `DHWFuel` = `Electricity` +- `DHWSystemCOP` = `0.95` +- `DHWDistributionCOP` = `0.9` + +## Parameter Coverage + +- **Equipment Schedule**: 6/6 (FULL) +- **Lighting Schedule**: 6/6 (FULL) +- **Occupancy Schedule**: 6/6 (FULL) +- **Thermostat Setpoints**: 7/7 (FULL) +- **HVAC Systems**: 6/6 (FULL) +- **Space Use**: 3/3 (FULL) +- **Ventilation**: 6/6 (FULL) +- **Domestic Hot Water**: 4/4 (FULL) +- **Envelope**: 1/1 (FULL) +- **Windows**: 3/3 (FULL) +- **Facade Construction**: 6/6 (FULL) +- **Roof Construction**: 6/6 (FULL) +- **Slab Construction**: 5/5 (FULL) +- **Geometry**: 0/6 (NONE) +- **Weather**: 0/1 (NONE) + +## Validation + +All structural validation checks passed. + +## User Fields + +- **income** (numeric): Annual household income in USD. Correlates loosely with ability to invest in energy upgrades. + - Data quality: Self-reported on utility assistance applications. About 30% of rows are missing. +- **year_built** (numeric): Year the building was originally constructed. + - Data quality: From assessor records; generally reliable, though some entries are approximate decades (e.g. 1900 for anything pre-1910). +- **building_typology** (categorical): Building typology classification from assessor data. + - Data quality: Assessor-derived, reliable. +- **weatherization_status** (categorical): Whether the building has been through a weatherization assistance program. + - Data quality: From state WAP records. Only captures state-funded programs; private weatherization is not tracked. About 60% of rows are missing (unknown status). +- **last_renovation** (categorical): Approximate timeframe of last known major renovation or retrofit. + - Data quality: From permit records where available. Very sparse -- roughly 70% missing. +- **has_smart_thermostat** (categorical): Whether the building has a smart thermostat. + - Data quality: We conducted a survey of all of the buildings and know precisely if it has a smart thermostat. diff --git a/tests/test_decision_dag/working_user_field_set.yaml b/tests/test_decision_dag/working_user_field_set.yaml new file mode 100644 index 0000000..66559df --- /dev/null +++ b/tests/test_decision_dag/working_user_field_set.yaml @@ -0,0 +1,110 @@ +fields: +- name: income + field_type: numeric + description: Annual household income in USD. Correlates loosely with ability to + invest in energy upgrades. + data_quality_description: Self-reported on utility assistance applications. About + 30% of rows are missing. + categories: null + min_value: 0.0 + max_value: 500000.0 + unit: USD/year +- name: year_built + field_type: numeric + description: Year the building was originally constructed. + data_quality_description: From assessor records; generally reliable, though some + entries are approximate decades (e.g. 1900 for anything pre-1910). + categories: null + min_value: 1700.0 + max_value: 2025.0 + unit: year +- name: building_typology + field_type: categorical + description: Building typology classification from assessor data. + data_quality_description: Assessor-derived, reliable. + categories: + - single_family_detached + - single_family_attached + - small_multifamily_2_4 + - medium_multifamily_5_20 + - large_multifamily_20_plus + min_value: null + max_value: null + unit: null +- name: weatherization_status + field_type: categorical + description: Whether the building has been through a weatherization assistance program. + data_quality_description: From state WAP records. Only captures state-funded programs; + private weatherization is not tracked. About 60% of rows are missing (unknown + status). + categories: + - weatherized + - not_weatherized + - unknown + min_value: null + max_value: null + unit: null +- name: last_renovation + field_type: categorical + description: Approximate timeframe of last known major renovation or retrofit. + data_quality_description: From permit records where available. Very sparse -- roughly + 70% missing. + categories: + - never + - before_1980 + - '1980_2000' + - '2000_2010' + - 2010_present + min_value: null + max_value: null + unit: null +- name: has_smart_thermostat + field_type: categorical + description: Whether the building has a smart thermostat. + data_quality_description: We conducted a survey of all of the buildings and know precisely if it has a smart thermostat. + categories: + - 'yes' + - 'no' + min_value: null + max_value: null + unit: null +context_description: We are building energy models for a portfolio of ~5,000 residential + buildings in Massachusetts for a utility-funded energy efficiency program. The goal + is to estimate building energy use and identify retrofit opportunities. Data is + sparse and of mixed quality. + +region_description: Massachusetts, USA. IECC Climate Zone 5A. Cold winters, warm humid + summers. Heating-dominated climate with ~5,500 HDD65 and ~700 CDD65. State energy + code is based on IECC 2021 for new construction. + +building_stock_description: Predominantly older housing stock. Roughly 60% of buildings + were built before 1960. Mix of wood-frame (most common for single-family), triple-decker + multi-family (very common in urban MA), and some masonry construction in older urban + cores. Natural gas heating dominates (~65%), followed by oil (~20%), and electric/heat + pump (~15%). Many older buildings have minimal insulation, especially in walls. + +supplementary_context: +- title: Typical Wall Construction by Era + content: 'Pre-1940: Double-wythe brick or balloon-frame wood with no insulation, + plaster interior. Infiltration is very high (often 1.0+ ACH). + + 1940-1970: Platform-frame wood, often with minimal batt insulation (R-7 to R-11 + cavities), some with aluminum siding over original clapboard. Infiltration moderate + (0.5-0.8 ACH). + + 1970-2000: Wood frame with R-11 to R-19 cavity insulation, vinyl or wood siding, + some continuous insulation in later builds. Infiltration moderate (0.3-0.6 ACH). + + Post-2000: Wood frame with R-19+ cavity, often R-5 to R-10 continuous exterior + insulation, air sealing. Infiltration low (0.15-0.35 ACH).' + format_hint: plaintext +- title: Thermostat Schedules + content: 'When a building has a smart thermostat, use the setback parameters to implement heating and cooling setpoint setbacks in order to save energy, similar to how a NEST thermostat might do so. If a building does not have a smart thermostat, use a constant setpoint year round for both heating and cooling.' + format_hint: plaintext +- title: Massachusetts Weatherization Program Notes + content: 'The MA WAP program typically performs: air sealing (blower-door guided), + attic insulation to R-38 minimum, wall insulation (dense-pack cellulose) where + feasible, and sometimes basement/crawlspace insulation. Weatherized homes see + roughly a 20-30% reduction in infiltration and improved wall/attic R-values compared + to un-weatherized homes of the same era.' + format_hint: plaintext diff --git a/uv.lock b/uv.lock index 026a4c4..c3e0662 100644 --- a/uv.lock +++ b/uv.lock @@ -7,6 +7,130 @@ resolution-markers = [ "python_full_version < '3.11'", ] +[[package]] +name = "ag-ui-protocol" +version = "0.1.13" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/b5/fc0b65b561d00d88811c8a7d98ee735833f81554be244340950e7b65820c/ag_ui_protocol-0.1.13.tar.gz", hash = "sha256:811d7d7dcce4783dec252918f40b717ebfa559399bf6b071c4ba47c0c1e21bcb", size = 5671, upload-time = "2026-02-19T18:40:38.602Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/9f/b833c1ab1999da35ebad54841ae85d2c2764c931da9a6f52d8541b6901b2/ag_ui_protocol-0.1.13-py3-none-any.whl", hash = "sha256:1393fa894c1e8416efe184168a50689e760d05b32f4646eebb8ff423dddf8e8f", size = 8053, upload-time = "2026-02-19T18:40:37.27Z" }, +] + +[[package]] +name = "aiofile" +version = "3.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "caio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/67/e2/d7cb819de8df6b5c1968a2756c3cb4122d4fa2b8fc768b53b7c9e5edb646/aiofile-3.9.0.tar.gz", hash = "sha256:e5ad718bb148b265b6df1b3752c4d1d83024b93da9bd599df74b9d9ffcf7919b", size = 17943, upload-time = "2024-10-08T10:39:35.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/25/da1f0b4dd970e52bf5a36c204c107e11a0c6d3ed195eba0bfbc664c312b2/aiofile-3.9.0-py3-none-any.whl", hash = "sha256:ce2f6c1571538cbdfa0143b04e16b208ecb0e9cb4148e528af8a640ed51cc8aa", size = 19539, upload-time = "2024-10-08T10:39:32.955Z" }, +] + +[[package]] +name = "aiohappyeyeballs" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.13.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "async-timeout", marker = "python_full_version < '3.11'" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/d6/5aec9313ee6ea9c7cde8b891b69f4ff4001416867104580670a31daeba5b/aiohttp-3.13.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7", size = 738950, upload-time = "2026-01-03T17:29:13.002Z" }, + { url = "https://files.pythonhosted.org/packages/68/03/8fa90a7e6d11ff20a18837a8e2b5dd23db01aabc475aa9271c8ad33299f5/aiohttp-3.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821", size = 496099, upload-time = "2026-01-03T17:29:15.268Z" }, + { url = "https://files.pythonhosted.org/packages/d2/23/b81f744d402510a8366b74eb420fc0cc1170d0c43daca12d10814df85f10/aiohttp-3.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845", size = 491072, upload-time = "2026-01-03T17:29:16.922Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e1/56d1d1c0dd334cd203dd97706ce004c1aa24b34a813b0b8daf3383039706/aiohttp-3.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af", size = 1671588, upload-time = "2026-01-03T17:29:18.539Z" }, + { url = "https://files.pythonhosted.org/packages/5f/34/8d7f962604f4bc2b4e39eb1220dac7d4e4cba91fb9ba0474b4ecd67db165/aiohttp-3.13.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940", size = 1640334, upload-time = "2026-01-03T17:29:21.028Z" }, + { url = "https://files.pythonhosted.org/packages/94/1d/fcccf2c668d87337ddeef9881537baee13c58d8f01f12ba8a24215f2b804/aiohttp-3.13.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160", size = 1722656, upload-time = "2026-01-03T17:29:22.531Z" }, + { url = "https://files.pythonhosted.org/packages/aa/98/c6f3b081c4c606bc1e5f2ec102e87d6411c73a9ef3616fea6f2d5c98c062/aiohttp-3.13.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7", size = 1817625, upload-time = "2026-01-03T17:29:24.276Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c0/cfcc3d2e11b477f86e1af2863f3858c8850d751ce8dc39c4058a072c9e54/aiohttp-3.13.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455", size = 1672604, upload-time = "2026-01-03T17:29:26.099Z" }, + { url = "https://files.pythonhosted.org/packages/1e/77/6b4ffcbcac4c6a5d041343a756f34a6dd26174ae07f977a64fe028dda5b0/aiohttp-3.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279", size = 1554370, upload-time = "2026-01-03T17:29:28.121Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f0/e3ddfa93f17d689dbe014ba048f18e0c9f9b456033b70e94349a2e9048be/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e", size = 1642023, upload-time = "2026-01-03T17:29:30.002Z" }, + { url = "https://files.pythonhosted.org/packages/eb/45/c14019c9ec60a8e243d06d601b33dcc4fd92379424bde3021725859d7f99/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d", size = 1649680, upload-time = "2026-01-03T17:29:31.782Z" }, + { url = "https://files.pythonhosted.org/packages/9c/fd/09c9451dae5aa5c5ed756df95ff9ef549d45d4be663bafd1e4954fd836f0/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808", size = 1692407, upload-time = "2026-01-03T17:29:33.392Z" }, + { url = "https://files.pythonhosted.org/packages/a6/81/938bc2ec33c10efd6637ccb3d22f9f3160d08e8f3aa2587a2c2d5ab578eb/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40", size = 1543047, upload-time = "2026-01-03T17:29:34.855Z" }, + { url = "https://files.pythonhosted.org/packages/f7/23/80488ee21c8d567c83045e412e1d9b7077d27171591a4eb7822586e8c06a/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29", size = 1715264, upload-time = "2026-01-03T17:29:36.389Z" }, + { url = "https://files.pythonhosted.org/packages/e2/83/259a8da6683182768200b368120ab3deff5370bed93880fb9a3a86299f34/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11", size = 1657275, upload-time = "2026-01-03T17:29:38.162Z" }, + { url = "https://files.pythonhosted.org/packages/3f/4f/2c41f800a0b560785c10fb316216ac058c105f9be50bdc6a285de88db625/aiohttp-3.13.3-cp310-cp310-win32.whl", hash = "sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd", size = 434053, upload-time = "2026-01-03T17:29:40.074Z" }, + { url = "https://files.pythonhosted.org/packages/80/df/29cd63c7ecfdb65ccc12f7d808cac4fa2a19544660c06c61a4a48462de0c/aiohttp-3.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c", size = 456687, upload-time = "2026-01-03T17:29:41.819Z" }, + { url = "https://files.pythonhosted.org/packages/f1/4c/a164164834f03924d9a29dc3acd9e7ee58f95857e0b467f6d04298594ebb/aiohttp-3.13.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b", size = 746051, upload-time = "2026-01-03T17:29:43.287Z" }, + { url = "https://files.pythonhosted.org/packages/82/71/d5c31390d18d4f58115037c432b7e0348c60f6f53b727cad33172144a112/aiohttp-3.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64", size = 499234, upload-time = "2026-01-03T17:29:44.822Z" }, + { url = "https://files.pythonhosted.org/packages/0e/c9/741f8ac91e14b1d2e7100690425a5b2b919a87a5075406582991fb7de920/aiohttp-3.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea", size = 494979, upload-time = "2026-01-03T17:29:46.405Z" }, + { url = "https://files.pythonhosted.org/packages/75/b5/31d4d2e802dfd59f74ed47eba48869c1c21552c586d5e81a9d0d5c2ad640/aiohttp-3.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a", size = 1748297, upload-time = "2026-01-03T17:29:48.083Z" }, + { url = "https://files.pythonhosted.org/packages/1a/3e/eefad0ad42959f226bb79664826883f2687d602a9ae2941a18e0484a74d3/aiohttp-3.13.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540", size = 1707172, upload-time = "2026-01-03T17:29:49.648Z" }, + { url = "https://files.pythonhosted.org/packages/c5/3a/54a64299fac2891c346cdcf2aa6803f994a2e4beeaf2e5a09dcc54acc842/aiohttp-3.13.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b", size = 1805405, upload-time = "2026-01-03T17:29:51.244Z" }, + { url = "https://files.pythonhosted.org/packages/6c/70/ddc1b7169cf64075e864f64595a14b147a895a868394a48f6a8031979038/aiohttp-3.13.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3", size = 1899449, upload-time = "2026-01-03T17:29:53.938Z" }, + { url = "https://files.pythonhosted.org/packages/a1/7e/6815aab7d3a56610891c76ef79095677b8b5be6646aaf00f69b221765021/aiohttp-3.13.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1", size = 1748444, upload-time = "2026-01-03T17:29:55.484Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f2/073b145c4100da5511f457dc0f7558e99b2987cf72600d42b559db856fbc/aiohttp-3.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3", size = 1606038, upload-time = "2026-01-03T17:29:57.179Z" }, + { url = "https://files.pythonhosted.org/packages/0a/c1/778d011920cae03ae01424ec202c513dc69243cf2db303965615b81deeea/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440", size = 1724156, upload-time = "2026-01-03T17:29:58.914Z" }, + { url = "https://files.pythonhosted.org/packages/0e/cb/3419eabf4ec1e9ec6f242c32b689248365a1cf621891f6f0386632525494/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7", size = 1722340, upload-time = "2026-01-03T17:30:01.962Z" }, + { url = "https://files.pythonhosted.org/packages/7a/e5/76cf77bdbc435bf233c1f114edad39ed4177ccbfab7c329482b179cff4f4/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c", size = 1783041, upload-time = "2026-01-03T17:30:03.609Z" }, + { url = "https://files.pythonhosted.org/packages/9d/d4/dd1ca234c794fd29c057ce8c0566b8ef7fd6a51069de5f06fa84b9a1971c/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51", size = 1596024, upload-time = "2026-01-03T17:30:05.132Z" }, + { url = "https://files.pythonhosted.org/packages/55/58/4345b5f26661a6180afa686c473620c30a66afdf120ed3dd545bbc809e85/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4", size = 1804590, upload-time = "2026-01-03T17:30:07.135Z" }, + { url = "https://files.pythonhosted.org/packages/7b/06/05950619af6c2df7e0a431d889ba2813c9f0129cec76f663e547a5ad56f2/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29", size = 1740355, upload-time = "2026-01-03T17:30:09.083Z" }, + { url = "https://files.pythonhosted.org/packages/3e/80/958f16de79ba0422d7c1e284b2abd0c84bc03394fbe631d0a39ffa10e1eb/aiohttp-3.13.3-cp311-cp311-win32.whl", hash = "sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239", size = 433701, upload-time = "2026-01-03T17:30:10.869Z" }, + { url = "https://files.pythonhosted.org/packages/dc/f2/27cdf04c9851712d6c1b99df6821a6623c3c9e55956d4b1e318c337b5a48/aiohttp-3.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f", size = 457678, upload-time = "2026-01-03T17:30:12.719Z" }, + { url = "https://files.pythonhosted.org/packages/a0/be/4fc11f202955a69e0db803a12a062b8379c970c7c84f4882b6da17337cc1/aiohttp-3.13.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c", size = 739732, upload-time = "2026-01-03T17:30:14.23Z" }, + { url = "https://files.pythonhosted.org/packages/97/2c/621d5b851f94fa0bb7430d6089b3aa970a9d9b75196bc93bb624b0db237a/aiohttp-3.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168", size = 494293, upload-time = "2026-01-03T17:30:15.96Z" }, + { url = "https://files.pythonhosted.org/packages/5d/43/4be01406b78e1be8320bb8316dc9c42dbab553d281c40364e0f862d5661c/aiohttp-3.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d", size = 493533, upload-time = "2026-01-03T17:30:17.431Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a8/5a35dc56a06a2c90d4742cbf35294396907027f80eea696637945a106f25/aiohttp-3.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29", size = 1737839, upload-time = "2026-01-03T17:30:19.422Z" }, + { url = "https://files.pythonhosted.org/packages/bf/62/4b9eeb331da56530bf2e198a297e5303e1c1ebdceeb00fe9b568a65c5a0c/aiohttp-3.13.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3", size = 1703932, upload-time = "2026-01-03T17:30:21.756Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f6/af16887b5d419e6a367095994c0b1332d154f647e7dc2bd50e61876e8e3d/aiohttp-3.13.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d", size = 1771906, upload-time = "2026-01-03T17:30:23.932Z" }, + { url = "https://files.pythonhosted.org/packages/ce/83/397c634b1bcc24292fa1e0c7822800f9f6569e32934bdeef09dae7992dfb/aiohttp-3.13.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463", size = 1871020, upload-time = "2026-01-03T17:30:26Z" }, + { url = "https://files.pythonhosted.org/packages/86/f6/a62cbbf13f0ac80a70f71b1672feba90fdb21fd7abd8dbf25c0105fb6fa3/aiohttp-3.13.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc", size = 1755181, upload-time = "2026-01-03T17:30:27.554Z" }, + { url = "https://files.pythonhosted.org/packages/0a/87/20a35ad487efdd3fba93d5843efdfaa62d2f1479eaafa7453398a44faf13/aiohttp-3.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf", size = 1561794, upload-time = "2026-01-03T17:30:29.254Z" }, + { url = "https://files.pythonhosted.org/packages/de/95/8fd69a66682012f6716e1bc09ef8a1a2a91922c5725cb904689f112309c4/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033", size = 1697900, upload-time = "2026-01-03T17:30:31.033Z" }, + { url = "https://files.pythonhosted.org/packages/e5/66/7b94b3b5ba70e955ff597672dad1691333080e37f50280178967aff68657/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f", size = 1728239, upload-time = "2026-01-03T17:30:32.703Z" }, + { url = "https://files.pythonhosted.org/packages/47/71/6f72f77f9f7d74719692ab65a2a0252584bf8d5f301e2ecb4c0da734530a/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679", size = 1740527, upload-time = "2026-01-03T17:30:34.695Z" }, + { url = "https://files.pythonhosted.org/packages/fa/b4/75ec16cbbd5c01bdaf4a05b19e103e78d7ce1ef7c80867eb0ace42ff4488/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423", size = 1554489, upload-time = "2026-01-03T17:30:36.864Z" }, + { url = "https://files.pythonhosted.org/packages/52/8f/bc518c0eea29f8406dcf7ed1f96c9b48e3bc3995a96159b3fc11f9e08321/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce", size = 1767852, upload-time = "2026-01-03T17:30:39.433Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f2/a07a75173124f31f11ea6f863dc44e6f09afe2bca45dd4e64979490deab1/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a", size = 1722379, upload-time = "2026-01-03T17:30:41.081Z" }, + { url = "https://files.pythonhosted.org/packages/3c/4a/1a3fee7c21350cac78e5c5cef711bac1b94feca07399f3d406972e2d8fcd/aiohttp-3.13.3-cp312-cp312-win32.whl", hash = "sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046", size = 428253, upload-time = "2026-01-03T17:30:42.644Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b7/76175c7cb4eb73d91ad63c34e29fc4f77c9386bba4a65b53ba8e05ee3c39/aiohttp-3.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57", size = 455407, upload-time = "2026-01-03T17:30:44.195Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + +[[package]] +name = "annotated-doc" +version = "0.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, +] + [[package]] name = "annotated-types" version = "0.7.0" @@ -16,6 +140,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] +[[package]] +name = "anthropic" +version = "0.83.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "docstring-parser" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/db/e5/02cd2919ec327b24234abb73082e6ab84c451182cc3cc60681af700f4c63/anthropic-0.83.0.tar.gz", hash = "sha256:a8732c68b41869266c3034541a31a29d8be0f8cd0a714f9edce3128b351eceb4", size = 534058, upload-time = "2026-02-19T19:26:38.904Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/75/b9d58e4e2a4b1fc3e75ffbab978f999baf8b7c4ba9f96e60edb918ba386b/anthropic-0.83.0-py3-none-any.whl", hash = "sha256:f069ef508c73b8f9152e8850830d92bd5ef185645dbacf234bb213344a274810", size = 456991, upload-time = "2026-02-19T19:26:40.114Z" }, +] + [[package]] name = "anyio" version = "4.9.0" @@ -43,7 +186,7 @@ wheels = [ [[package]] name = "archetypal" version = "2.18.10" -source = { registry = "https://pypi.org/simple" } +source = { directory = "archetypal" } dependencies = [ { name = "click" }, { name = "coolprop" }, @@ -70,9 +213,43 @@ dependencies = [ { name = "transforms3d" }, { name = "validator-collection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3b/e6/4f52882c31c26d6ca95acd71cf88f8e3d044fe6ed99058dc6e909e16accf/archetypal-2.18.10.tar.gz", hash = "sha256:fca2698762c36a2ed02faa00a33ad55da66ab01cc1b7ed8c3d86a12a82082c8a", size = 237848, upload-time = "2026-02-10T18:21:30.974Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/c3/76577d22f946ee26c5b530a21274e36bad1afb2c2048b39353d690058d44/archetypal-2.18.10-py3-none-any.whl", hash = "sha256:43e2d66d0a6b4d617a76dd074b6825f7ebc3a97a89ba4b0adfbdeb4736e9d407", size = 289062, upload-time = "2026-02-10T18:21:32.13Z" }, + +[package.metadata] +requires-dist = [ + { name = "click", specifier = ">=8.1.7,<9.0.0" }, + { name = "coolprop", specifier = ">=6.6.0,<7.0.0" }, + { name = "energy-pandas", specifier = ">=0.4.1,<0.5.0" }, + { name = "eppy", specifier = ">=0.5.63,<0.6.0" }, + { name = "esoreader", specifier = ">=1.2.3,<2.0.0" }, + { name = "matplotlib", specifier = ">=3.4,<4.0" }, + { name = "networkx", specifier = "<3" }, + { name = "numpy", marker = "python_full_version <= '3.9'", specifier = ">=2.0.2,<3.0.0" }, + { name = "numpy", marker = "python_full_version == '3.10.*'", specifier = ">=2.1.1,<3.0.0" }, + { name = "packaging", specifier = ">=24.1" }, + { name = "pandas", specifier = ">=2.0.3" }, + { name = "path", specifier = ">=17.1.0" }, + { name = "pyclipper", specifier = ">=1.3.0.post5,<2.0.0" }, + { name = "pycountry", specifier = ">=24.6.1,<25.0.0" }, + { name = "pydantic-settings", specifier = ">=2.3.2,<3.0.0" }, + { name = "pypoly2tri", specifier = ">=0.0.3,<0.0.4" }, + { name = "requests", specifier = ">=2.32.3,<3.0.0" }, + { name = "scikit-learn", specifier = ">=1.5.0,<2.0.0" }, + { name = "shapely", specifier = ">=2.0.6,<3.0.0" }, + { name = "sigfig", specifier = ">=1.3.3,<2.0.0" }, + { name = "six", specifier = ">=1.16.0,<2.0.0" }, + { name = "tomli", specifier = ">=2.0.1,<3.0.0" }, + { name = "tqdm", specifier = ">=4.66.4,<5.0.0" }, + { name = "transforms3d", specifier = ">=0.4.1,<0.5.0" }, + { name = "validator-collection", specifier = ">=1.5.0,<2.0.0" }, +] + +[[package]] +name = "argcomplete" +version = "3.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/38/61/0b9ae6399dd4a58d8c1b1dc5a27d6f2808023d0b5dd3104bb99f45a33ff6/argcomplete-3.6.3.tar.gz", hash = "sha256:62e8ed4fd6a45864acc8235409461b72c9a28ee785a2011cc5eb78318786c89c", size = 73754, upload-time = "2025-10-20T03:33:34.741Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/f5/9373290775639cb67a2fce7f629a1c240dce9f12fe927bc32b2736e16dfc/argcomplete-3.6.3-py3-none-any.whl", hash = "sha256:f5007b3a600ccac5d25bbce33089211dfd49eab4a7718da3f10e3082525a92ce", size = 43846, upload-time = "2025-10-20T03:33:33.021Z" }, ] [[package]] @@ -142,6 +319,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/03/49/d10027df9fce941cb8184e78a02857af36360d33e1721df81c5ed2179a1a/async_lru-2.0.5-py3-none-any.whl", hash = "sha256:ab95404d8d2605310d345932697371a5f40def0487c03d6d0ad9138de52c9943", size = 6069, upload-time = "2025-03-16T17:25:35.422Z" }, ] +[[package]] +name = "async-timeout" +version = "5.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3", size = 9274, upload-time = "2024-11-06T16:41:39.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c", size = 6233, upload-time = "2024-11-06T16:41:37.9Z" }, +] + [[package]] name = "attrs" version = "25.3.0" @@ -151,6 +337,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, ] +[[package]] +name = "authlib" +version = "1.6.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6b/6c/c88eac87468c607f88bc24df1f3b31445ee6fc9ba123b09e666adf687cd9/authlib-1.6.8.tar.gz", hash = "sha256:41ae180a17cf672bc784e4a518e5c82687f1fe1e98b0cafaeda80c8e4ab2d1cb", size = 165074, upload-time = "2026-02-14T04:02:17.941Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/73/f7084bf12755113cd535ae586782ff3a6e710bfbe6a0d13d1c2f81ffbbfa/authlib-1.6.8-py2.py3-none-any.whl", hash = "sha256:97286fd7a15e6cfefc32771c8ef9c54f0ed58028f1322de6a2a7c969c3817888", size = 244116, upload-time = "2026-02-14T04:02:15.579Z" }, +] + [[package]] name = "babel" version = "2.17.0" @@ -160,6 +358,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, ] +[[package]] +name = "backports-tarfile" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", size = 86406, upload-time = "2024-05-28T17:01:54.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181, upload-time = "2024-05-28T17:01:53.112Z" }, +] + [[package]] name = "backrefs" version = "5.9" @@ -172,6 +379,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/41/ff/392bff89415399a979be4a65357a41d92729ae8580a66073d8ec8d810f98/backrefs-5.9-py39-none-any.whl", hash = "sha256:f48ee18f6252b8f5777a22a00a09a85de0ca931658f1dd96d4406a34f3748c60", size = 380265, upload-time = "2025-06-22T19:34:12.405Z" }, ] +[[package]] +name = "beartype" +version = "0.22.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/94/1009e248bbfbab11397abca7193bea6626806be9a327d399810d523a07cb/beartype-0.22.9.tar.gz", hash = "sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f", size = 1608866, upload-time = "2025-12-13T06:50:30.72Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" }, +] + [[package]] name = "beautifulsoup4" version = "4.8.0" @@ -201,6 +417,34 @@ css = [ { name = "tinycss2" }, ] +[[package]] +name = "boto3" +version = "1.42.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, + { name = "jmespath" }, + { name = "s3transfer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/41/ed/8eacb8ec7bf264079608be5f9a2a57e31e7fed7a791bb3b15500ca9274a5/boto3-1.42.52.tar.gz", hash = "sha256:ff4a4afb832f63a1358e11fe6eb321da0f4767979c6721dd32fb02e6eabcebf5", size = 112811, upload-time = "2026-02-18T21:54:57.804Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/2a/de34ad6c43c56fe6dd5824bff2cd7fdef5edd9de0617cbd217040318ba97/boto3-1.42.52-py3-none-any.whl", hash = "sha256:7b3e0c4bfd8815a3df64fbe98fc9f87dfb12bd7a783cf63dfc2f166c66798c9d", size = 140556, upload-time = "2026-02-18T21:54:56.609Z" }, +] + +[[package]] +name = "botocore" +version = "1.42.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jmespath" }, + { name = "python-dateutil" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/37/7044e09d416ff746d23c7456e8c30ddade1154ecd08814b17ab7e2c20fb0/botocore-1.42.52.tar.gz", hash = "sha256:3bdef10aee4cee13ff019b6a1423a2ce3ca17352328d9918157a1829e5cc9be1", size = 14917923, upload-time = "2026-02-18T21:54:48.06Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/67/bbd723d489b25ff9f94a734e734986bb8343263dd024a3846291028c26d0/botocore-1.42.52-py3-none-any.whl", hash = "sha256:c3a0b7138a4c5a534da0eb2444c19763b4d03ba2190c0602c49315e54efd7252", size = 14588731, upload-time = "2026-02-18T21:54:45.532Z" }, +] + [[package]] name = "cachetools" version = "6.1.0" @@ -210,6 +454,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/00/f0/2ef431fe4141f5e334759d73e81120492b23b2824336883a91ac04ba710b/cachetools-6.1.0-py3-none-any.whl", hash = "sha256:1c7bb3cf9193deaf3508b7c5f2a79986c13ea38965c5adcff1f84519cf39163e", size = 11189, upload-time = "2025-06-16T18:51:01.514Z" }, ] +[[package]] +name = "caio" +version = "0.9.25" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/88/b8527e1b00c1811db339a1df8bd1ae49d146fcea9d6a5c40e3a80aaeb38d/caio-0.9.25.tar.gz", hash = "sha256:16498e7f81d1d0f5a4c0ad3f2540e65fe25691376e0a5bd367f558067113ed10", size = 26781, upload-time = "2025-12-26T15:21:36.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/80/ea4ead0c5d52a9828692e7df20f0eafe8d26e671ce4883a0a146bb91049e/caio-0.9.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ca6c8ecda611478b6016cb94d23fd3eb7124852b985bdec7ecaad9f3116b9619", size = 36836, upload-time = "2025-12-26T15:22:04.662Z" }, + { url = "https://files.pythonhosted.org/packages/17/b9/36715c97c873649d1029001578f901b50250916295e3dddf20c865438865/caio-0.9.25-cp310-cp310-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:db9b5681e4af8176159f0d6598e73b2279bb661e718c7ac23342c550bd78c241", size = 79695, upload-time = "2025-12-26T15:22:18.818Z" }, + { url = "https://files.pythonhosted.org/packages/ec/90/543f556fcfcfa270713eef906b6352ab048e1e557afec12925c991dc93c2/caio-0.9.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d6956d9e4a27021c8bd6c9677f3a59eb1d820cc32d0343cea7961a03b1371965", size = 36839, upload-time = "2025-12-26T15:21:40.267Z" }, + { url = "https://files.pythonhosted.org/packages/51/3b/36f3e8ec38dafe8de4831decd2e44c69303d2a3892d16ceda42afed44e1b/caio-0.9.25-cp311-cp311-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bf84bfa039f25ad91f4f52944452a5f6f405e8afab4d445450978cd6241d1478", size = 80255, upload-time = "2025-12-26T15:22:20.271Z" }, + { url = "https://files.pythonhosted.org/packages/d3/25/79c98ebe12df31548ba4eaf44db11b7cad6b3e7b4203718335620939083c/caio-0.9.25-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fb7ff95af4c31ad3f03179149aab61097a71fd85e05f89b4786de0359dffd044", size = 36983, upload-time = "2025-12-26T15:21:36.075Z" }, + { url = "https://files.pythonhosted.org/packages/a3/2b/21288691f16d479945968a0a4f2856818c1c5be56881d51d4dac9b255d26/caio-0.9.25-cp312-cp312-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:97084e4e30dfa598449d874c4d8e0c8d5ea17d2f752ef5e48e150ff9d240cd64", size = 82012, upload-time = "2025-12-26T15:22:20.983Z" }, + { url = "https://files.pythonhosted.org/packages/86/93/1f76c8d1bafe3b0614e06b2195784a3765bbf7b0a067661af9e2dd47fc33/caio-0.9.25-py3-none-any.whl", hash = "sha256:06c0bb02d6b929119b1cfbe1ca403c768b2013a369e2db46bfa2a5761cf82e40", size = 19087, upload-time = "2025-12-26T15:22:00.221Z" }, +] + [[package]] name = "certifi" version = "2025.7.14" @@ -221,48 +480,50 @@ wheels = [ [[package]] name = "cffi" -version = "1.17.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pycparser" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191, upload-time = "2024-09-04T20:43:30.027Z" }, - { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592, upload-time = "2024-09-04T20:43:32.108Z" }, - { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024, upload-time = "2024-09-04T20:43:34.186Z" }, - { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188, upload-time = "2024-09-04T20:43:36.286Z" }, - { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571, upload-time = "2024-09-04T20:43:38.586Z" }, - { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687, upload-time = "2024-09-04T20:43:40.084Z" }, - { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211, upload-time = "2024-09-04T20:43:41.526Z" }, - { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325, upload-time = "2024-09-04T20:43:43.117Z" }, - { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784, upload-time = "2024-09-04T20:43:45.256Z" }, - { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564, upload-time = "2024-09-04T20:43:46.779Z" }, - { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804, upload-time = "2024-09-04T20:43:48.186Z" }, - { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299, upload-time = "2024-09-04T20:43:49.812Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264, upload-time = "2024-09-04T20:43:51.124Z" }, - { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651, upload-time = "2024-09-04T20:43:52.872Z" }, - { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259, upload-time = "2024-09-04T20:43:56.123Z" }, - { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200, upload-time = "2024-09-04T20:43:57.891Z" }, - { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235, upload-time = "2024-09-04T20:44:00.18Z" }, - { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721, upload-time = "2024-09-04T20:44:01.585Z" }, - { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242, upload-time = "2024-09-04T20:44:03.467Z" }, - { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999, upload-time = "2024-09-04T20:44:05.023Z" }, - { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242, upload-time = "2024-09-04T20:44:06.444Z" }, - { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604, upload-time = "2024-09-04T20:44:08.206Z" }, - { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727, upload-time = "2024-09-04T20:44:09.481Z" }, - { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400, upload-time = "2024-09-04T20:44:10.873Z" }, - { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload-time = "2024-09-04T20:44:12.232Z" }, - { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload-time = "2024-09-04T20:44:13.739Z" }, - { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" }, - { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" }, - { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" }, - { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" }, - { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" }, - { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" }, - { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" }, - { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" }, - { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" }, +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44", size = 184283, upload-time = "2025-09-08T23:22:08.01Z" }, + { url = "https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49", size = 180504, upload-time = "2025-09-08T23:22:10.637Z" }, + { url = "https://files.pythonhosted.org/packages/50/bd/b1a6362b80628111e6653c961f987faa55262b4002fcec42308cad1db680/cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", size = 208811, upload-time = "2025-09-08T23:22:12.267Z" }, + { url = "https://files.pythonhosted.org/packages/4f/27/6933a8b2562d7bd1fb595074cf99cc81fc3789f6a6c05cdabb46284a3188/cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", size = 216402, upload-time = "2025-09-08T23:22:13.455Z" }, + { url = "https://files.pythonhosted.org/packages/05/eb/b86f2a2645b62adcfff53b0dd97e8dfafb5c8aa864bd0d9a2c2049a0d551/cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", size = 203217, upload-time = "2025-09-08T23:22:14.596Z" }, + { url = "https://files.pythonhosted.org/packages/9f/e0/6cbe77a53acf5acc7c08cc186c9928864bd7c005f9efd0d126884858a5fe/cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4", size = 203079, upload-time = "2025-09-08T23:22:15.769Z" }, + { url = "https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", size = 216475, upload-time = "2025-09-08T23:22:17.427Z" }, + { url = "https://files.pythonhosted.org/packages/21/7a/13b24e70d2f90a322f2900c5d8e1f14fa7e2a6b3332b7309ba7b2ba51a5a/cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", size = 218829, upload-time = "2025-09-08T23:22:19.069Z" }, + { url = "https://files.pythonhosted.org/packages/60/99/c9dc110974c59cc981b1f5b66e1d8af8af764e00f0293266824d9c4254bc/cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", size = 211211, upload-time = "2025-09-08T23:22:20.588Z" }, + { url = "https://files.pythonhosted.org/packages/49/72/ff2d12dbf21aca1b32a40ed792ee6b40f6dc3a9cf1644bd7ef6e95e0ac5e/cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", size = 218036, upload-time = "2025-09-08T23:22:22.143Z" }, + { url = "https://files.pythonhosted.org/packages/e2/cc/027d7fb82e58c48ea717149b03bcadcbdc293553edb283af792bd4bcbb3f/cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a", size = 172184, upload-time = "2025-09-08T23:22:23.328Z" }, + { url = "https://files.pythonhosted.org/packages/33/fa/072dd15ae27fbb4e06b437eb6e944e75b068deb09e2a2826039e49ee2045/cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739", size = 182790, upload-time = "2025-09-08T23:22:24.752Z" }, + { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" }, + { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, + { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, + { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" }, + { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" }, + { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" }, + { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, + { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, + { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" }, + { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" }, + { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, + { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, + { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, + { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, + { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, + { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, + { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, + { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, + { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, ] [[package]] @@ -343,6 +604,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941, upload-time = "2023-08-17T17:29:10.08Z" }, ] +[[package]] +name = "cohere" +version = "5.20.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastavro" }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "pydantic-core" }, + { name = "requests" }, + { name = "tokenizers" }, + { name = "types-requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9a/7c/415e9b150843d879427ad4760c2331443d3f4e6860d17a3c3b3841357898/cohere-5.20.6.tar.gz", hash = "sha256:96b53fafcca97d7345646b66caafb79d6d92fa144c44b6d7fd63fbeade2a5155", size = 185110, upload-time = "2026-02-18T15:57:38.19Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/0e/175613bbd3a16465b93e429edd3a44e2f76d67367131206baa951a82925d/cohere-5.20.6-py3-none-any.whl", hash = "sha256:f67050be06c437fb3b330f1326e4fc1974cdcddbb6c25afd57c2bd94897feaa6", size = 323373, upload-time = "2026-02-18T15:57:36.761Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -494,6 +774,52 @@ toml = [ { name = "tomli", marker = "python_full_version <= '3.11'" }, ] +[[package]] +name = "cryptography" +version = "46.0.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/04/ee2a9e8542e4fa2773b81771ff8349ff19cdd56b7258a0cc442639052edb/cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d", size = 750064, upload-time = "2026-02-10T19:18:38.255Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/81/b0bb27f2ba931a65409c6b8a8b358a7f03c0e46eceacddff55f7c84b1f3b/cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad", size = 7176289, upload-time = "2026-02-10T19:17:08.274Z" }, + { url = "https://files.pythonhosted.org/packages/ff/9e/6b4397a3e3d15123de3b1806ef342522393d50736c13b20ec4c9ea6693a6/cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b", size = 4275637, upload-time = "2026-02-10T19:17:10.53Z" }, + { url = "https://files.pythonhosted.org/packages/63/e7/471ab61099a3920b0c77852ea3f0ea611c9702f651600397ac567848b897/cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b", size = 4424742, upload-time = "2026-02-10T19:17:12.388Z" }, + { url = "https://files.pythonhosted.org/packages/37/53/a18500f270342d66bf7e4d9f091114e31e5ee9e7375a5aba2e85a91e0044/cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263", size = 4277528, upload-time = "2026-02-10T19:17:13.853Z" }, + { url = "https://files.pythonhosted.org/packages/22/29/c2e812ebc38c57b40e7c583895e73c8c5adb4d1e4a0cc4c5a4fdab2b1acc/cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d", size = 4947993, upload-time = "2026-02-10T19:17:15.618Z" }, + { url = "https://files.pythonhosted.org/packages/6b/e7/237155ae19a9023de7e30ec64e5d99a9431a567407ac21170a046d22a5a3/cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed", size = 4456855, upload-time = "2026-02-10T19:17:17.221Z" }, + { url = "https://files.pythonhosted.org/packages/2d/87/fc628a7ad85b81206738abbd213b07702bcbdada1dd43f72236ef3cffbb5/cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2", size = 3984635, upload-time = "2026-02-10T19:17:18.792Z" }, + { url = "https://files.pythonhosted.org/packages/84/29/65b55622bde135aedf4565dc509d99b560ee4095e56989e815f8fd2aa910/cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2", size = 4277038, upload-time = "2026-02-10T19:17:20.256Z" }, + { url = "https://files.pythonhosted.org/packages/bc/36/45e76c68d7311432741faf1fbf7fac8a196a0a735ca21f504c75d37e2558/cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0", size = 4912181, upload-time = "2026-02-10T19:17:21.825Z" }, + { url = "https://files.pythonhosted.org/packages/6d/1a/c1ba8fead184d6e3d5afcf03d569acac5ad063f3ac9fb7258af158f7e378/cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731", size = 4456482, upload-time = "2026-02-10T19:17:25.133Z" }, + { url = "https://files.pythonhosted.org/packages/f9/e5/3fb22e37f66827ced3b902cf895e6a6bc1d095b5b26be26bd13c441fdf19/cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82", size = 4405497, upload-time = "2026-02-10T19:17:26.66Z" }, + { url = "https://files.pythonhosted.org/packages/1a/df/9d58bb32b1121a8a2f27383fabae4d63080c7ca60b9b5c88be742be04ee7/cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1", size = 4667819, upload-time = "2026-02-10T19:17:28.569Z" }, + { url = "https://files.pythonhosted.org/packages/ea/ed/325d2a490c5e94038cdb0117da9397ece1f11201f425c4e9c57fe5b9f08b/cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48", size = 3028230, upload-time = "2026-02-10T19:17:30.518Z" }, + { url = "https://files.pythonhosted.org/packages/e9/5a/ac0f49e48063ab4255d9e3b79f5def51697fce1a95ea1370f03dc9db76f6/cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4", size = 3480909, upload-time = "2026-02-10T19:17:32.083Z" }, + { url = "https://files.pythonhosted.org/packages/e2/fa/a66aa722105ad6a458bebd64086ca2b72cdd361fed31763d20390f6f1389/cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31", size = 7170514, upload-time = "2026-02-10T19:17:56.267Z" }, + { url = "https://files.pythonhosted.org/packages/0f/04/c85bdeab78c8bc77b701bf0d9bdcf514c044e18a46dcff330df5448631b0/cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18", size = 4275349, upload-time = "2026-02-10T19:17:58.419Z" }, + { url = "https://files.pythonhosted.org/packages/5c/32/9b87132a2f91ee7f5223b091dc963055503e9b442c98fc0b8a5ca765fab0/cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235", size = 4420667, upload-time = "2026-02-10T19:18:00.619Z" }, + { url = "https://files.pythonhosted.org/packages/a1/a6/a7cb7010bec4b7c5692ca6f024150371b295ee1c108bdc1c400e4c44562b/cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a", size = 4276980, upload-time = "2026-02-10T19:18:02.379Z" }, + { url = "https://files.pythonhosted.org/packages/8e/7c/c4f45e0eeff9b91e3f12dbd0e165fcf2a38847288fcfd889deea99fb7b6d/cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76", size = 4939143, upload-time = "2026-02-10T19:18:03.964Z" }, + { url = "https://files.pythonhosted.org/packages/37/19/e1b8f964a834eddb44fa1b9a9976f4e414cbb7aa62809b6760c8803d22d1/cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614", size = 4453674, upload-time = "2026-02-10T19:18:05.588Z" }, + { url = "https://files.pythonhosted.org/packages/db/ed/db15d3956f65264ca204625597c410d420e26530c4e2943e05a0d2f24d51/cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229", size = 3978801, upload-time = "2026-02-10T19:18:07.167Z" }, + { url = "https://files.pythonhosted.org/packages/41/e2/df40a31d82df0a70a0daf69791f91dbb70e47644c58581d654879b382d11/cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1", size = 4276755, upload-time = "2026-02-10T19:18:09.813Z" }, + { url = "https://files.pythonhosted.org/packages/33/45/726809d1176959f4a896b86907b98ff4391a8aa29c0aaaf9450a8a10630e/cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d", size = 4901539, upload-time = "2026-02-10T19:18:11.263Z" }, + { url = "https://files.pythonhosted.org/packages/99/0f/a3076874e9c88ecb2ecc31382f6e7c21b428ede6f55aafa1aa272613e3cd/cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c", size = 4452794, upload-time = "2026-02-10T19:18:12.914Z" }, + { url = "https://files.pythonhosted.org/packages/02/ef/ffeb542d3683d24194a38f66ca17c0a4b8bf10631feef44a7ef64e631b1a/cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4", size = 4404160, upload-time = "2026-02-10T19:18:14.375Z" }, + { url = "https://files.pythonhosted.org/packages/96/93/682d2b43c1d5f1406ed048f377c0fc9fc8f7b0447a478d5c65ab3d3a66eb/cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9", size = 4667123, upload-time = "2026-02-10T19:18:15.886Z" }, + { url = "https://files.pythonhosted.org/packages/45/2d/9c5f2926cb5300a8eefc3f4f0b3f3df39db7f7ce40c8365444c49363cbda/cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72", size = 3010220, upload-time = "2026-02-10T19:18:17.361Z" }, + { url = "https://files.pythonhosted.org/packages/48/ef/0c2f4a8e31018a986949d34a01115dd057bf536905dca38897bacd21fac3/cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595", size = 3467050, upload-time = "2026-02-10T19:18:18.899Z" }, + { url = "https://files.pythonhosted.org/packages/eb/dd/2d9fdb07cebdf3d51179730afb7d5e576153c6744c3ff8fded23030c204e/cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c", size = 3476964, upload-time = "2026-02-10T19:18:20.687Z" }, + { url = "https://files.pythonhosted.org/packages/e9/6f/6cc6cc9955caa6eaf83660b0da2b077c7fe8ff9950a3c5e45d605038d439/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a", size = 4218321, upload-time = "2026-02-10T19:18:22.349Z" }, + { url = "https://files.pythonhosted.org/packages/3e/5d/c4da701939eeee699566a6c1367427ab91a8b7088cc2328c09dbee940415/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356", size = 4381786, upload-time = "2026-02-10T19:18:24.529Z" }, + { url = "https://files.pythonhosted.org/packages/ac/97/a538654732974a94ff96c1db621fa464f455c02d4bb7d2652f4edc21d600/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da", size = 4217990, upload-time = "2026-02-10T19:18:25.957Z" }, + { url = "https://files.pythonhosted.org/packages/ae/11/7e500d2dd3ba891197b9efd2da5454b74336d64a7cc419aa7327ab74e5f6/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257", size = 4381252, upload-time = "2026-02-10T19:18:27.496Z" }, + { url = "https://files.pythonhosted.org/packages/bc/58/6b3d24e6b9bc474a2dcdee65dfd1f008867015408a271562e4b690561a4d/cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7", size = 3407605, upload-time = "2026-02-10T19:18:29.233Z" }, +] + [[package]] name = "cycler" version = "0.12.1" @@ -503,6 +829,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, ] +[[package]] +name = "cyclopts" +version = "4.5.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "docstring-parser" }, + { name = "rich" }, + { name = "rich-rst" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a5/16/06e35c217334930ff7c476ce1c8e74ed786fa3ef6742e59a1458e2412290/cyclopts-4.5.3.tar.gz", hash = "sha256:35fa70971204c450d9668646a6ca372eb5fa3070fbe8dd51c5b4b31e65198f2d", size = 162437, upload-time = "2026-02-16T15:07:11.96Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/1f/d8bce383a90d8a6a11033327777afa4d4d611ec11869284adb6f48152906/cyclopts-4.5.3-py3-none-any.whl", hash = "sha256:50af3085bb15d4a6f2582dd383dad5e4ba6a0d4d4c64ee63326d881a752a6919", size = 200231, upload-time = "2026-02-16T15:07:13.045Z" }, +] + [[package]] name = "debugpy" version = "1.8.15" @@ -551,6 +894,55 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, ] +[[package]] +name = "distro" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, +] + +[[package]] +name = "dnspython" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, +] + +[[package]] +name = "docstring-parser" +version = "0.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/9d/c3b43da9515bd270df0f80548d9944e389870713cc1fe2b8fb35fe2bcefd/docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912", size = 27442, upload-time = "2025-07-21T07:35:01.868Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size = 36896, upload-time = "2025-07-21T07:35:00.684Z" }, +] + +[[package]] +name = "docutils" +version = "0.22.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, +] + +[[package]] +name = "email-validator" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dnspython" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" }, +] + [[package]] name = "energy-pandas" version = "0.4.1" @@ -589,6 +981,11 @@ dependencies = [ { name = "pythermalcomfort" }, ] +[package.optional-dependencies] +llm = [ + { name = "pydantic-ai" }, +] + [package.dev-dependencies] dev = [ { name = "jupyter" }, @@ -611,18 +1008,20 @@ docs = [ [package.metadata] requires-dist = [ - { name = "archetypal", specifier = "==2.18.10" }, + { name = "archetypal", directory = "archetypal" }, { name = "click", specifier = "==8.1.7" }, { name = "geopandas", specifier = "~=1.0.1" }, - { name = "httpx", specifier = "~=0.27.2" }, + { name = "httpx", specifier = ">=0.27.2" }, { name = "ladybug-core", specifier = ">=0.44.30" }, { name = "openpyxl", specifier = "~=3.1.5" }, { name = "pandas", specifier = ">=2.2,<2.3" }, { name = "prisma", specifier = "~=0.15.0" }, { name = "pydantic", specifier = ">=2.9,<3" }, + { name = "pydantic-ai", marker = "extra == 'llm'", specifier = ">=1.62" }, { name = "pydantic-settings", specifier = ">=2.0,<3" }, { name = "pythermalcomfort", specifier = ">=3.8.0" }, ] +provides-extras = ["llm"] [package.metadata.requires-dev] dev = [ @@ -679,12 +1078,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", size = 18059, upload-time = "2024-10-25T17:25:39.051Z" }, ] +[[package]] +name = "eval-type-backport" +version = "0.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fb/a3/cafafb4558fd638aadfe4121dc6cefb8d743368c085acb2f521df0f3d9d7/eval_type_backport-0.3.1.tar.gz", hash = "sha256:57e993f7b5b69d271e37482e62f74e76a0276c82490cf8e4f0dffeb6b332d5ed", size = 9445, upload-time = "2025-12-02T11:51:42.987Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/22/fdc2e30d43ff853720042fa15baa3e6122722be1a7950a98233ebb55cd71/eval_type_backport-0.3.1-py3-none-any.whl", hash = "sha256:279ab641905e9f11129f56a8a78f493518515b83402b860f6f06dd7c011fdfa8", size = 6063, upload-time = "2025-12-02T11:51:41.665Z" }, +] + [[package]] name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ @@ -700,6 +1108,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702, upload-time = "2025-01-22T15:41:25.929Z" }, ] +[[package]] +name = "fastavro" +version = "1.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/65/8b/fa2d3287fd2267be6261d0177c6809a7fa12c5600ddb33490c8dc29e77b2/fastavro-1.12.1.tar.gz", hash = "sha256:2f285be49e45bc047ab2f6bed040bb349da85db3f3c87880e4b92595ea093b2b", size = 1025661, upload-time = "2025-10-10T15:40:55.41Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/a0/077fd7cbfc143152cb96780cb592ed6cb6696667d8bc1b977745eb2255a8/fastavro-1.12.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:00650ca533907361edda22e6ffe8cf87ab2091c5d8aee5c8000b0f2dcdda7ed3", size = 1000335, upload-time = "2025-10-10T15:40:59.834Z" }, + { url = "https://files.pythonhosted.org/packages/a0/ae/a115e027f3a75df237609701b03ecba0b7f0aa3d77fe0161df533fde1eb7/fastavro-1.12.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac76d6d95f909c72ee70d314b460b7e711d928845771531d823eb96a10952d26", size = 3221067, upload-time = "2025-10-10T15:41:04.399Z" }, + { url = "https://files.pythonhosted.org/packages/94/4e/c4991c3eec0175af9a8a0c161b88089cb7bf7fe353b3e3be1bc4cf9036b2/fastavro-1.12.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f55eef18c41d4476bd32a82ed5dd86aabc3f614e1b66bdb09ffa291612e1670", size = 3228979, upload-time = "2025-10-10T15:41:06.738Z" }, + { url = "https://files.pythonhosted.org/packages/21/0c/f2afb8eaea38799ccb1ed07d68bf2659f2e313f1902bbd36774cf6a1bef9/fastavro-1.12.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81563e1f93570e6565487cdb01ba241a36a00e58cff9c5a0614af819d1155d8f", size = 3160740, upload-time = "2025-10-10T15:41:08.731Z" }, + { url = "https://files.pythonhosted.org/packages/0d/1a/f4d367924b40b86857862c1fa65f2afba94ddadf298b611e610a676a29e5/fastavro-1.12.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bec207360f76f0b3de540758a297193c5390e8e081c43c3317f610b1414d8c8f", size = 3235787, upload-time = "2025-10-10T15:41:10.869Z" }, + { url = "https://files.pythonhosted.org/packages/90/ec/8db9331896e3dfe4f71b2b3c23f2e97fbbfd90129777467ca9f8bafccb74/fastavro-1.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:c0390bfe4a9f8056a75ac6785fbbff8f5e317f5356481d2e29ec980877d2314b", size = 449350, upload-time = "2025-10-10T15:41:12.104Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e9/31c64b47cefc0951099e7c0c8c8ea1c931edd1350f34d55c27cbfbb08df1/fastavro-1.12.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b632b713bc5d03928a87d811fa4a11d5f25cd43e79c161e291c7d3f7aa740fd", size = 1016585, upload-time = "2025-10-10T15:41:13.717Z" }, + { url = "https://files.pythonhosted.org/packages/10/76/111560775b548f5d8d828c1b5285ff90e2d2745643fb80ecbf115344eea4/fastavro-1.12.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa7ab3769beadcebb60f0539054c7755f63bd9cf7666e2c15e615ab605f89a8", size = 3404629, upload-time = "2025-10-10T15:41:15.642Z" }, + { url = "https://files.pythonhosted.org/packages/b0/07/6bb93cb963932146c2b6c5c765903a0a547ad9f0f8b769a4a9aad8c06369/fastavro-1.12.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123fb221df3164abd93f2d042c82f538a1d5a43ce41375f12c91ce1355a9141e", size = 3428594, upload-time = "2025-10-10T15:41:17.779Z" }, + { url = "https://files.pythonhosted.org/packages/d1/67/8115ec36b584197ea737ec79e3499e1f1b640b288d6c6ee295edd13b80f6/fastavro-1.12.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:632a4e3ff223f834ddb746baae0cc7cee1068eb12c32e4d982c2fee8a5b483d0", size = 3344145, upload-time = "2025-10-10T15:41:19.89Z" }, + { url = "https://files.pythonhosted.org/packages/9e/9e/a7cebb3af967e62539539897c10138fa0821668ec92525d1be88a9cd3ee6/fastavro-1.12.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83e6caf4e7a8717d932a3b1ff31595ad169289bbe1128a216be070d3a8391671", size = 3431942, upload-time = "2025-10-10T15:41:22.076Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d1/7774ddfb8781c5224294c01a593ebce2ad3289b948061c9701bd1903264d/fastavro-1.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:b91a0fe5a173679a6c02d53ca22dcaad0a2c726b74507e0c1c2e71a7c3f79ef9", size = 450542, upload-time = "2025-10-10T15:41:23.333Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f0/10bd1a3d08667fa0739e2b451fe90e06df575ec8b8ba5d3135c70555c9bd/fastavro-1.12.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:509818cb24b98a804fc80be9c5fed90f660310ae3d59382fc811bfa187122167", size = 1009057, upload-time = "2025-10-10T15:41:24.556Z" }, + { url = "https://files.pythonhosted.org/packages/78/ad/0d985bc99e1fa9e74c636658000ba38a5cd7f5ab2708e9c62eaf736ecf1a/fastavro-1.12.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089e155c0c76e0d418d7e79144ce000524dd345eab3bc1e9c5ae69d500f71b14", size = 3391866, upload-time = "2025-10-10T15:41:26.882Z" }, + { url = "https://files.pythonhosted.org/packages/0d/9e/b4951dc84ebc34aac69afcbfbb22ea4a91080422ec2bfd2c06076ff1d419/fastavro-1.12.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44cbff7518901c91a82aab476fcab13d102e4999499df219d481b9e15f61af34", size = 3458005, upload-time = "2025-10-10T15:41:29.017Z" }, + { url = "https://files.pythonhosted.org/packages/af/f8/5a8df450a9f55ca8441f22ea0351d8c77809fc121498b6970daaaf667a21/fastavro-1.12.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a275e48df0b1701bb764b18a8a21900b24cf882263cb03d35ecdba636bbc830b", size = 3295258, upload-time = "2025-10-10T15:41:31.564Z" }, + { url = "https://files.pythonhosted.org/packages/99/b2/40f25299111d737e58b85696e91138a66c25b7334f5357e7ac2b0e8966f8/fastavro-1.12.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2de72d786eb38be6b16d556b27232b1bf1b2797ea09599507938cdb7a9fe3e7c", size = 3430328, upload-time = "2025-10-10T15:41:33.689Z" }, + { url = "https://files.pythonhosted.org/packages/e0/07/85157a7c57c5f8b95507d7829b5946561e5ee656ff80e9dd9a757f53ddaf/fastavro-1.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:9090f0dee63fe022ee9cc5147483366cc4171c821644c22da020d6b48f576b4f", size = 444140, upload-time = "2025-10-10T15:41:34.902Z" }, +] + [[package]] name = "fastjsonschema" version = "2.21.1" @@ -709,6 +1143,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/90/2b/0817a2b257fe88725c25589d89aec060581aabf668707a8d03b2e9e0cb2a/fastjsonschema-2.21.1-py3-none-any.whl", hash = "sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667", size = 23924, upload-time = "2024-12-02T10:55:07.599Z" }, ] +[[package]] +name = "fastmcp" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "authlib" }, + { name = "cyclopts" }, + { name = "exceptiongroup" }, + { name = "httpx" }, + { name = "jsonref" }, + { name = "jsonschema-path" }, + { name = "mcp" }, + { name = "openapi-pydantic" }, + { name = "opentelemetry-api" }, + { name = "packaging" }, + { name = "platformdirs" }, + { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, + { name = "pydantic", extra = ["email"] }, + { name = "pyperclip" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "rich" }, + { name = "uvicorn" }, + { name = "watchfiles" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4b/be/beb5d3e485983b9dd122f3f74772bcceeb085ca824e11c52c14ba71cf21a/fastmcp-3.0.0.tar.gz", hash = "sha256:f3b0cfa012f6b2b50b877da181431c6f9a551197f466b0bb7de7f39ceae159a1", size = 16093079, upload-time = "2026-02-18T21:25:34.461Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/14/05bebaf3764ea71ce6fa9d3fcf870610bbc8b1e7be2505e870d709375316/fastmcp-3.0.0-py3-none-any.whl", hash = "sha256:561d537cb789f995174c5591f1b54f758ce3f82da3cd951ffe51ce18609569e9", size = 603327, upload-time = "2026-02-18T21:25:36.701Z" }, +] + [[package]] name = "filelock" version = "3.18.0" @@ -784,6 +1249,72 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, ] +[[package]] +name = "frozenlist" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/4a/557715d5047da48d54e659203b9335be7bfaafda2c3f627b7c47e0b3aaf3/frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011", size = 86230, upload-time = "2025-10-06T05:35:23.699Z" }, + { url = "https://files.pythonhosted.org/packages/a2/fb/c85f9fed3ea8fe8740e5b46a59cc141c23b842eca617da8876cfce5f760e/frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565", size = 49621, upload-time = "2025-10-06T05:35:25.341Z" }, + { url = "https://files.pythonhosted.org/packages/63/70/26ca3f06aace16f2352796b08704338d74b6d1a24ca38f2771afbb7ed915/frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad", size = 49889, upload-time = "2025-10-06T05:35:26.797Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ed/c7895fd2fde7f3ee70d248175f9b6cdf792fb741ab92dc59cd9ef3bd241b/frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2", size = 219464, upload-time = "2025-10-06T05:35:28.254Z" }, + { url = "https://files.pythonhosted.org/packages/6b/83/4d587dccbfca74cb8b810472392ad62bfa100bf8108c7223eb4c4fa2f7b3/frozenlist-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186", size = 221649, upload-time = "2025-10-06T05:35:29.454Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c6/fd3b9cd046ec5fff9dab66831083bc2077006a874a2d3d9247dea93ddf7e/frozenlist-1.8.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e", size = 219188, upload-time = "2025-10-06T05:35:30.951Z" }, + { url = "https://files.pythonhosted.org/packages/ce/80/6693f55eb2e085fc8afb28cf611448fb5b90e98e068fa1d1b8d8e66e5c7d/frozenlist-1.8.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450", size = 231748, upload-time = "2025-10-06T05:35:32.101Z" }, + { url = "https://files.pythonhosted.org/packages/97/d6/e9459f7c5183854abd989ba384fe0cc1a0fb795a83c033f0571ec5933ca4/frozenlist-1.8.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef", size = 236351, upload-time = "2025-10-06T05:35:33.834Z" }, + { url = "https://files.pythonhosted.org/packages/97/92/24e97474b65c0262e9ecd076e826bfd1d3074adcc165a256e42e7b8a7249/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4", size = 218767, upload-time = "2025-10-06T05:35:35.205Z" }, + { url = "https://files.pythonhosted.org/packages/ee/bf/dc394a097508f15abff383c5108cb8ad880d1f64a725ed3b90d5c2fbf0bb/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff", size = 235887, upload-time = "2025-10-06T05:35:36.354Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/25b201b9c015dbc999a5baf475a257010471a1fa8c200c843fd4abbee725/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c", size = 228785, upload-time = "2025-10-06T05:35:37.949Z" }, + { url = "https://files.pythonhosted.org/packages/84/f4/b5bc148df03082f05d2dd30c089e269acdbe251ac9a9cf4e727b2dbb8a3d/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f", size = 230312, upload-time = "2025-10-06T05:35:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/db/4b/87e95b5d15097c302430e647136b7d7ab2398a702390cf4c8601975709e7/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7", size = 217650, upload-time = "2025-10-06T05:35:40.377Z" }, + { url = "https://files.pythonhosted.org/packages/e5/70/78a0315d1fea97120591a83e0acd644da638c872f142fd72a6cebee825f3/frozenlist-1.8.0-cp310-cp310-win32.whl", hash = "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a", size = 39659, upload-time = "2025-10-06T05:35:41.863Z" }, + { url = "https://files.pythonhosted.org/packages/66/aa/3f04523fb189a00e147e60c5b2205126118f216b0aa908035c45336e27e4/frozenlist-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6", size = 43837, upload-time = "2025-10-06T05:35:43.205Z" }, + { url = "https://files.pythonhosted.org/packages/39/75/1135feecdd7c336938bd55b4dc3b0dfc46d85b9be12ef2628574b28de776/frozenlist-1.8.0-cp310-cp310-win_arm64.whl", hash = "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e", size = 39989, upload-time = "2025-10-06T05:35:44.596Z" }, + { url = "https://files.pythonhosted.org/packages/bc/03/077f869d540370db12165c0aa51640a873fb661d8b315d1d4d67b284d7ac/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", size = 86912, upload-time = "2025-10-06T05:35:45.98Z" }, + { url = "https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", size = 50046, upload-time = "2025-10-06T05:35:47.009Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", size = 50119, upload-time = "2025-10-06T05:35:48.38Z" }, + { url = "https://files.pythonhosted.org/packages/11/b1/71a477adc7c36e5fb628245dfbdea2166feae310757dea848d02bd0689fd/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", size = 231067, upload-time = "2025-10-06T05:35:49.97Z" }, + { url = "https://files.pythonhosted.org/packages/45/7e/afe40eca3a2dc19b9904c0f5d7edfe82b5304cb831391edec0ac04af94c2/frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", size = 233160, upload-time = "2025-10-06T05:35:51.729Z" }, + { url = "https://files.pythonhosted.org/packages/a6/aa/7416eac95603ce428679d273255ffc7c998d4132cfae200103f164b108aa/frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", size = 228544, upload-time = "2025-10-06T05:35:53.246Z" }, + { url = "https://files.pythonhosted.org/packages/8b/3d/2a2d1f683d55ac7e3875e4263d28410063e738384d3adc294f5ff3d7105e/frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", size = 243797, upload-time = "2025-10-06T05:35:54.497Z" }, + { url = "https://files.pythonhosted.org/packages/78/1e/2d5565b589e580c296d3bb54da08d206e797d941a83a6fdea42af23be79c/frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", size = 247923, upload-time = "2025-10-06T05:35:55.861Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/65872fcf1d326a7f101ad4d86285c403c87be7d832b7470b77f6d2ed5ddc/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", size = 230886, upload-time = "2025-10-06T05:35:57.399Z" }, + { url = "https://files.pythonhosted.org/packages/a0/76/ac9ced601d62f6956f03cc794f9e04c81719509f85255abf96e2510f4265/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", size = 245731, upload-time = "2025-10-06T05:35:58.563Z" }, + { url = "https://files.pythonhosted.org/packages/b9/49/ecccb5f2598daf0b4a1415497eba4c33c1e8ce07495eb07d2860c731b8d5/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", size = 241544, upload-time = "2025-10-06T05:35:59.719Z" }, + { url = "https://files.pythonhosted.org/packages/53/4b/ddf24113323c0bbcc54cb38c8b8916f1da7165e07b8e24a717b4a12cbf10/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", size = 241806, upload-time = "2025-10-06T05:36:00.959Z" }, + { url = "https://files.pythonhosted.org/packages/a7/fb/9b9a084d73c67175484ba2789a59f8eebebd0827d186a8102005ce41e1ba/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", size = 229382, upload-time = "2025-10-06T05:36:02.22Z" }, + { url = "https://files.pythonhosted.org/packages/95/a3/c8fb25aac55bf5e12dae5c5aa6a98f85d436c1dc658f21c3ac73f9fa95e5/frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25", size = 39647, upload-time = "2025-10-06T05:36:03.409Z" }, + { url = "https://files.pythonhosted.org/packages/0a/f5/603d0d6a02cfd4c8f2a095a54672b3cf967ad688a60fb9faf04fc4887f65/frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b", size = 44064, upload-time = "2025-10-06T05:36:04.368Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/c2c9ab44e181f043a86f9a8f84d5124b62dbcb3a02c0977ec72b9ac1d3e0/frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a", size = 39937, upload-time = "2025-10-06T05:36:05.669Z" }, + { url = "https://files.pythonhosted.org/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, + { url = "https://files.pythonhosted.org/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, + { url = "https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, + { url = "https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, + { url = "https://files.pythonhosted.org/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, + { url = "https://files.pythonhosted.org/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, + { url = "https://files.pythonhosted.org/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, + { url = "https://files.pythonhosted.org/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, + { url = "https://files.pythonhosted.org/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, + { url = "https://files.pythonhosted.org/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, + { url = "https://files.pythonhosted.org/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, + { url = "https://files.pythonhosted.org/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, + { url = "https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, + { url = "https://files.pythonhosted.org/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, + { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, +] + +[[package]] +name = "fsspec" +version = "2026.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/51/7c/f60c259dcbf4f0c47cc4ddb8f7720d2dcdc8888c8e5ad84c73ea4531cc5b/fsspec-2026.2.0.tar.gz", hash = "sha256:6544e34b16869f5aacd5b90bdf1a71acb37792ea3ddf6125ee69a22a53fb8bff", size = 313441, upload-time = "2026-02-05T21:50:53.743Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl", hash = "sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437", size = 202505, upload-time = "2026-02-05T21:50:51.819Z" }, +] + [[package]] name = "future" version = "1.0.0" @@ -793,6 +1324,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216", size = 491326, upload-time = "2024-02-21T11:52:35.956Z" }, ] +[[package]] +name = "genai-prices" +version = "0.0.54" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8e/20/d64d04c7870db01232f8f8e36dec2072281b1f594b924200aa017778eec2/genai_prices-0.0.54.tar.gz", hash = "sha256:9d985affc19d055be16613b0c5e49d182d4c2164cf1587129f9996dfb9a3cb8d", size = 59588, upload-time = "2026-02-17T20:26:06.849Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/71/d2a941b0ca01186912fedb096d8eef7b3e1680c86fdcf8fe3dc84e76d5a9/genai_prices-0.0.54-py3-none-any.whl", hash = "sha256:5b45012b2981b7d4d42c49c8614ee95420fec244c87542542045786b36fc2235", size = 62198, upload-time = "2026-02-17T20:26:05.186Z" }, +] + [[package]] name = "geopandas" version = "1.0.1" @@ -823,6 +1367,59 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034, upload-time = "2022-05-02T15:47:14.552Z" }, ] +[[package]] +name = "google-auth" +version = "2.48.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "pyasn1-modules" }, + { name = "rsa" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0c/41/242044323fbd746615884b1c16639749e73665b718209946ebad7ba8a813/google_auth-2.48.0.tar.gz", hash = "sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce", size = 326522, upload-time = "2026-01-26T19:22:47.157Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/1d/d6466de3a5249d35e832a52834115ca9d1d0de6abc22065f049707516d47/google_auth-2.48.0-py3-none-any.whl", hash = "sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f", size = 236499, upload-time = "2026-01-26T19:22:45.099Z" }, +] + +[package.optional-dependencies] +requests = [ + { name = "requests" }, +] + +[[package]] +name = "google-genai" +version = "1.64.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "anyio" }, + { name = "distro" }, + { name = "google-auth", extra = ["requests"] }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "sniffio" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bc/14/344b450d4387845fc5c8b7f168ffbe734b831b729ece3333fc0fe8556f04/google_genai-1.64.0.tar.gz", hash = "sha256:8db94ab031f745d08c45c69674d1892f7447c74ed21542abe599f7888e28b924", size = 496434, upload-time = "2026-02-19T02:06:13.95Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/56/765eca90c781fedbe2a7e7dc873ef6045048e28ba5f2d4a5bcb13e13062b/google_genai-1.64.0-py3-none-any.whl", hash = "sha256:78a4d2deeb33b15ad78eaa419f6f431755e7f0e03771254f8000d70f717e940b", size = 728836, upload-time = "2026-02-19T02:06:11.655Z" }, +] + +[[package]] +name = "googleapis-common-protos" +version = "1.72.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e5/7b/adfd75544c415c487b33061fe7ae526165241c1ea133f9a9125a56b39fd8/googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5", size = 147433, upload-time = "2025-11-06T18:29:24.087Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/ab/09169d5a4612a5f92490806649ac8d41e3ec9129c636754575b3553f4ea4/googleapis_common_protos-1.72.0-py3-none-any.whl", hash = "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038", size = 297515, upload-time = "2025-11-06T18:29:13.14Z" }, +] + [[package]] name = "griffe" version = "1.7.3" @@ -835,6 +1432,72 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/58/c6/5c20af38c2a57c15d87f7f38bee77d63c1d2a3689f74fefaf35915dd12b2/griffe-1.7.3-py3-none-any.whl", hash = "sha256:c6b3ee30c2f0f17f30bcdef5068d6ab7a2a4f1b8bf1a3e74b56fffd21e1c5f75", size = 129303, upload-time = "2025-04-23T11:29:07.145Z" }, ] +[[package]] +name = "griffelib" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl", hash = "sha256:01284878c966508b6d6f1dbff9b6fa607bc062d8261c5c7253cb285b06422a7f", size = 142004, upload-time = "2026-02-09T19:09:40.561Z" }, +] + +[[package]] +name = "groq" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3f/12/f4099a141677fcd2ed79dcc1fcec431e60c52e0e90c9c5d935f0ffaf8c0e/groq-1.0.0.tar.gz", hash = "sha256:66cb7bb729e6eb644daac7ce8efe945e99e4eb33657f733ee6f13059ef0c25a9", size = 146068, upload-time = "2025-12-17T23:34:23.115Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/88/3175759d2ef30406ea721f4d837bfa1ba4339fde3b81ba8c5640a96ed231/groq-1.0.0-py3-none-any.whl", hash = "sha256:6e22bf92ffad988f01d2d4df7729add66b8fd5dbfb2154b5bbf3af245b72c731", size = 138292, upload-time = "2025-12-17T23:34:21.957Z" }, +] + +[[package]] +name = "grpcio" +version = "1.78.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/8a/3d098f35c143a89520e568e6539cc098fcd294495910e359889ce8741c84/grpcio-1.78.0.tar.gz", hash = "sha256:7382b95189546f375c174f53a5fa873cef91c4b8005faa05cc5b3beea9c4f1c5", size = 12852416, upload-time = "2026-02-06T09:57:18.093Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/a8/690a085b4d1fe066130de97a87de32c45062cf2ecd218df9675add895550/grpcio-1.78.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:7cc47943d524ee0096f973e1081cb8f4f17a4615f2116882a5f1416e4cfe92b5", size = 5946986, upload-time = "2026-02-06T09:54:34.043Z" }, + { url = "https://files.pythonhosted.org/packages/c7/1b/e5213c5c0ced9d2d92778d30529ad5bb2dcfb6c48c4e2d01b1f302d33d64/grpcio-1.78.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:c3f293fdc675ccba4db5a561048cca627b5e7bd1c8a6973ffedabe7d116e22e2", size = 11816533, upload-time = "2026-02-06T09:54:37.04Z" }, + { url = "https://files.pythonhosted.org/packages/18/37/1ba32dccf0a324cc5ace744c44331e300b000a924bf14840f948c559ede7/grpcio-1.78.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:10a9a644b5dd5aec3b82b5b0b90d41c0fa94c85ef42cb42cf78a23291ddb5e7d", size = 6519964, upload-time = "2026-02-06T09:54:40.268Z" }, + { url = "https://files.pythonhosted.org/packages/ed/f5/c0e178721b818072f2e8b6fde13faaba942406c634009caf065121ce246b/grpcio-1.78.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4c5533d03a6cbd7f56acfc9cfb44ea64f63d29091e40e44010d34178d392d7eb", size = 7198058, upload-time = "2026-02-06T09:54:42.389Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b2/40d43c91ae9cd667edc960135f9f08e58faa1576dc95af29f66ec912985f/grpcio-1.78.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ff870aebe9a93a85283837801d35cd5f8814fe2ad01e606861a7fb47c762a2b7", size = 6727212, upload-time = "2026-02-06T09:54:44.91Z" }, + { url = "https://files.pythonhosted.org/packages/ed/88/9da42eed498f0efcfcd9156e48ae63c0cde3bea398a16c99fb5198c885b6/grpcio-1.78.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:391e93548644e6b2726f1bb84ed60048d4bcc424ce5e4af0843d28ca0b754fec", size = 7300845, upload-time = "2026-02-06T09:54:47.562Z" }, + { url = "https://files.pythonhosted.org/packages/23/3f/1c66b7b1b19a8828890e37868411a6e6925df5a9030bfa87ab318f34095d/grpcio-1.78.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:df2c8f3141f7cbd112a6ebbd760290b5849cda01884554f7c67acc14e7b1758a", size = 8284605, upload-time = "2026-02-06T09:54:50.475Z" }, + { url = "https://files.pythonhosted.org/packages/94/c4/ca1bd87394f7b033e88525384b4d1e269e8424ab441ea2fba1a0c5b50986/grpcio-1.78.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd8cb8026e5f5b50498a3c4f196f57f9db344dad829ffae16b82e4fdbaea2813", size = 7726672, upload-time = "2026-02-06T09:54:53.11Z" }, + { url = "https://files.pythonhosted.org/packages/41/09/f16e487d4cc65ccaf670f6ebdd1a17566b965c74fc3d93999d3b2821e052/grpcio-1.78.0-cp310-cp310-win32.whl", hash = "sha256:f8dff3d9777e5d2703a962ee5c286c239bf0ba173877cc68dc02c17d042e29de", size = 4076715, upload-time = "2026-02-06T09:54:55.549Z" }, + { url = "https://files.pythonhosted.org/packages/2a/32/4ce60d94e242725fd3bcc5673c04502c82a8e87b21ea411a63992dc39f8f/grpcio-1.78.0-cp310-cp310-win_amd64.whl", hash = "sha256:94f95cf5d532d0e717eed4fc1810e8e6eded04621342ec54c89a7c2f14b581bf", size = 4799157, upload-time = "2026-02-06T09:54:59.838Z" }, + { url = "https://files.pythonhosted.org/packages/86/c7/d0b780a29b0837bf4ca9580904dfb275c1fc321ded7897d620af7047ec57/grpcio-1.78.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2777b783f6c13b92bd7b716667452c329eefd646bfb3f2e9dabea2e05dbd34f6", size = 5951525, upload-time = "2026-02-06T09:55:01.989Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b1/96920bf2ee61df85a9503cb6f733fe711c0ff321a5a697d791b075673281/grpcio-1.78.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:9dca934f24c732750389ce49d638069c3892ad065df86cb465b3fa3012b70c9e", size = 11830418, upload-time = "2026-02-06T09:55:04.462Z" }, + { url = "https://files.pythonhosted.org/packages/83/0c/7c1528f098aeb75a97de2bae18c530f56959fb7ad6c882db45d9884d6edc/grpcio-1.78.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:459ab414b35f4496138d0ecd735fed26f1318af5e52cb1efbc82a09f0d5aa911", size = 6524477, upload-time = "2026-02-06T09:55:07.111Z" }, + { url = "https://files.pythonhosted.org/packages/8d/52/e7c1f3688f949058e19a011c4e0dec973da3d0ae5e033909677f967ae1f4/grpcio-1.78.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:082653eecbdf290e6e3e2c276ab2c54b9e7c299e07f4221872380312d8cf395e", size = 7198266, upload-time = "2026-02-06T09:55:10.016Z" }, + { url = "https://files.pythonhosted.org/packages/e5/61/8ac32517c1e856677282c34f2e7812d6c328fa02b8f4067ab80e77fdc9c9/grpcio-1.78.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85f93781028ec63f383f6bc90db785a016319c561cc11151fbb7b34e0d012303", size = 6730552, upload-time = "2026-02-06T09:55:12.207Z" }, + { url = "https://files.pythonhosted.org/packages/bd/98/b8ee0158199250220734f620b12e4a345955ac7329cfd908d0bf0fda77f0/grpcio-1.78.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f12857d24d98441af6a1d5c87442d624411db486f7ba12550b07788f74b67b04", size = 7304296, upload-time = "2026-02-06T09:55:15.044Z" }, + { url = "https://files.pythonhosted.org/packages/bd/0f/7b72762e0d8840b58032a56fdbd02b78fc645b9fa993d71abf04edbc54f4/grpcio-1.78.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5397fff416b79e4b284959642a4e95ac4b0f1ece82c9993658e0e477d40551ec", size = 8288298, upload-time = "2026-02-06T09:55:17.276Z" }, + { url = "https://files.pythonhosted.org/packages/24/ae/ae4ce56bc5bb5caa3a486d60f5f6083ac3469228faa734362487176c15c5/grpcio-1.78.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbe6e89c7ffb48518384068321621b2a69cab509f58e40e4399fdd378fa6d074", size = 7730953, upload-time = "2026-02-06T09:55:19.545Z" }, + { url = "https://files.pythonhosted.org/packages/b5/6e/8052e3a28eb6a820c372b2eb4b5e32d195c661e137d3eca94d534a4cfd8a/grpcio-1.78.0-cp311-cp311-win32.whl", hash = "sha256:6092beabe1966a3229f599d7088b38dfc8ffa1608b5b5cdda31e591e6500f856", size = 4076503, upload-time = "2026-02-06T09:55:21.521Z" }, + { url = "https://files.pythonhosted.org/packages/08/62/f22c98c5265dfad327251fa2f840b591b1df5f5e15d88b19c18c86965b27/grpcio-1.78.0-cp311-cp311-win_amd64.whl", hash = "sha256:1afa62af6e23f88629f2b29ec9e52ec7c65a7176c1e0a83292b93c76ca882558", size = 4799767, upload-time = "2026-02-06T09:55:24.107Z" }, + { url = "https://files.pythonhosted.org/packages/4e/f4/7384ed0178203d6074446b3c4f46c90a22ddf7ae0b3aee521627f54cfc2a/grpcio-1.78.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:f9ab915a267fc47c7e88c387a3a28325b58c898e23d4995f765728f4e3dedb97", size = 5913985, upload-time = "2026-02-06T09:55:26.832Z" }, + { url = "https://files.pythonhosted.org/packages/81/ed/be1caa25f06594463f685b3790b320f18aea49b33166f4141bfdc2bfb236/grpcio-1.78.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3f8904a8165ab21e07e58bf3e30a73f4dffc7a1e0dbc32d51c61b5360d26f43e", size = 11811853, upload-time = "2026-02-06T09:55:29.224Z" }, + { url = "https://files.pythonhosted.org/packages/24/a7/f06d151afc4e64b7e3cc3e872d331d011c279aaab02831e40a81c691fb65/grpcio-1.78.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:859b13906ce098c0b493af92142ad051bf64c7870fa58a123911c88606714996", size = 6475766, upload-time = "2026-02-06T09:55:31.825Z" }, + { url = "https://files.pythonhosted.org/packages/8a/a8/4482922da832ec0082d0f2cc3a10976d84a7424707f25780b82814aafc0a/grpcio-1.78.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b2342d87af32790f934a79c3112641e7b27d63c261b8b4395350dad43eff1dc7", size = 7170027, upload-time = "2026-02-06T09:55:34.7Z" }, + { url = "https://files.pythonhosted.org/packages/54/bf/f4a3b9693e35d25b24b0b39fa46d7d8a3c439e0a3036c3451764678fec20/grpcio-1.78.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12a771591ae40bc65ba67048fa52ef4f0e6db8279e595fd349f9dfddeef571f9", size = 6690766, upload-time = "2026-02-06T09:55:36.902Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b9/521875265cc99fe5ad4c5a17010018085cae2810a928bf15ebe7d8bcd9cc/grpcio-1.78.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:185dea0d5260cbb2d224c507bf2a5444d5abbb1fa3594c1ed7e4c709d5eb8383", size = 7266161, upload-time = "2026-02-06T09:55:39.824Z" }, + { url = "https://files.pythonhosted.org/packages/05/86/296a82844fd40a4ad4a95f100b55044b4f817dece732bf686aea1a284147/grpcio-1.78.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:51b13f9aed9d59ee389ad666b8c2214cc87b5de258fa712f9ab05f922e3896c6", size = 8253303, upload-time = "2026-02-06T09:55:42.353Z" }, + { url = "https://files.pythonhosted.org/packages/f3/e4/ea3c0caf5468537f27ad5aab92b681ed7cc0ef5f8c9196d3fd42c8c2286b/grpcio-1.78.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fd5f135b1bd58ab088930b3c613455796dfa0393626a6972663ccdda5b4ac6ce", size = 7698222, upload-time = "2026-02-06T09:55:44.629Z" }, + { url = "https://files.pythonhosted.org/packages/d7/47/7f05f81e4bb6b831e93271fb12fd52ba7b319b5402cbc101d588f435df00/grpcio-1.78.0-cp312-cp312-win32.whl", hash = "sha256:94309f498bcc07e5a7d16089ab984d42ad96af1d94b5a4eb966a266d9fcabf68", size = 4066123, upload-time = "2026-02-06T09:55:47.644Z" }, + { url = "https://files.pythonhosted.org/packages/ad/e7/d6914822c88aa2974dbbd10903d801a28a19ce9cd8bad7e694cbbcf61528/grpcio-1.78.0-cp312-cp312-win_amd64.whl", hash = "sha256:9566fe4ababbb2610c39190791e5b829869351d14369603702e890ef3ad2d06e", size = 4797657, upload-time = "2026-02-06T09:55:49.86Z" }, +] + [[package]] name = "h11" version = "0.16.0" @@ -844,6 +1507,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, ] +[[package]] +name = "hf-xet" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/6e/0f11bacf08a67f7fb5ee09740f2ca54163863b07b70d579356e9222ce5d8/hf_xet-1.2.0.tar.gz", hash = "sha256:a8c27070ca547293b6890c4bf389f713f80e8c478631432962bb7f4bc0bd7d7f", size = 506020, upload-time = "2025-10-24T19:04:32.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/2d/22338486473df5923a9ab7107d375dbef9173c338ebef5098ef593d2b560/hf_xet-1.2.0-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:46740d4ac024a7ca9b22bebf77460ff43332868b661186a8e46c227fdae01848", size = 2866099, upload-time = "2025-10-24T19:04:15.366Z" }, + { url = "https://files.pythonhosted.org/packages/7f/8c/c5becfa53234299bc2210ba314eaaae36c2875e0045809b82e40a9544f0c/hf_xet-1.2.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:27df617a076420d8845bea087f59303da8be17ed7ec0cd7ee3b9b9f579dff0e4", size = 2722178, upload-time = "2025-10-24T19:04:13.695Z" }, + { url = "https://files.pythonhosted.org/packages/9a/92/cf3ab0b652b082e66876d08da57fcc6fa2f0e6c70dfbbafbd470bb73eb47/hf_xet-1.2.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3651fd5bfe0281951b988c0facbe726aa5e347b103a675f49a3fa8144c7968fd", size = 3320214, upload-time = "2025-10-24T19:04:03.596Z" }, + { url = "https://files.pythonhosted.org/packages/46/92/3f7ec4a1b6a65bf45b059b6d4a5d38988f63e193056de2f420137e3c3244/hf_xet-1.2.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d06fa97c8562fb3ee7a378dd9b51e343bc5bc8190254202c9771029152f5e08c", size = 3229054, upload-time = "2025-10-24T19:04:01.949Z" }, + { url = "https://files.pythonhosted.org/packages/0b/dd/7ac658d54b9fb7999a0ccb07ad863b413cbaf5cf172f48ebcd9497ec7263/hf_xet-1.2.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:4c1428c9ae73ec0939410ec73023c4f842927f39db09b063b9482dac5a3bb737", size = 3413812, upload-time = "2025-10-24T19:04:24.585Z" }, + { url = "https://files.pythonhosted.org/packages/92/68/89ac4e5b12a9ff6286a12174c8538a5930e2ed662091dd2572bbe0a18c8a/hf_xet-1.2.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a55558084c16b09b5ed32ab9ed38421e2d87cf3f1f89815764d1177081b99865", size = 3508920, upload-time = "2025-10-24T19:04:26.927Z" }, + { url = "https://files.pythonhosted.org/packages/cb/44/870d44b30e1dcfb6a65932e3e1506c103a8a5aea9103c337e7a53180322c/hf_xet-1.2.0-cp37-abi3-win_amd64.whl", hash = "sha256:e6584a52253f72c9f52f9e549d5895ca7a471608495c4ecaa6cc73dba2b24d69", size = 2905735, upload-time = "2025-10-24T19:04:35.928Z" }, +] + [[package]] name = "highspy" version = "1.11.0" @@ -901,18 +1579,47 @@ wheels = [ [[package]] name = "httpx" -version = "0.27.2" +version = "0.28.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "certifi" }, { name = "httpcore" }, { name = "idna" }, - { name = "sniffio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/78/82/08f8c936781f67d9e6b9eeb8a0c8b4e406136ea4c3d1f89a5db71d42e0e6/httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2", size = 144189, upload-time = "2024-08-27T12:54:01.334Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/56/95/9377bcb415797e44274b51d46e3249eba641711cf3348050f76ee7b15ffc/httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0", size = 76395, upload-time = "2024-08-27T12:53:59.653Z" }, + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "httpx-sse" +version = "0.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, +] + +[[package]] +name = "huggingface-hub" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "fsspec" }, + { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, + { name = "httpx" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "shellingham" }, + { name = "tqdm" }, + { name = "typer-slim" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c4/fc/eb9bc06130e8bbda6a616e1b80a7aa127681c448d6b49806f61db2670b61/huggingface_hub-1.4.1.tar.gz", hash = "sha256:b41131ec35e631e7383ab26d6146b8d8972abc8b6309b963b306fbcca87f5ed5", size = 642156, upload-time = "2026-02-06T09:20:03.013Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/ae/2f6d96b4e6c5478d87d606a1934b5d436c4a2bce6bb7c6fdece891c128e3/huggingface_hub-1.4.1-py3-none-any.whl", hash = "sha256:9931d075fb7a79af5abc487106414ec5fba2c0ae86104c0c62fd6cae38873d18", size = 553326, upload-time = "2026-02-06T09:20:00.728Z" }, ] [[package]] @@ -933,13 +1640,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, ] +[[package]] +name = "importlib-metadata" +version = "8.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, +] + [[package]] name = "iniconfig" version = "2.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, +] + +[[package]] +name = "invoke" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/de/bd/b461d3424a24c80490313fd77feeb666ca4f6a28c7e72713e3d9095719b4/invoke-2.2.1.tar.gz", hash = "sha256:515bf49b4a48932b79b024590348da22f39c4942dff991ad1fb8b8baea1be707", size = 304762, upload-time = "2025-10-11T00:36:35.172Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, + { url = "https://files.pythonhosted.org/packages/32/4b/b99e37f88336009971405cbb7630610322ed6fbfa31e1d7ab3fbf3049a2d/invoke-2.2.1-py3-none-any.whl", hash = "sha256:2413bc441b376e5cd3f55bb5d364f973ad8bdd7bf87e53c79de3c11bf3feecc8", size = 160287, upload-time = "2025-10-11T00:36:33.703Z" }, ] [[package]] @@ -1059,6 +1787,42 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, ] +[[package]] +name = "jaraco-classes" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" }, +] + +[[package]] +name = "jaraco-context" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "backports-tarfile", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/9c/a788f5bb29c61e456b8ee52ce76dbdd32fd72cd73dd67bc95f42c7a8d13c/jaraco_context-6.1.0.tar.gz", hash = "sha256:129a341b0a85a7db7879e22acd66902fda67882db771754574338898b2d5d86f", size = 15850, upload-time = "2026-01-13T02:53:53.847Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/48/aa685dbf1024c7bd82bede569e3a85f82c32fd3d79ba5fea578f0159571a/jaraco_context-6.1.0-py3-none-any.whl", hash = "sha256:a43b5ed85815223d0d3cfdb6d7ca0d2bc8946f28f30b6f3216bda070f68badda", size = 7065, upload-time = "2026-01-13T02:53:53.031Z" }, +] + +[[package]] +name = "jaraco-functools" +version = "4.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0f/27/056e0638a86749374d6f57d0b0db39f29509cce9313cf91bdc0ac4d91084/jaraco_functools-4.4.0.tar.gz", hash = "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb", size = 19943, upload-time = "2025-12-21T09:29:43.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl", hash = "sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176", size = 10481, upload-time = "2025-12-21T09:29:42.27Z" }, +] + [[package]] name = "jedi" version = "0.19.2" @@ -1071,6 +1835,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" }, ] +[[package]] +name = "jeepney" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" }, +] + [[package]] name = "jinja2" version = "3.1.6" @@ -1083,6 +1856,69 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] +[[package]] +name = "jiter" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/5e/4ec91646aee381d01cdb9974e30882c9cd3b8c5d1079d6b5ff4af522439a/jiter-0.13.0.tar.gz", hash = "sha256:f2839f9c2c7e2dffc1bc5929a510e14ce0a946be9365fd1219e7ef342dae14f4", size = 164847, upload-time = "2026-02-02T12:37:56.441Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/5a/41da76c5ea07bec1b0472b6b2fdb1b651074d504b19374d7e130e0cdfb25/jiter-0.13.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2ffc63785fd6c7977defe49b9824ae6ce2b2e2b77ce539bdaf006c26da06342e", size = 311164, upload-time = "2026-02-02T12:35:17.688Z" }, + { url = "https://files.pythonhosted.org/packages/40/cb/4a1bf994a3e869f0d39d10e11efb471b76d0ad70ecbfb591427a46c880c2/jiter-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4a638816427006c1e3f0013eb66d391d7a3acda99a7b0cf091eff4497ccea33a", size = 320296, upload-time = "2026-02-02T12:35:19.828Z" }, + { url = "https://files.pythonhosted.org/packages/09/82/acd71ca9b50ecebadc3979c541cd717cce2fe2bc86236f4fa597565d8f1a/jiter-0.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19928b5d1ce0ff8c1ee1b9bdef3b5bfc19e8304f1b904e436caf30bc15dc6cf5", size = 352742, upload-time = "2026-02-02T12:35:21.258Z" }, + { url = "https://files.pythonhosted.org/packages/71/03/d1fc996f3aecfd42eb70922edecfb6dd26421c874503e241153ad41df94f/jiter-0.13.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:309549b778b949d731a2f0e1594a3f805716be704a73bf3ad9a807eed5eb5721", size = 363145, upload-time = "2026-02-02T12:35:24.653Z" }, + { url = "https://files.pythonhosted.org/packages/f1/61/a30492366378cc7a93088858f8991acd7d959759fe6138c12a4644e58e81/jiter-0.13.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcdabaea26cb04e25df3103ce47f97466627999260290349a88c8136ecae0060", size = 487683, upload-time = "2026-02-02T12:35:26.162Z" }, + { url = "https://files.pythonhosted.org/packages/20/4e/4223cffa9dbbbc96ed821c5aeb6bca510848c72c02086d1ed3f1da3d58a7/jiter-0.13.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3a377af27b236abbf665a69b2bdd680e3b5a0bd2af825cd3b81245279a7606c", size = 373579, upload-time = "2026-02-02T12:35:27.582Z" }, + { url = "https://files.pythonhosted.org/packages/fe/c9/b0489a01329ab07a83812d9ebcffe7820a38163c6d9e7da644f926ff877c/jiter-0.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe49d3ff6db74321f144dff9addd4a5874d3105ac5ba7c5b77fac099cfae31ae", size = 362904, upload-time = "2026-02-02T12:35:28.925Z" }, + { url = "https://files.pythonhosted.org/packages/05/af/53e561352a44afcba9a9bc67ee1d320b05a370aed8df54eafe714c4e454d/jiter-0.13.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2113c17c9a67071b0f820733c0893ed1d467b5fcf4414068169e5c2cabddb1e2", size = 392380, upload-time = "2026-02-02T12:35:30.385Z" }, + { url = "https://files.pythonhosted.org/packages/76/2a/dd805c3afb8ed5b326c5ae49e725d1b1255b9754b1b77dbecdc621b20773/jiter-0.13.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ab1185ca5c8b9491b55ebf6c1e8866b8f68258612899693e24a92c5fdb9455d5", size = 517939, upload-time = "2026-02-02T12:35:31.865Z" }, + { url = "https://files.pythonhosted.org/packages/20/2a/7b67d76f55b8fe14c937e7640389612f05f9a4145fc28ae128aaa5e62257/jiter-0.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9621ca242547edc16400981ca3231e0c91c0c4c1ab8573a596cd9bb3575d5c2b", size = 551696, upload-time = "2026-02-02T12:35:33.306Z" }, + { url = "https://files.pythonhosted.org/packages/85/9c/57cdd64dac8f4c6ab8f994fe0eb04dc9fd1db102856a4458fcf8a99dfa62/jiter-0.13.0-cp310-cp310-win32.whl", hash = "sha256:a7637d92b1c9d7a771e8c56f445c7f84396d48f2e756e5978840ecba2fac0894", size = 204592, upload-time = "2026-02-02T12:35:34.58Z" }, + { url = "https://files.pythonhosted.org/packages/a7/38/f4f3ea5788b8a5bae7510a678cdc747eda0c45ffe534f9878ff37e7cf3b3/jiter-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c1b609e5cbd2f52bb74fb721515745b407df26d7b800458bd97cb3b972c29e7d", size = 206016, upload-time = "2026-02-02T12:35:36.435Z" }, + { url = "https://files.pythonhosted.org/packages/71/29/499f8c9eaa8a16751b1c0e45e6f5f1761d180da873d417996cc7bddc8eef/jiter-0.13.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ea026e70a9a28ebbdddcbcf0f1323128a8db66898a06eaad3a4e62d2f554d096", size = 311157, upload-time = "2026-02-02T12:35:37.758Z" }, + { url = "https://files.pythonhosted.org/packages/50/f6/566364c777d2ab450b92100bea11333c64c38d32caf8dc378b48e5b20c46/jiter-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66aa3e663840152d18cc8ff1e4faad3dd181373491b9cfdc6004b92198d67911", size = 319729, upload-time = "2026-02-02T12:35:39.246Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/560f13ec5e4f116d8ad2658781646cca91b617ae3b8758d4a5076b278f70/jiter-0.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3524798e70655ff19aec58c7d05adb1f074fecff62da857ea9be2b908b6d701", size = 354766, upload-time = "2026-02-02T12:35:40.662Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0d/061faffcfe94608cbc28a0d42a77a74222bdf5055ccdbe5fd2292b94f510/jiter-0.13.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec7e287d7fbd02cb6e22f9a00dd9c9cd504c40a61f2c61e7e1f9690a82726b4c", size = 362587, upload-time = "2026-02-02T12:35:42.025Z" }, + { url = "https://files.pythonhosted.org/packages/92/c9/c66a7864982fd38a9773ec6e932e0398d1262677b8c60faecd02ffb67bf3/jiter-0.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47455245307e4debf2ce6c6e65a717550a0244231240dcf3b8f7d64e4c2f22f4", size = 487537, upload-time = "2026-02-02T12:35:43.459Z" }, + { url = "https://files.pythonhosted.org/packages/6c/86/84eb4352cd3668f16d1a88929b5888a3fe0418ea8c1dfc2ad4e7bf6e069a/jiter-0.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ee9da221dca6e0429c2704c1b3655fe7b025204a71d4d9b73390c759d776d165", size = 373717, upload-time = "2026-02-02T12:35:44.928Z" }, + { url = "https://files.pythonhosted.org/packages/6e/09/9fe4c159358176f82d4390407a03f506a8659ed13ca3ac93a843402acecf/jiter-0.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24ab43126d5e05f3d53a36a8e11eb2f23304c6c1117844aaaf9a0aa5e40b5018", size = 362683, upload-time = "2026-02-02T12:35:46.636Z" }, + { url = "https://files.pythonhosted.org/packages/c9/5e/85f3ab9caca0c1d0897937d378b4a515cae9e119730563572361ea0c48ae/jiter-0.13.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9da38b4fedde4fb528c740c2564628fbab737166a0e73d6d46cb4bb5463ff411", size = 392345, upload-time = "2026-02-02T12:35:48.088Z" }, + { url = "https://files.pythonhosted.org/packages/12/4c/05b8629ad546191939e6f0c2f17e29f542a398f4a52fb987bc70b6d1eb8b/jiter-0.13.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0b34c519e17658ed88d5047999a93547f8889f3c1824120c26ad6be5f27b6cf5", size = 517775, upload-time = "2026-02-02T12:35:49.482Z" }, + { url = "https://files.pythonhosted.org/packages/4d/88/367ea2eb6bc582c7052e4baf5ddf57ebe5ab924a88e0e09830dfb585c02d/jiter-0.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2a6394e6af690d462310a86b53c47ad75ac8c21dc79f120714ea449979cb1d3", size = 551325, upload-time = "2026-02-02T12:35:51.104Z" }, + { url = "https://files.pythonhosted.org/packages/f3/12/fa377ffb94a2f28c41afaed093e0d70cfe512035d5ecb0cad0ae4792d35e/jiter-0.13.0-cp311-cp311-win32.whl", hash = "sha256:0f0c065695f616a27c920a56ad0d4fc46415ef8b806bf8fc1cacf25002bd24e1", size = 204709, upload-time = "2026-02-02T12:35:52.467Z" }, + { url = "https://files.pythonhosted.org/packages/cb/16/8e8203ce92f844dfcd3d9d6a5a7322c77077248dbb12da52d23193a839cd/jiter-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:0733312953b909688ae3c2d58d043aa040f9f1a6a75693defed7bc2cc4bf2654", size = 204560, upload-time = "2026-02-02T12:35:53.925Z" }, + { url = "https://files.pythonhosted.org/packages/44/26/97cc40663deb17b9e13c3a5cf29251788c271b18ee4d262c8f94798b8336/jiter-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:5d9b34ad56761b3bf0fbe8f7e55468704107608512350962d3317ffd7a4382d5", size = 189608, upload-time = "2026-02-02T12:35:55.304Z" }, + { url = "https://files.pythonhosted.org/packages/2e/30/7687e4f87086829955013ca12a9233523349767f69653ebc27036313def9/jiter-0.13.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0a2bd69fc1d902e89925fc34d1da51b2128019423d7b339a45d9e99c894e0663", size = 307958, upload-time = "2026-02-02T12:35:57.165Z" }, + { url = "https://files.pythonhosted.org/packages/c3/27/e57f9a783246ed95481e6749cc5002a8a767a73177a83c63ea71f0528b90/jiter-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f917a04240ef31898182f76a332f508f2cc4b57d2b4d7ad2dbfebbfe167eb505", size = 318597, upload-time = "2026-02-02T12:35:58.591Z" }, + { url = "https://files.pythonhosted.org/packages/cf/52/e5719a60ac5d4d7c5995461a94ad5ef962a37c8bf5b088390e6fad59b2ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e2b199f446d3e82246b4fd9236d7cb502dc2222b18698ba0d986d2fecc6152", size = 348821, upload-time = "2026-02-02T12:36:00.093Z" }, + { url = "https://files.pythonhosted.org/packages/61/db/c1efc32b8ba4c740ab3fc2d037d8753f67685f475e26b9d6536a4322bcdd/jiter-0.13.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04670992b576fa65bd056dbac0c39fe8bd67681c380cb2b48efa885711d9d726", size = 364163, upload-time = "2026-02-02T12:36:01.937Z" }, + { url = "https://files.pythonhosted.org/packages/55/8a/fb75556236047c8806995671a18e4a0ad646ed255276f51a20f32dceaeec/jiter-0.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a1aff1fbdb803a376d4d22a8f63f8e7ccbce0b4890c26cc7af9e501ab339ef0", size = 483709, upload-time = "2026-02-02T12:36:03.41Z" }, + { url = "https://files.pythonhosted.org/packages/7e/16/43512e6ee863875693a8e6f6d532e19d650779d6ba9a81593ae40a9088ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b3fb8c2053acaef8580809ac1d1f7481a0a0bdc012fd7f5d8b18fb696a5a089", size = 370480, upload-time = "2026-02-02T12:36:04.791Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4c/09b93e30e984a187bc8aaa3510e1ec8dcbdcd71ca05d2f56aac0492453aa/jiter-0.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdaba7d87e66f26a2c45d8cbadcbfc4bf7884182317907baf39cfe9775bb4d93", size = 360735, upload-time = "2026-02-02T12:36:06.994Z" }, + { url = "https://files.pythonhosted.org/packages/1a/1b/46c5e349019874ec5dfa508c14c37e29864ea108d376ae26d90bee238cd7/jiter-0.13.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b88d649135aca526da172e48083da915ec086b54e8e73a425ba50999468cc08", size = 391814, upload-time = "2026-02-02T12:36:08.368Z" }, + { url = "https://files.pythonhosted.org/packages/15/9e/26184760e85baee7162ad37b7912797d2077718476bf91517641c92b3639/jiter-0.13.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e404ea551d35438013c64b4f357b0474c7abf9f781c06d44fcaf7a14c69ff9e2", size = 513990, upload-time = "2026-02-02T12:36:09.993Z" }, + { url = "https://files.pythonhosted.org/packages/e9/34/2c9355247d6debad57a0a15e76ab1566ab799388042743656e566b3b7de1/jiter-0.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1f4748aad1b4a93c8bdd70f604d0f748cdc0e8744c5547798acfa52f10e79228", size = 548021, upload-time = "2026-02-02T12:36:11.376Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4a/9f2c23255d04a834398b9c2e0e665382116911dc4d06b795710503cdad25/jiter-0.13.0-cp312-cp312-win32.whl", hash = "sha256:0bf670e3b1445fc4d31612199f1744f67f889ee1bbae703c4b54dc097e5dd394", size = 203024, upload-time = "2026-02-02T12:36:12.682Z" }, + { url = "https://files.pythonhosted.org/packages/09/ee/f0ae675a957ae5a8f160be3e87acea6b11dc7b89f6b7ab057e77b2d2b13a/jiter-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:15db60e121e11fe186c0b15236bd5d18381b9ddacdcf4e659feb96fc6c969c92", size = 205424, upload-time = "2026-02-02T12:36:13.93Z" }, + { url = "https://files.pythonhosted.org/packages/1b/02/ae611edf913d3cbf02c97cdb90374af2082c48d7190d74c1111dde08bcdd/jiter-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:41f92313d17989102f3cb5dd533a02787cdb99454d494344b0361355da52fcb9", size = 186818, upload-time = "2026-02-02T12:36:15.308Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/3c29819a27178d0e461a8571fb63c6ae38be6dc36b78b3ec2876bbd6a910/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b1cbfa133241d0e6bdab48dcdc2604e8ba81512f6bbd68ec3e8e1357dd3c316c", size = 307016, upload-time = "2026-02-02T12:37:42.755Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ae/60993e4b07b1ac5ebe46da7aa99fdbb802eb986c38d26e3883ac0125c4e0/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:db367d8be9fad6e8ebbac4a7578b7af562e506211036cba2c06c3b998603c3d2", size = 305024, upload-time = "2026-02-02T12:37:44.774Z" }, + { url = "https://files.pythonhosted.org/packages/77/fa/2227e590e9cf98803db2811f172b2d6460a21539ab73006f251c66f44b14/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45f6f8efb2f3b0603092401dc2df79fa89ccbc027aaba4174d2d4133ed661434", size = 339337, upload-time = "2026-02-02T12:37:46.668Z" }, + { url = "https://files.pythonhosted.org/packages/2d/92/015173281f7eb96c0ef580c997da8ef50870d4f7f4c9e03c845a1d62ae04/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:597245258e6ad085d064780abfb23a284d418d3e61c57362d9449c6c7317ee2d", size = 346395, upload-time = "2026-02-02T12:37:48.09Z" }, + { url = "https://files.pythonhosted.org/packages/80/60/e50fa45dd7e2eae049f0ce964663849e897300433921198aef94b6ffa23a/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:3d744a6061afba08dd7ae375dcde870cffb14429b7477e10f67e9e6d68772a0a", size = 305169, upload-time = "2026-02-02T12:37:50.376Z" }, + { url = "https://files.pythonhosted.org/packages/d2/73/a009f41c5eed71c49bec53036c4b33555afcdee70682a18c6f66e396c039/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:ff732bd0a0e778f43d5009840f20b935e79087b4dc65bd36f1cd0f9b04b8ff7f", size = 303808, upload-time = "2026-02-02T12:37:52.092Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/528b439290763bff3d939268085d03382471b442f212dca4ff5f12802d43/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab44b178f7981fcaea7e0a5df20e773c663d06ffda0198f1a524e91b2fde7e59", size = 337384, upload-time = "2026-02-02T12:37:53.582Z" }, + { url = "https://files.pythonhosted.org/packages/67/8a/a342b2f0251f3dac4ca17618265d93bf244a2a4d089126e81e4c1056ac50/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb00b6d26db67a05fe3e12c76edc75f32077fb51deed13822dc648fa373bc19", size = 343768, upload-time = "2026-02-02T12:37:55.055Z" }, +] + +[[package]] +name = "jmespath" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/59/322338183ecda247fb5d1763a6cbe46eff7222eaeebafd9fa65d4bf5cb11/jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d", size = 27377, upload-time = "2026-01-22T16:35:26.279Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" }, +] + [[package]] name = "joblib" version = "1.5.1" @@ -1110,6 +1946,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, ] +[[package]] +name = "jsonref" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/0d/c1f3277e90ccdb50d33ed5ba1ec5b3f0a242ed8c1b1a85d3afeb68464dca/jsonref-1.1.0.tar.gz", hash = "sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552", size = 8814, upload-time = "2023-01-16T16:10:04.455Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl", hash = "sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9", size = 9425, upload-time = "2023-01-16T16:10:02.255Z" }, +] + [[package]] name = "jsonschema" version = "4.25.0" @@ -1138,6 +1983,21 @@ format-nongpl = [ { name = "webcolors" }, ] +[[package]] +name = "jsonschema-path" +version = "0.3.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pathable" }, + { name = "pyyaml" }, + { name = "referencing" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6e/45/41ebc679c2a4fced6a722f624c18d658dee42612b83ea24c1caf7c0eb3a8/jsonschema_path-0.3.4.tar.gz", hash = "sha256:8365356039f16cc65fddffafda5f58766e34bebab7d6d105616ab52bc4297001", size = 11159, upload-time = "2025-01-24T14:33:16.547Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/58/3485da8cb93d2f393bce453adeef16896751f14ba3e2024bc21dc9597646/jsonschema_path-0.3.4-py3-none-any.whl", hash = "sha256:f502191fdc2b22050f9a81c9237be9d27145b9001c55842bece5e94e382e52f8", size = 14810, upload-time = "2025-01-24T14:33:14.652Z" }, +] + [[package]] name = "jsonschema-specifications" version = "2025.4.1" @@ -1352,6 +2212,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/43/6a/ca128561b22b60bd5a0c4ea26649e68c8556b82bc70a0c396eebc977fe86/jupyterlab_widgets-3.0.15-py3-none-any.whl", hash = "sha256:d59023d7d7ef71400d51e6fee9a88867f6e65e10a4201605d2d7f3e8f012a31c", size = 216571, upload-time = "2025-05-05T12:32:29.534Z" }, ] +[[package]] +name = "keyring" +version = "25.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata", marker = "python_full_version < '3.12'" }, + { name = "jaraco-classes" }, + { name = "jaraco-context" }, + { name = "jaraco-functools" }, + { name = "jeepney", marker = "sys_platform == 'linux'" }, + { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, + { name = "secretstorage", marker = "sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, +] + [[package]] name = "kiwisolver" version = "1.4.8" @@ -1471,6 +2349,39 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/6b/d139535d7590a1bba1ceb68751bef22fadaa5b815bbdf0e858e3875726b2/llvmlite-0.46.0-cp312-cp312-win_amd64.whl", hash = "sha256:398b39db462c39563a97b912d4f2866cd37cba60537975a09679b28fbbc0fb38", size = 38138940, upload-time = "2025-12-08T18:15:10.162Z" }, ] +[[package]] +name = "logfire" +version = "4.25.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "executing" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-sdk" }, + { name = "protobuf" }, + { name = "rich" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d8/43/374fc0e6ebe95209414cf743cc693f4ff2ad391fd0712445ed1f63245395/logfire-4.25.0.tar.gz", hash = "sha256:f9a6bf6d40fd3e2c2a86a364617246cadecbde620b4ecccb17c499140f1ebc13", size = 1049745, upload-time = "2026-02-19T15:27:28Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/cc/a3eb3a5fff27a6bfe2f626624c7c781322151f3228d4ea98c31003dc2d4c/logfire-4.25.0-py3-none-any.whl", hash = "sha256:1865b832e08c58a3fb0d21b24460ee9c6cbeff12db6038c508fb966699ce81c2", size = 298186, upload-time = "2026-02-19T15:27:23.324Z" }, +] + +[package.optional-dependencies] +httpx = [ + { name = "opentelemetry-instrumentation-httpx" }, +] + +[[package]] +name = "logfire-api" +version = "4.25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/5c/026cec30d85394aec8f5f12d70edbe2d706837bc9a411bd71a542cedae50/logfire_api-4.25.0.tar.gz", hash = "sha256:7562d5adfe3987291039dddb21947c86cb9d832d068c87d9aa23db86ef07095b", size = 75853, upload-time = "2026-02-19T15:27:29.518Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/39/83414c0fadb4f11f90e6b80b631aa79f62a605664f0c4693e2ebc7ee73f3/logfire_api-4.25.0-py3-none-any.whl", hash = "sha256:0d607eb09ef5426e26f376ff277a8d401bc5b7b4178ea66db404e13c368494cf", size = 120473, upload-time = "2026-02-19T15:27:25.832Z" }, +] + [[package]] name = "lxml" version = "5.4.0" @@ -1545,6 +2456,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/96/2b/34cc11786bc00d0f04d0f5fdc3a2b1ae0b6239eef72d3d345805f9ad92a1/markdown-3.8.2-py3-none-any.whl", hash = "sha256:5c83764dbd4e00bdd94d85a19b8d55ccca20fe35b2e678a1422b380324dd5f24", size = 106827, upload-time = "2025-06-19T17:12:42.994Z" }, ] +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + [[package]] name = "markupsafe" version = "3.0.2" @@ -1636,6 +2559,40 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca", size = 9899, upload-time = "2024-04-15T13:44:43.265Z" }, ] +[[package]] +name = "mcp" +version = "1.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "pyjwt", extra = ["crypto"] }, + { name = "python-multipart" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "sse-starlette" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, + { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/6d/62e76bbb8144d6ed86e202b5edd8a4cb631e7c8130f3f4893c3f90262b10/mcp-1.26.0.tar.gz", hash = "sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66", size = 608005, upload-time = "2026-01-24T19:40:32.468Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/d9/eaa1f80170d2b7c5ba23f3b59f766f3a0bb41155fbc32a69adfa1adaaef9/mcp-1.26.0-py3-none-any.whl", hash = "sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca", size = 233615, upload-time = "2026-01-24T19:40:30.652Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + [[package]] name = "mergedeep" version = "1.3.4" @@ -1645,6 +2602,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" }, ] +[[package]] +name = "mistralai" +version = "1.12.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eval-type-backport" }, + { name = "httpx" }, + { name = "invoke" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, + { name = "opentelemetry-sdk" }, + { name = "pydantic" }, + { name = "python-dateutil" }, + { name = "pyyaml" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/ad/3d3b17a768f641ab428bbe7c4a75283db029737778d4f56cb4a9145ba54f/mistralai-1.12.3.tar.gz", hash = "sha256:d59a788e82c16fd7d340f9f2e722ed0897fe15ccce797278b836d65fa671ef6e", size = 242961, upload-time = "2026-02-17T15:41:29Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/3c/d17250578195b90b0a7f2500c4d587996c9b79470dbcfe7fb9d24feb9d1b/mistralai-1.12.3-py3-none-any.whl", hash = "sha256:e164e070011dd7759ad5d969c44359939d7d73f7fec787667317b7e81ffc5a8b", size = 502976, upload-time = "2026-02-17T15:41:30.648Z" }, +] + [[package]] name = "mistune" version = "3.1.3" @@ -1790,6 +2768,81 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3b/dd/a24ee3de56954bfafb6ede7cd63c2413bb842cc48eb45e41c43a05a33074/mkdocstrings_python-1.16.12-py3-none-any.whl", hash = "sha256:22ded3a63b3d823d57457a70ff9860d5a4de9e8b1e482876fc9baabaf6f5f374", size = 124287, upload-time = "2025-06-03T12:52:47.819Z" }, ] +[[package]] +name = "more-itertools" +version = "10.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ea/5d/38b681d3fce7a266dd9ab73c66959406d565b3e85f21d5e66e1181d93721/more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd", size = 137431, upload-time = "2025-09-02T15:23:11.018Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" }, +] + +[[package]] +name = "multidict" +version = "6.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1a/c2/c2d94cbe6ac1753f3fc980da97b3d930efe1da3af3c9f5125354436c073d/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", size = 102010, upload-time = "2026-01-26T02:46:45.979Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/0b/19348d4c98980c4851d2f943f8ebafdece2ae7ef737adcfa5994ce8e5f10/multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5", size = 77176, upload-time = "2026-01-26T02:42:59.784Z" }, + { url = "https://files.pythonhosted.org/packages/ef/04/9de3f8077852e3d438215c81e9b691244532d2e05b4270e89ce67b7d103c/multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8", size = 44996, upload-time = "2026-01-26T02:43:01.674Z" }, + { url = "https://files.pythonhosted.org/packages/31/5c/08c7f7fe311f32e83f7621cd3f99d805f45519cd06fafb247628b861da7d/multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872", size = 44631, upload-time = "2026-01-26T02:43:03.169Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7f/0e3b1390ae772f27501199996b94b52ceeb64fe6f9120a32c6c3f6b781be/multidict-6.7.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991", size = 242561, upload-time = "2026-01-26T02:43:04.733Z" }, + { url = "https://files.pythonhosted.org/packages/dd/f4/8719f4f167586af317b69dd3e90f913416c91ca610cac79a45c53f590312/multidict-6.7.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03", size = 242223, upload-time = "2026-01-26T02:43:06.695Z" }, + { url = "https://files.pythonhosted.org/packages/47/ab/7c36164cce64a6ad19c6d9a85377b7178ecf3b89f8fd589c73381a5eedfd/multidict-6.7.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981", size = 222322, upload-time = "2026-01-26T02:43:08.472Z" }, + { url = "https://files.pythonhosted.org/packages/f5/79/a25add6fb38035b5337bc5734f296d9afc99163403bbcf56d4170f97eb62/multidict-6.7.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6", size = 254005, upload-time = "2026-01-26T02:43:10.127Z" }, + { url = "https://files.pythonhosted.org/packages/4a/7b/64a87cf98e12f756fc8bd444b001232ffff2be37288f018ad0d3f0aae931/multidict-6.7.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190", size = 251173, upload-time = "2026-01-26T02:43:11.731Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ac/b605473de2bb404e742f2cc3583d12aedb2352a70e49ae8fce455b50c5aa/multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92", size = 243273, upload-time = "2026-01-26T02:43:13.063Z" }, + { url = "https://files.pythonhosted.org/packages/03/65/11492d6a0e259783720f3bc1d9ea55579a76f1407e31ed44045c99542004/multidict-6.7.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee", size = 238956, upload-time = "2026-01-26T02:43:14.843Z" }, + { url = "https://files.pythonhosted.org/packages/5f/a7/7ee591302af64e7c196fb63fe856c788993c1372df765102bd0448e7e165/multidict-6.7.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2", size = 233477, upload-time = "2026-01-26T02:43:16.025Z" }, + { url = "https://files.pythonhosted.org/packages/9c/99/c109962d58756c35fd9992fed7f2355303846ea2ff054bb5f5e9d6b888de/multidict-6.7.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568", size = 243615, upload-time = "2026-01-26T02:43:17.84Z" }, + { url = "https://files.pythonhosted.org/packages/d5/5f/1973e7c771c86e93dcfe1c9cc55a5481b610f6614acfc28c0d326fe6bfad/multidict-6.7.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40", size = 249930, upload-time = "2026-01-26T02:43:19.06Z" }, + { url = "https://files.pythonhosted.org/packages/5d/a5/f170fc2268c3243853580203378cd522446b2df632061e0a5409817854c7/multidict-6.7.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962", size = 243807, upload-time = "2026-01-26T02:43:20.286Z" }, + { url = "https://files.pythonhosted.org/packages/de/01/73856fab6d125e5bc652c3986b90e8699a95e84b48d72f39ade6c0e74a8c/multidict-6.7.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505", size = 239103, upload-time = "2026-01-26T02:43:21.508Z" }, + { url = "https://files.pythonhosted.org/packages/e7/46/f1220bd9944d8aa40d8ccff100eeeee19b505b857b6f603d6078cb5315b0/multidict-6.7.1-cp310-cp310-win32.whl", hash = "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122", size = 41416, upload-time = "2026-01-26T02:43:22.703Z" }, + { url = "https://files.pythonhosted.org/packages/68/00/9b38e272a770303692fc406c36e1a4c740f401522d5787691eb38a8925a8/multidict-6.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df", size = 46022, upload-time = "2026-01-26T02:43:23.77Z" }, + { url = "https://files.pythonhosted.org/packages/64/65/d8d42490c02ee07b6bbe00f7190d70bb4738b3cce7629aaf9f213ef730dd/multidict-6.7.1-cp310-cp310-win_arm64.whl", hash = "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db", size = 43238, upload-time = "2026-01-26T02:43:24.882Z" }, + { url = "https://files.pythonhosted.org/packages/ce/f1/a90635c4f88fb913fbf4ce660b83b7445b7a02615bda034b2f8eb38fd597/multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d", size = 76626, upload-time = "2026-01-26T02:43:26.485Z" }, + { url = "https://files.pythonhosted.org/packages/a6/9b/267e64eaf6fc637a15b35f5de31a566634a2740f97d8d094a69d34f524a4/multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e", size = 44706, upload-time = "2026-01-26T02:43:27.607Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a4/d45caf2b97b035c57267791ecfaafbd59c68212004b3842830954bb4b02e/multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855", size = 44356, upload-time = "2026-01-26T02:43:28.661Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d2/0a36c8473f0cbaeadd5db6c8b72d15bbceeec275807772bfcd059bef487d/multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3", size = 244355, upload-time = "2026-01-26T02:43:31.165Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/8c65be997fd7dd311b7d39c7b6e71a0cb449bad093761481eccbbe4b42a2/multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e", size = 246433, upload-time = "2026-01-26T02:43:32.581Z" }, + { url = "https://files.pythonhosted.org/packages/01/fb/4dbd7e848d2799c6a026ec88ad39cf2b8416aa167fcc903baa55ecaa045c/multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a", size = 225376, upload-time = "2026-01-26T02:43:34.417Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8a/4a3a6341eac3830f6053062f8fbc9a9e54407c80755b3f05bc427295c2d0/multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8", size = 257365, upload-time = "2026-01-26T02:43:35.741Z" }, + { url = "https://files.pythonhosted.org/packages/f7/a2/dd575a69c1aa206e12d27d0770cdf9b92434b48a9ef0cd0d1afdecaa93c4/multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0", size = 254747, upload-time = "2026-01-26T02:43:36.976Z" }, + { url = "https://files.pythonhosted.org/packages/5a/56/21b27c560c13822ed93133f08aa6372c53a8e067f11fbed37b4adcdac922/multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144", size = 246293, upload-time = "2026-01-26T02:43:38.258Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/23466059dc3854763423d0ad6c0f3683a379d97673b1b89ec33826e46728/multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49", size = 242962, upload-time = "2026-01-26T02:43:40.034Z" }, + { url = "https://files.pythonhosted.org/packages/1f/67/51dd754a3524d685958001e8fa20a0f5f90a6a856e0a9dcabff69be3dbb7/multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71", size = 237360, upload-time = "2026-01-26T02:43:41.752Z" }, + { url = "https://files.pythonhosted.org/packages/64/3f/036dfc8c174934d4b55d86ff4f978e558b0e585cef70cfc1ad01adc6bf18/multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3", size = 245940, upload-time = "2026-01-26T02:43:43.042Z" }, + { url = "https://files.pythonhosted.org/packages/3d/20/6214d3c105928ebc353a1c644a6ef1408bc5794fcb4f170bb524a3c16311/multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c", size = 253502, upload-time = "2026-01-26T02:43:44.371Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e2/c653bc4ae1be70a0f836b82172d643fcf1dade042ba2676ab08ec08bff0f/multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0", size = 247065, upload-time = "2026-01-26T02:43:45.745Z" }, + { url = "https://files.pythonhosted.org/packages/c8/11/a854b4154cd3bd8b1fd375e8a8ca9d73be37610c361543d56f764109509b/multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa", size = 241870, upload-time = "2026-01-26T02:43:47.054Z" }, + { url = "https://files.pythonhosted.org/packages/13/bf/9676c0392309b5fdae322333d22a829715b570edb9baa8016a517b55b558/multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a", size = 41302, upload-time = "2026-01-26T02:43:48.753Z" }, + { url = "https://files.pythonhosted.org/packages/c9/68/f16a3a8ba6f7b6dc92a1f19669c0810bd2c43fc5a02da13b1cbf8e253845/multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b", size = 45981, upload-time = "2026-01-26T02:43:49.921Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/9dd5305253fa00cd3c7555dbef69d5bf4133debc53b87ab8d6a44d411665/multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6", size = 43159, upload-time = "2026-01-26T02:43:51.635Z" }, + { url = "https://files.pythonhosted.org/packages/8d/9c/f20e0e2cf80e4b2e4b1c365bf5fe104ee633c751a724246262db8f1a0b13/multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172", size = 76893, upload-time = "2026-01-26T02:43:52.754Z" }, + { url = "https://files.pythonhosted.org/packages/fe/cf/18ef143a81610136d3da8193da9d80bfe1cb548a1e2d1c775f26b23d024a/multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd", size = 45456, upload-time = "2026-01-26T02:43:53.893Z" }, + { url = "https://files.pythonhosted.org/packages/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7", size = 43872, upload-time = "2026-01-26T02:43:55.041Z" }, + { url = "https://files.pythonhosted.org/packages/cf/3b/d6bd75dc4f3ff7c73766e04e705b00ed6dbbaccf670d9e05a12b006f5a21/multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53", size = 251018, upload-time = "2026-01-26T02:43:56.198Z" }, + { url = "https://files.pythonhosted.org/packages/fd/80/c959c5933adedb9ac15152e4067c702a808ea183a8b64cf8f31af8ad3155/multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75", size = 258883, upload-time = "2026-01-26T02:43:57.499Z" }, + { url = "https://files.pythonhosted.org/packages/86/85/7ed40adafea3d4f1c8b916e3b5cc3a8e07dfcdcb9cd72800f4ed3ca1b387/multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b", size = 242413, upload-time = "2026-01-26T02:43:58.755Z" }, + { url = "https://files.pythonhosted.org/packages/d2/57/b8565ff533e48595503c785f8361ff9a4fde4d67de25c207cd0ba3befd03/multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733", size = 268404, upload-time = "2026-01-26T02:44:00.216Z" }, + { url = "https://files.pythonhosted.org/packages/e0/50/9810c5c29350f7258180dfdcb2e52783a0632862eb334c4896ac717cebcb/multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a", size = 269456, upload-time = "2026-01-26T02:44:02.202Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961", size = 256322, upload-time = "2026-01-26T02:44:03.56Z" }, + { url = "https://files.pythonhosted.org/packages/31/6e/d8a26d81ac166a5592782d208dd90dfdc0a7a218adaa52b45a672b46c122/multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582", size = 253955, upload-time = "2026-01-26T02:44:04.845Z" }, + { url = "https://files.pythonhosted.org/packages/59/4c/7c672c8aad41534ba619bcd4ade7a0dc87ed6b8b5c06149b85d3dd03f0cd/multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e", size = 251254, upload-time = "2026-01-26T02:44:06.133Z" }, + { url = "https://files.pythonhosted.org/packages/7b/bd/84c24de512cbafbdbc39439f74e967f19570ce7924e3007174a29c348916/multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3", size = 252059, upload-time = "2026-01-26T02:44:07.518Z" }, + { url = "https://files.pythonhosted.org/packages/fa/ba/f5449385510825b73d01c2d4087bf6d2fccc20a2d42ac34df93191d3dd03/multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6", size = 263588, upload-time = "2026-01-26T02:44:09.382Z" }, + { url = "https://files.pythonhosted.org/packages/d7/11/afc7c677f68f75c84a69fe37184f0f82fce13ce4b92f49f3db280b7e92b3/multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a", size = 259642, upload-time = "2026-01-26T02:44:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/2b/17/ebb9644da78c4ab36403739e0e6e0e30ebb135b9caf3440825001a0bddcb/multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba", size = 251377, upload-time = "2026-01-26T02:44:12.042Z" }, + { url = "https://files.pythonhosted.org/packages/ca/a4/840f5b97339e27846c46307f2530a2805d9d537d8b8bd416af031cad7fa0/multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511", size = 41887, upload-time = "2026-01-26T02:44:14.245Z" }, + { url = "https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19", size = 46053, upload-time = "2026-01-26T02:44:15.371Z" }, + { url = "https://files.pythonhosted.org/packages/0c/5b/aba28e4ee4006ae4c7df8d327d31025d760ffa992ea23812a601d226e682/multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf", size = 43307, upload-time = "2026-01-26T02:44:16.852Z" }, + { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, +] + [[package]] name = "munch" version = "4.0.0" @@ -1872,6 +2925,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/42/31/d2f89f1ae42718f8c8a9e440ebe38d7d5fe1e0d9eb9178ce779e365b3ab0/networkx-2.8.8-py3-none-any.whl", hash = "sha256:e435dfa75b1d7195c7b8378c3859f0445cd88c6b0375c181ed66823a9ceb7524", size = 2025192, upload-time = "2022-11-01T20:31:49.035Z" }, ] +[[package]] +name = "nexus-rpc" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/50/95d7bc91f900da5e22662c82d9bf0f72a4b01f2a552708bf2f43807707a1/nexus_rpc-1.2.0.tar.gz", hash = "sha256:b4ddaffa4d3996aaeadf49b80dfcdfbca48fe4cb616defaf3b3c5c2c8fc61890", size = 74142, upload-time = "2025-11-17T19:17:06.798Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/04/eaac430d0e6bf21265ae989427d37e94be5e41dc216879f1fbb6c5339942/nexus_rpc-1.2.0-py3-none-any.whl", hash = "sha256:977876f3af811ad1a09b2961d3d1ac9233bda43ff0febbb0c9906483b9d9f8a3", size = 28166, upload-time = "2025-11-17T19:17:05.64Z" }, +] + [[package]] name = "nodeenv" version = "1.9.1" @@ -2019,6 +3084,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/48/6b/1c6b515a83d5564b1698a61efa245727c8feecf308f4091f565988519d20/numpy-2.3.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e610832418a2bc09d974cc9fecebfa51e9532d6190223bc5ef6a7402ebf3b5cb", size = 12927246, upload-time = "2025-06-21T12:27:38.618Z" }, ] +[[package]] +name = "openai" +version = "2.21.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/92/e5/3d197a0947a166649f566706d7a4c8f7fe38f1fa7b24c9bcffe4c7591d44/openai-2.21.0.tar.gz", hash = "sha256:81b48ce4b8bbb2cc3af02047ceb19561f7b1dc0d4e52d1de7f02abfd15aa59b7", size = 644374, upload-time = "2026-02-14T00:12:01.577Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/56/0a89092a453bb2c676d66abee44f863e742b2110d4dbb1dbcca3f7e5fc33/openai-2.21.0-py3-none-any.whl", hash = "sha256:0bc1c775e5b1536c294eded39ee08f8407656537ccc71b1004104fe1602e267c", size = 1103065, upload-time = "2026-02-14T00:11:59.603Z" }, +] + +[[package]] +name = "openapi-pydantic" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/2e/58d83848dd1a79cb92ed8e63f6ba901ca282c5f09d04af9423ec26c56fd7/openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d", size = 60892, upload-time = "2025-01-08T19:29:27.083Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/cf/03675d8bd8ecbf4445504d8071adab19f5f993676795708e36402ab38263/openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", size = 96381, upload-time = "2025-01-08T19:29:25.275Z" }, +] + [[package]] name = "openpyxl" version = "3.1.5" @@ -2031,6 +3127,128 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2", size = 250910, upload-time = "2024-06-28T14:03:41.161Z" }, ] +[[package]] +name = "opentelemetry-api" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/97/b9/3161be15bb8e3ad01be8be5a968a9237c3027c5be504362ff800fca3e442/opentelemetry_api-1.39.1.tar.gz", hash = "sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c", size = 65767, upload-time = "2025-12-11T13:32:39.182Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/df/d3f1ddf4bb4cb50ed9b1139cc7b1c54c34a1e7ce8fd1b9a37c0d1551a6bd/opentelemetry_api-1.39.1-py3-none-any.whl", hash = "sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950", size = 66356, upload-time = "2025-12-11T13:32:17.304Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-proto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/9d/22d241b66f7bbde88a3bfa6847a351d2c46b84de23e71222c6aae25c7050/opentelemetry_exporter_otlp_proto_common-1.39.1.tar.gz", hash = "sha256:763370d4737a59741c89a67b50f9e39271639ee4afc999dadfe768541c027464", size = 20409, upload-time = "2025-12-11T13:32:40.885Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/02/ffc3e143d89a27ac21fd557365b98bd0653b98de8a101151d5805b5d4c33/opentelemetry_exporter_otlp_proto_common-1.39.1-py3-none-any.whl", hash = "sha256:08f8a5862d64cc3435105686d0216c1365dc5701f86844a8cd56597d0c764fde", size = 18366, upload-time = "2025-12-11T13:32:20.2Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/80/04/2a08fa9c0214ae38880df01e8bfae12b067ec0793446578575e5080d6545/opentelemetry_exporter_otlp_proto_http-1.39.1.tar.gz", hash = "sha256:31bdab9745c709ce90a49a0624c2bd445d31a28ba34275951a6a362d16a0b9cb", size = 17288, upload-time = "2025-12-11T13:32:42.029Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/f1/b27d3e2e003cd9a3592c43d099d2ed8d0a947c15281bf8463a256db0b46c/opentelemetry_exporter_otlp_proto_http-1.39.1-py3-none-any.whl", hash = "sha256:d9f5207183dd752a412c4cd564ca8875ececba13be6e9c6c370ffb752fd59985", size = 19641, upload-time = "2025-12-11T13:32:22.248Z" }, +] + +[[package]] +name = "opentelemetry-instrumentation" +version = "0.60b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "packaging" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/41/0f/7e6b713ac117c1f5e4e3300748af699b9902a2e5e34c9cf443dde25a01fa/opentelemetry_instrumentation-0.60b1.tar.gz", hash = "sha256:57ddc7974c6eb35865af0426d1a17132b88b2ed8586897fee187fd5b8944bd6a", size = 31706, upload-time = "2025-12-11T13:36:42.515Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/d2/6788e83c5c86a2690101681aeef27eeb2a6bf22df52d3f263a22cee20915/opentelemetry_instrumentation-0.60b1-py3-none-any.whl", hash = "sha256:04480db952b48fb1ed0073f822f0ee26012b7be7c3eac1a3793122737c78632d", size = 33096, upload-time = "2025-12-11T13:35:33.067Z" }, +] + +[[package]] +name = "opentelemetry-instrumentation-httpx" +version = "0.60b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/86/08/11208bcfcab4fc2023252c3f322aa397fd9ad948355fea60f5fc98648603/opentelemetry_instrumentation_httpx-0.60b1.tar.gz", hash = "sha256:a506ebaf28c60112cbe70ad4f0338f8603f148938cb7b6794ce1051cd2b270ae", size = 20611, upload-time = "2025-12-11T13:37:01.661Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/59/b98e84eebf745ffc75397eaad4763795bff8a30cbf2373a50ed4e70646c5/opentelemetry_instrumentation_httpx-0.60b1-py3-none-any.whl", hash = "sha256:f37636dd742ad2af83d896ba69601ed28da51fa4e25d1ab62fde89ce413e275b", size = 15701, upload-time = "2025-12-11T13:36:04.56Z" }, +] + +[[package]] +name = "opentelemetry-proto" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/1d/f25d76d8260c156c40c97c9ed4511ec0f9ce353f8108ca6e7561f82a06b2/opentelemetry_proto-1.39.1.tar.gz", hash = "sha256:6c8e05144fc0d3ed4d22c2289c6b126e03bcd0e6a7da0f16cedd2e1c2772e2c8", size = 46152, upload-time = "2025-12-11T13:32:48.681Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/95/b40c96a7b5203005a0b03d8ce8cd212ff23f1793d5ba289c87a097571b18/opentelemetry_proto-1.39.1-py3-none-any.whl", hash = "sha256:22cdc78efd3b3765d09e68bfbd010d4fc254c9818afd0b6b423387d9dee46007", size = 72535, upload-time = "2025-12-11T13:32:33.866Z" }, +] + +[[package]] +name = "opentelemetry-sdk" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/fb/c76080c9ba07e1e8235d24cdcc4d125ef7aa3edf23eb4e497c2e50889adc/opentelemetry_sdk-1.39.1.tar.gz", hash = "sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6", size = 171460, upload-time = "2025-12-11T13:32:49.369Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/98/e91cf858f203d86f4eccdf763dcf01cf03f1dae80c3750f7e635bfa206b6/opentelemetry_sdk-1.39.1-py3-none-any.whl", hash = "sha256:4d5482c478513ecb0a5d938dcc61394e647066e0cc2676bee9f3af3f3f45f01c", size = 132565, upload-time = "2025-12-11T13:32:35.069Z" }, +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.60b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/91/df/553f93ed38bf22f4b999d9be9c185adb558982214f33eae539d3b5cd0858/opentelemetry_semantic_conventions-0.60b1.tar.gz", hash = "sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953", size = 137935, upload-time = "2025-12-11T13:32:50.487Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/5e/5958555e09635d09b75de3c4f8b9cae7335ca545d77392ffe7331534c402/opentelemetry_semantic_conventions-0.60b1-py3-none-any.whl", hash = "sha256:9fa8c8b0c110da289809292b0591220d3a7b53c1526a23021e977d68597893fb", size = 219982, upload-time = "2025-12-11T13:32:36.955Z" }, +] + +[[package]] +name = "opentelemetry-util-http" +version = "0.60b1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/50/fc/c47bb04a1d8a941a4061307e1eddfa331ed4d0ab13d8a9781e6db256940a/opentelemetry_util_http-0.60b1.tar.gz", hash = "sha256:0d97152ca8c8a41ced7172d29d3622a219317f74ae6bb3027cfbdcf22c3cc0d6", size = 11053, upload-time = "2025-12-11T13:37:25.115Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/5c/d3f1733665f7cd582ef0842fb1d2ed0bc1fba10875160593342d22bba375/opentelemetry_util_http-0.60b1-py3-none-any.whl", hash = "sha256:66381ba28550c91bee14dcba8979ace443444af1ed609226634596b4b0faf199", size = 8947, upload-time = "2025-12-11T13:36:37.151Z" }, +] + [[package]] name = "outdated" version = "0.2.2" @@ -2056,11 +3274,11 @@ wheels = [ [[package]] name = "packaging" -version = "24.2" +version = "25.0" 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, upload-time = "2024-11-08T09:47:47.202Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" }, + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, ] [[package]] @@ -2149,6 +3367,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/94/30/4b1094c93615ea388058452dee70e3bbc6dc88ececea73f9c4e4437accea/path-17.1.0-py3-none-any.whl", hash = "sha256:688e7ec254f07a1c25f5474662d4480c663a2c8c4eb15c0ba056d8ab81608d22", size = 23839, upload-time = "2024-12-28T16:05:45.622Z" }, ] +[[package]] +name = "pathable" +version = "0.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/67/93/8f2c2075b180c12c1e9f6a09d1a985bc2036906b13dff1d8917e395f2048/pathable-0.4.4.tar.gz", hash = "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2", size = 8124, upload-time = "2025-01-10T18:43:13.247Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/eb/b6260b31b1a96386c0a880edebe26f89669098acea8e0318bff6adb378fd/pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2", size = 9592, upload-time = "2025-01-10T18:43:11.88Z" }, +] + [[package]] name = "pathspec" version = "0.12.1" @@ -2317,6 +3544,75 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810, upload-time = "2025-04-15T09:18:44.753Z" }, ] +[[package]] +name = "propcache" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/0e/934b541323035566a9af292dba85a195f7b78179114f2c6ebb24551118a9/propcache-0.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db", size = 79534, upload-time = "2025-10-08T19:46:02.083Z" }, + { url = "https://files.pythonhosted.org/packages/a1/6b/db0d03d96726d995dc7171286c6ba9d8d14251f37433890f88368951a44e/propcache-0.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8", size = 45526, upload-time = "2025-10-08T19:46:03.884Z" }, + { url = "https://files.pythonhosted.org/packages/e4/c3/82728404aea669e1600f304f2609cde9e665c18df5a11cdd57ed73c1dceb/propcache-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925", size = 47263, upload-time = "2025-10-08T19:46:05.405Z" }, + { url = "https://files.pythonhosted.org/packages/df/1b/39313ddad2bf9187a1432654c38249bab4562ef535ef07f5eb6eb04d0b1b/propcache-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21", size = 201012, upload-time = "2025-10-08T19:46:07.165Z" }, + { url = "https://files.pythonhosted.org/packages/5b/01/f1d0b57d136f294a142acf97f4ed58c8e5b974c21e543000968357115011/propcache-0.4.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5", size = 209491, upload-time = "2025-10-08T19:46:08.909Z" }, + { url = "https://files.pythonhosted.org/packages/a1/c8/038d909c61c5bb039070b3fb02ad5cccdb1dde0d714792e251cdb17c9c05/propcache-0.4.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db", size = 215319, upload-time = "2025-10-08T19:46:10.7Z" }, + { url = "https://files.pythonhosted.org/packages/08/57/8c87e93142b2c1fa2408e45695205a7ba05fb5db458c0bf5c06ba0e09ea6/propcache-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7", size = 196856, upload-time = "2025-10-08T19:46:12.003Z" }, + { url = "https://files.pythonhosted.org/packages/42/df/5615fec76aa561987a534759b3686008a288e73107faa49a8ae5795a9f7a/propcache-0.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4", size = 193241, upload-time = "2025-10-08T19:46:13.495Z" }, + { url = "https://files.pythonhosted.org/packages/d5/21/62949eb3a7a54afe8327011c90aca7e03547787a88fb8bd9726806482fea/propcache-0.4.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60", size = 190552, upload-time = "2025-10-08T19:46:14.938Z" }, + { url = "https://files.pythonhosted.org/packages/30/ee/ab4d727dd70806e5b4de96a798ae7ac6e4d42516f030ee60522474b6b332/propcache-0.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f", size = 200113, upload-time = "2025-10-08T19:46:16.695Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0b/38b46208e6711b016aa8966a3ac793eee0d05c7159d8342aa27fc0bc365e/propcache-0.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900", size = 200778, upload-time = "2025-10-08T19:46:18.023Z" }, + { url = "https://files.pythonhosted.org/packages/cf/81/5abec54355ed344476bee711e9f04815d4b00a311ab0535599204eecc257/propcache-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c", size = 193047, upload-time = "2025-10-08T19:46:19.449Z" }, + { url = "https://files.pythonhosted.org/packages/ec/b6/1f237c04e32063cb034acd5f6ef34ef3a394f75502e72703545631ab1ef6/propcache-0.4.1-cp310-cp310-win32.whl", hash = "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb", size = 38093, upload-time = "2025-10-08T19:46:20.643Z" }, + { url = "https://files.pythonhosted.org/packages/a6/67/354aac4e0603a15f76439caf0427781bcd6797f370377f75a642133bc954/propcache-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37", size = 41638, upload-time = "2025-10-08T19:46:21.935Z" }, + { url = "https://files.pythonhosted.org/packages/e0/e1/74e55b9fd1a4c209ff1a9a824bf6c8b3d1fc5a1ac3eabe23462637466785/propcache-0.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581", size = 38229, upload-time = "2025-10-08T19:46:23.368Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d4/4e2c9aaf7ac2242b9358f98dccd8f90f2605402f5afeff6c578682c2c491/propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", size = 80208, upload-time = "2025-10-08T19:46:24.597Z" }, + { url = "https://files.pythonhosted.org/packages/c2/21/d7b68e911f9c8e18e4ae43bdbc1e1e9bbd971f8866eb81608947b6f585ff/propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", size = 45777, upload-time = "2025-10-08T19:46:25.733Z" }, + { url = "https://files.pythonhosted.org/packages/d3/1d/11605e99ac8ea9435651ee71ab4cb4bf03f0949586246476a25aadfec54a/propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", size = 47647, upload-time = "2025-10-08T19:46:27.304Z" }, + { url = "https://files.pythonhosted.org/packages/58/1a/3c62c127a8466c9c843bccb503d40a273e5cc69838805f322e2826509e0d/propcache-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566", size = 214929, upload-time = "2025-10-08T19:46:28.62Z" }, + { url = "https://files.pythonhosted.org/packages/56/b9/8fa98f850960b367c4b8fe0592e7fc341daa7a9462e925228f10a60cf74f/propcache-0.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165", size = 221778, upload-time = "2025-10-08T19:46:30.358Z" }, + { url = "https://files.pythonhosted.org/packages/46/a6/0ab4f660eb59649d14b3d3d65c439421cf2f87fe5dd68591cbe3c1e78a89/propcache-0.4.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc", size = 228144, upload-time = "2025-10-08T19:46:32.607Z" }, + { url = "https://files.pythonhosted.org/packages/52/6a/57f43e054fb3d3a56ac9fc532bc684fc6169a26c75c353e65425b3e56eef/propcache-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48", size = 210030, upload-time = "2025-10-08T19:46:33.969Z" }, + { url = "https://files.pythonhosted.org/packages/40/e2/27e6feebb5f6b8408fa29f5efbb765cd54c153ac77314d27e457a3e993b7/propcache-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570", size = 208252, upload-time = "2025-10-08T19:46:35.309Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f8/91c27b22ccda1dbc7967f921c42825564fa5336a01ecd72eb78a9f4f53c2/propcache-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85", size = 202064, upload-time = "2025-10-08T19:46:36.993Z" }, + { url = "https://files.pythonhosted.org/packages/f2/26/7f00bd6bd1adba5aafe5f4a66390f243acab58eab24ff1a08bebb2ef9d40/propcache-0.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e", size = 212429, upload-time = "2025-10-08T19:46:38.398Z" }, + { url = "https://files.pythonhosted.org/packages/84/89/fd108ba7815c1117ddca79c228f3f8a15fc82a73bca8b142eb5de13b2785/propcache-0.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757", size = 216727, upload-time = "2025-10-08T19:46:39.732Z" }, + { url = "https://files.pythonhosted.org/packages/79/37/3ec3f7e3173e73f1d600495d8b545b53802cbf35506e5732dd8578db3724/propcache-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f", size = 205097, upload-time = "2025-10-08T19:46:41.025Z" }, + { url = "https://files.pythonhosted.org/packages/61/b0/b2631c19793f869d35f47d5a3a56fb19e9160d3c119f15ac7344fc3ccae7/propcache-0.4.1-cp311-cp311-win32.whl", hash = "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1", size = 38084, upload-time = "2025-10-08T19:46:42.693Z" }, + { url = "https://files.pythonhosted.org/packages/f4/78/6cce448e2098e9f3bfc91bb877f06aa24b6ccace872e39c53b2f707c4648/propcache-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6", size = 41637, upload-time = "2025-10-08T19:46:43.778Z" }, + { url = "https://files.pythonhosted.org/packages/9c/e9/754f180cccd7f51a39913782c74717c581b9cc8177ad0e949f4d51812383/propcache-0.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239", size = 38064, upload-time = "2025-10-08T19:46:44.872Z" }, + { url = "https://files.pythonhosted.org/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" }, + { url = "https://files.pythonhosted.org/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" }, + { url = "https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" }, + { url = "https://files.pythonhosted.org/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" }, + { url = "https://files.pythonhosted.org/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" }, + { url = "https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" }, + { url = "https://files.pythonhosted.org/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" }, + { url = "https://files.pythonhosted.org/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" }, + { url = "https://files.pythonhosted.org/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" }, + { url = "https://files.pythonhosted.org/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" }, + { url = "https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" }, + { url = "https://files.pythonhosted.org/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" }, + { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, +] + +[[package]] +name = "protobuf" +version = "6.33.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/25/7c72c307aafc96fa87062aa6291d9f7c94836e43214d43722e86037aac02/protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c", size = 444465, upload-time = "2026-01-29T21:51:33.494Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/79/af92d0a8369732b027e6d6084251dd8e782c685c72da161bd4a2e00fbabb/protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b", size = 425769, upload-time = "2026-01-29T21:51:21.751Z" }, + { url = "https://files.pythonhosted.org/packages/55/75/bb9bc917d10e9ee13dee8607eb9ab963b7cf8be607c46e7862c748aa2af7/protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c", size = 437118, upload-time = "2026-01-29T21:51:24.022Z" }, + { url = "https://files.pythonhosted.org/packages/a2/6b/e48dfc1191bc5b52950246275bf4089773e91cb5ba3592621723cdddca62/protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5", size = 427766, upload-time = "2026-01-29T21:51:25.413Z" }, + { url = "https://files.pythonhosted.org/packages/4e/b1/c79468184310de09d75095ed1314b839eb2f72df71097db9d1404a1b2717/protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190", size = 324638, upload-time = "2026-01-29T21:51:26.423Z" }, + { url = "https://files.pythonhosted.org/packages/c5/f5/65d838092fd01c44d16037953fd4c2cc851e783de9b8f02b27ec4ffd906f/protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd", size = 339411, upload-time = "2026-01-29T21:51:27.446Z" }, + { url = "https://files.pythonhosted.org/packages/9b/53/a9443aa3ca9ba8724fdfa02dd1887c1bcd8e89556b715cfbacca6b63dbec/protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0", size = 323465, upload-time = "2026-01-29T21:51:28.925Z" }, + { url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z" }, +] + [[package]] name = "psutil" version = "7.0.0" @@ -2350,6 +3646,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, ] +[[package]] +name = "py-key-value-aio" +version = "0.4.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beartype" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/3c/0397c072a38d4bc580994b42e0c90c5f44f679303489e4376289534735e5/py_key_value_aio-0.4.4.tar.gz", hash = "sha256:e3012e6243ed7cc09bb05457bd4d03b1ba5c2b1ca8700096b3927db79ffbbe55", size = 92300, upload-time = "2026-02-16T21:21:43.245Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/69/f1b537ee70b7def42d63124a539ed3026a11a3ffc3086947a1ca6e861868/py_key_value_aio-0.4.4-py3-none-any.whl", hash = "sha256:18e17564ecae61b987f909fc2cd41ee2012c84b4b1dcb8c055cf8b4bc1bf3f5d", size = 152291, upload-time = "2026-02-16T21:21:44.241Z" }, +] + +[package.optional-dependencies] +filetree = [ + { name = "aiofile" }, + { name = "anyio" }, +] +keyring = [ + { name = "keyring" }, +] +memory = [ + { name = "cachetools" }, +] + [[package]] name = "pyarrow" version = "20.0.0" @@ -2385,6 +3706,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/8e/9adee63dfa3911be2382fb4d92e4b2e7d82610f9d9f668493bebaa2af50f/pyarrow-20.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:96d6a0a37d9c98be08f5ed6a10831d88d52cac7b13f5287f1e0f625a0de8062b", size = 25660496, upload-time = "2025-04-27T12:30:42.809Z" }, ] +[[package]] +name = "pyasn1" +version = "0.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/b6/6e630dff89739fcd427e3f72b3d905ce0acb85a45d4ec3e2678718a3487f/pyasn1-0.6.2.tar.gz", hash = "sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b", size = 146586, upload-time = "2026-01-16T18:04:18.534Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/b5/a96872e5184f354da9c84ae119971a0a4c221fe9b27a4d94bd43f2596727/pyasn1-0.6.2-py3-none-any.whl", hash = "sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf", size = 83371, upload-time = "2026-01-16T18:04:17.174Z" }, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, +] + [[package]] name = "pyclipper" version = "1.3.0.post6" @@ -2444,6 +3786,107 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a1/6b/83661fa77dcefa195ad5f8cd9af3d1a7450fd57cc883ad04d65446ac2029/pydantic-2.12.3-py3-none-any.whl", hash = "sha256:6986454a854bc3bc6e5443e1369e06a3a456af9d339eda45510f517d9ea5c6bf", size = 462431, upload-time = "2025-10-17T15:04:19.346Z" }, ] +[package.optional-dependencies] +email = [ + { name = "email-validator" }, +] + +[[package]] +name = "pydantic-ai" +version = "1.62.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic-ai-slim", extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "fastmcp", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "temporal", "ui", "vertexai", "xai"] }, +] +sdist = { url = "https://files.pythonhosted.org/packages/20/97/e3158fa976a29e9580ba1c59601590424bbb81179c359fd29de0dc23aa09/pydantic_ai-1.62.0.tar.gz", hash = "sha256:d6ae517e365ea3ea162ca8ae643f319e105b71b0b6218b83dcad1d1eb2e38c9b", size = 12130, upload-time = "2026-02-19T05:07:07.853Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/7a/053aebfab576603e95fcfce1139de4a87e12bd5a2ef1ba00007a931c3ff0/pydantic_ai-1.62.0-py3-none-any.whl", hash = "sha256:1eb88f745ae045e63da41ad68966e8876c964d0f023fbf5d6a3f5d243370bd04", size = 7227, upload-time = "2026-02-19T05:06:58.341Z" }, +] + +[[package]] +name = "pydantic-ai-slim" +version = "1.62.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "genai-prices" }, + { name = "griffelib" }, + { name = "httpx" }, + { name = "opentelemetry-api" }, + { name = "pydantic" }, + { name = "pydantic-graph" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cc/8d/6350a49f2e4b636efbcfc233221420ab576e4ba4edba38254cb84ae4a1e6/pydantic_ai_slim-1.62.0.tar.gz", hash = "sha256:00d84f659107bbbd88823a3d3dbe7348385935a9870b9d7d4ba799256f6b6983", size = 422452, upload-time = "2026-02-19T05:07:10.292Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/67/21e9b3b0944568662e3790c936226bd48a9f27c6b5f27b5916f5857bc4d8/pydantic_ai_slim-1.62.0-py3-none-any.whl", hash = "sha256:5210073fadd46f65859a67da67845093c487f025fa430ed027151f22ec684ab2", size = 549296, upload-time = "2026-02-19T05:07:01.624Z" }, +] + +[package.optional-dependencies] +ag-ui = [ + { name = "ag-ui-protocol" }, + { name = "starlette" }, +] +anthropic = [ + { name = "anthropic" }, +] +bedrock = [ + { name = "boto3" }, +] +cli = [ + { name = "argcomplete" }, + { name = "prompt-toolkit" }, + { name = "pyperclip" }, + { name = "rich" }, +] +cohere = [ + { name = "cohere", marker = "sys_platform != 'emscripten'" }, +] +evals = [ + { name = "pydantic-evals" }, +] +fastmcp = [ + { name = "fastmcp" }, +] +google = [ + { name = "google-genai" }, +] +groq = [ + { name = "groq" }, +] +huggingface = [ + { name = "huggingface-hub" }, +] +logfire = [ + { name = "logfire", extra = ["httpx"] }, +] +mcp = [ + { name = "mcp" }, +] +mistral = [ + { name = "mistralai" }, +] +openai = [ + { name = "openai" }, + { name = "tiktoken" }, +] +retries = [ + { name = "tenacity" }, +] +temporal = [ + { name = "temporalio" }, +] +ui = [ + { name = "starlette" }, +] +vertexai = [ + { name = "google-auth" }, + { name = "requests" }, +] +xai = [ + { name = "xai-sdk" }, +] + [[package]] name = "pydantic-core" version = "2.41.4" @@ -2520,6 +3963,38 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/48/f7/925f65d930802e3ea2eb4d5afa4cb8730c8dc0d2cb89a59dc4ed2fcb2d74/pydantic_core-2.41.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c173ddcd86afd2535e2b695217e82191580663a1d1928239f877f5a1649ef39f", size = 2147775, upload-time = "2025-10-14T10:23:45.406Z" }, ] +[[package]] +name = "pydantic-evals" +version = "1.62.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "logfire-api" }, + { name = "pydantic" }, + { name = "pydantic-ai-slim" }, + { name = "pyyaml" }, + { name = "rich" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/23/90/080f6722412263395d1d6d066ee90fa8bc2722ce097844220c2d9c946877/pydantic_evals-1.62.0.tar.gz", hash = "sha256:198c4bee936718a4acf6f504056b113e60b34eb49021df8889a394e14c803693", size = 56434, upload-time = "2026-02-19T05:07:11.793Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d8/b9/dc8dba744ec02b16c6fd1abe3fd8ef1b00fd05c72feef5069851b811952f/pydantic_evals-1.62.0-py3-none-any.whl", hash = "sha256:0ca7e10037ed90393c54b6cff41370d6d4bac63f8c878715599c58863c303db1", size = 67341, upload-time = "2026-02-19T05:07:03.83Z" }, +] + +[[package]] +name = "pydantic-graph" +version = "1.62.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "logfire-api" }, + { name = "pydantic" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/b6/0b084c847ecd99624f4fbc5c8ecd3f67a2388a282a32612b2a68c3b3595f/pydantic_graph-1.62.0.tar.gz", hash = "sha256:efe56bee3a8ca35b11a3be6a5f7352419fe182ef1e1323a3267ee12dec95f3c7", size = 58529, upload-time = "2026-02-19T05:07:12.947Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/12/1a9cbcd59fd070ba72b0fe544caa6ca97758518643523ec2bf1162084e0d/pydantic_graph-1.62.0-py3-none-any.whl", hash = "sha256:abe0e7b356b4d3202b069ec020d8dd1f647f55e9a0e85cd272dab48250bde87d", size = 72350, upload-time = "2026-02-19T05:07:05.305Z" }, +] + [[package]] name = "pydantic-settings" version = "2.10.1" @@ -2585,6 +4060,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/14/e2/d928434ec3a840478e95fd0d73b0dfc0b8060a07b06f4b45e9df30444e9a/pyinstrument-5.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:55a905384ba43efc924b8863aa6cfd276f029e4aa70c4a0e3b7389e27b191e45", size = 126675, upload-time = "2026-01-04T18:37:57.278Z" }, ] +[[package]] +name = "pyjwt" +version = "2.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/5a/b46fa56bf322901eee5b0454a34343cdbdae202cd421775a8ee4e42fd519/pyjwt-2.11.0.tar.gz", hash = "sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623", size = 98019, upload-time = "2026-01-30T19:59:55.694Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/01/c26ce75ba460d5cd503da9e13b21a33804d38c2165dec7b716d06b13010c/pyjwt-2.11.0-py3-none-any.whl", hash = "sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469", size = 28224, upload-time = "2026-01-30T19:59:54.539Z" }, +] + +[package.optional-dependencies] +crypto = [ + { name = "cryptography" }, +] + [[package]] name = "pymdown-extensions" version = "10.16" @@ -2665,6 +4154,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/05/e7/df2285f3d08fee213f2d041540fa4fc9ca6c2d44cf36d3a035bf2a8d2bcc/pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf", size = 111120, upload-time = "2025-03-25T05:01:24.908Z" }, ] +[[package]] +name = "pyperclip" +version = "1.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/52/d87eba7cb129b81563019d1679026e7a112ef76855d6159d24754dbd2a51/pyperclip-1.11.0.tar.gz", hash = "sha256:244035963e4428530d9e3a6101a1ef97209c6825edab1567beac148ccc1db1b6", size = 12185, upload-time = "2025-09-26T14:40:37.245Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/80/fc9d01d5ed37ba4c42ca2b55b4339ae6e200b456be3a1aaddf4a9fa99b8c/pyperclip-1.11.0-py3-none-any.whl", hash = "sha256:299403e9ff44581cb9ba2ffeed69c7aa96a008622ad0c46cb575ca75b5b84273", size = 11063, upload-time = "2025-09-26T14:40:36.069Z" }, +] + [[package]] name = "pypoly2tri" version = "0.0.3" @@ -2823,6 +4321,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/08/20/0f2523b9e50a8052bc6a8b732dfc8568abbdc42010aef03a2d750bdab3b2/python_json_logger-3.3.0-py3-none-any.whl", hash = "sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7", size = 15163, upload-time = "2025-03-07T07:08:25.627Z" }, ] +[[package]] +name = "python-multipart" +version = "0.0.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/01/979e98d542a70714b0cb2b6728ed0b7c46792b695e3eaec3e20711271ca3/python_multipart-0.0.22.tar.gz", hash = "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58", size = 37612, upload-time = "2026-01-25T10:15:56.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/d0/397f9626e711ff749a95d96b7af99b9c566a9bb5129b8e4c10fc4d100304/python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155", size = 24579, upload-time = "2026-01-25T10:15:54.811Z" }, +] + [[package]] name = "pytz" version = "2025.2" @@ -2848,6 +4355,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, ] +[[package]] +name = "pywin32-ctypes" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, +] + [[package]] name = "pywinpty" version = "2.0.15" @@ -2971,6 +4487,63 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775, upload-time = "2025-01-25T08:48:14.241Z" }, ] +[[package]] +name = "regex" +version = "2026.2.19" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ff/c0/d8079d4f6342e4cec5c3e7d7415b5cd3e633d5f4124f7a4626908dbe84c7/regex-2026.2.19.tar.gz", hash = "sha256:6fb8cb09b10e38f3ae17cc6dc04a1df77762bd0351b6ba9041438e7cc85ec310", size = 414973, upload-time = "2026-02-19T19:03:47.899Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/de/f10b4506acfd684de4e42b0aa56ccea1a778a18864da8f6d319a40591062/regex-2026.2.19-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f5a37a17d110f9d5357a43aa7e3507cb077bf3143d1c549a45c4649e90e40a70", size = 488369, upload-time = "2026-02-19T18:59:45.01Z" }, + { url = "https://files.pythonhosted.org/packages/8b/2f/b4eaef1f0b4d0bf2a73eaf07c08f6c13422918a4180c9211ce0521746d0c/regex-2026.2.19-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:676c4e6847a83a1d5732b4ed553881ad36f0a8133627bb695a89ecf3571499d3", size = 290743, upload-time = "2026-02-19T18:59:48.527Z" }, + { url = "https://files.pythonhosted.org/packages/76/7c/805413bd0a88d04688c0725c222cfb811bd54a2f571004c24199a1ae55d6/regex-2026.2.19-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82336faeecac33297cd42857c3b36f12b91810e3fdd276befdd128f73a2b43fa", size = 288652, upload-time = "2026-02-19T18:59:50.2Z" }, + { url = "https://files.pythonhosted.org/packages/08/ff/2c4cd530a878b1975398e76faef4285f11e7c9ccf1aaedfd528bfcc1f580/regex-2026.2.19-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:52136f5b71f095cb74b736cc3a1b578030dada2e361ef2f07ca582240b703946", size = 781759, upload-time = "2026-02-19T18:59:51.836Z" }, + { url = "https://files.pythonhosted.org/packages/37/45/9608ab1b41f6740ff4076eabadde8e8b3f3400942b348ac41e8599ccc131/regex-2026.2.19-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4192464fe3e6cb0ef6751f7d3b16f886d8270d359ed1590dd555539d364f0ff7", size = 850947, upload-time = "2026-02-19T18:59:53.739Z" }, + { url = "https://files.pythonhosted.org/packages/90/3a/66471b6c4f7cac17e14bf5300e46661bba2b17ffb0871bd2759e837a6f82/regex-2026.2.19-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e561dd47a85d2660d3d3af4e6cb2da825cf20f121e577147963f875b83d32786", size = 898794, upload-time = "2026-02-19T18:59:55.993Z" }, + { url = "https://files.pythonhosted.org/packages/c2/d2/38c53929a5931f7398e5e49f5a5a3079cb2aba30119b4350608364cfad8c/regex-2026.2.19-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00ec994d7824bf01cd6c7d14c7a6a04d9aeaf7c42a2bc22d2359d715634d539b", size = 791922, upload-time = "2026-02-19T18:59:58.216Z" }, + { url = "https://files.pythonhosted.org/packages/8b/bd/b046e065630fa25059d9c195b7b5308ea94da45eee65d40879772500f74c/regex-2026.2.19-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2cb00aabd96b345d56a8c2bc328c8d6c4d29935061e05078bf1f02302e12abf5", size = 783345, upload-time = "2026-02-19T18:59:59.948Z" }, + { url = "https://files.pythonhosted.org/packages/d4/8f/045c643d2fa255a985e8f87d848e4be230b711a8935e4bdc58e60b8f7b84/regex-2026.2.19-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f374366ed35673ea81b86a8859c457d4fae6ba092b71024857e9e237410c7404", size = 768055, upload-time = "2026-02-19T19:00:01.65Z" }, + { url = "https://files.pythonhosted.org/packages/72/9f/ab7ae9f5447559562f1a788bbc85c0e526528c5e6c20542d18e4afc86aad/regex-2026.2.19-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f9417fd853fcd00b7d55167e692966dd12d95ba1a88bf08a62002ccd85030790", size = 774955, upload-time = "2026-02-19T19:00:03.368Z" }, + { url = "https://files.pythonhosted.org/packages/37/5c/f16fc23c56f60b6f4ff194604a6e53bb8aec7b6e8e4a23a482dee8d77235/regex-2026.2.19-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:12e86a01594031abf892686fcb309b041bf3de3d13d99eb7e2b02a8f3c687df1", size = 846010, upload-time = "2026-02-19T19:00:05.079Z" }, + { url = "https://files.pythonhosted.org/packages/51/c8/6be4c854135d7c9f35d4deeafdaf124b039ecb4ffcaeb7ed0495ad2c97ca/regex-2026.2.19-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:79014115e6fdf18fd9b32e291d58181bf42d4298642beaa13fd73e69810e4cb6", size = 755938, upload-time = "2026-02-19T19:00:07.148Z" }, + { url = "https://files.pythonhosted.org/packages/d6/8d/f683d49b9663a5324b95a328e69d397f6dade7cb84154eec116bf79fe150/regex-2026.2.19-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:31aefac2506967b7dd69af2c58eca3cc8b086d4110b66d6ac6e9026f0ee5b697", size = 835773, upload-time = "2026-02-19T19:00:08.939Z" }, + { url = "https://files.pythonhosted.org/packages/16/cd/619224b90da09f167fe4497c350a0d0b30edc539ee9244bf93e604c073c3/regex-2026.2.19-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:49cef7bb2a491f91a8869c7cdd90babf0a417047ab0bf923cd038ed2eab2ccb8", size = 780075, upload-time = "2026-02-19T19:00:10.838Z" }, + { url = "https://files.pythonhosted.org/packages/5b/88/19cfb0c262d6f9d722edef29157125418bf90eb3508186bf79335afeedae/regex-2026.2.19-cp310-cp310-win32.whl", hash = "sha256:3a039474986e7a314ace6efb9ce52f5da2bdb80ac4955358723d350ec85c32ad", size = 266004, upload-time = "2026-02-19T19:00:12.371Z" }, + { url = "https://files.pythonhosted.org/packages/82/af/5b487e0287ef72545d7ae92edecdacbe3d44e531cac24fda7de5598ba8dd/regex-2026.2.19-cp310-cp310-win_amd64.whl", hash = "sha256:5b81ff4f9cad99f90c807a00c5882fbcda86d8b3edd94e709fb531fc52cb3d25", size = 277895, upload-time = "2026-02-19T19:00:13.75Z" }, + { url = "https://files.pythonhosted.org/packages/4c/19/b6715a187ffca4d2979af92a46ce922445ba41f910bf187ccd666a2d52ef/regex-2026.2.19-cp310-cp310-win_arm64.whl", hash = "sha256:a032bc01a4bc73fc3cadba793fce28eb420da39338f47910c59ffcc11a5ba5ef", size = 270465, upload-time = "2026-02-19T19:00:15.127Z" }, + { url = "https://files.pythonhosted.org/packages/6f/93/43f405a98f54cc59c786efb4fc0b644615ed2392fc89d57d30da11f35b5b/regex-2026.2.19-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:93b16a18cadb938f0f2306267161d57eb33081a861cee9ffcd71e60941eb5dfc", size = 488365, upload-time = "2026-02-19T19:00:17.857Z" }, + { url = "https://files.pythonhosted.org/packages/66/46/da0efce22cd8f5ae28eeb25ac69703f49edcad3331ac22440776f4ea0867/regex-2026.2.19-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:78af1e499cab704131f6f4e2f155b7f54ce396ca2acb6ef21a49507e4752e0be", size = 290737, upload-time = "2026-02-19T19:00:19.869Z" }, + { url = "https://files.pythonhosted.org/packages/fb/19/f735078448132c1c974974d30d5306337bc297fe6b6f126164bff72c1019/regex-2026.2.19-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eb20c11aa4c3793c9ad04c19a972078cdadb261b8429380364be28e867a843f2", size = 288654, upload-time = "2026-02-19T19:00:21.307Z" }, + { url = "https://files.pythonhosted.org/packages/e2/3e/6d7c24a2f423c03ad03e3fbddefa431057186ac1c4cb4fa98b03c7f39808/regex-2026.2.19-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:db5fd91eec71e7b08de10011a2223d0faa20448d4e1380b9daa179fa7bf58906", size = 793785, upload-time = "2026-02-19T19:00:22.926Z" }, + { url = "https://files.pythonhosted.org/packages/67/32/fdb8107504b3122a79bde6705ac1f9d495ed1fe35b87d7cfc1864471999a/regex-2026.2.19-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fdbade8acba71bb45057c2b72f477f0b527c4895f9c83e6cfc30d4a006c21726", size = 860731, upload-time = "2026-02-19T19:00:25.196Z" }, + { url = "https://files.pythonhosted.org/packages/9a/fd/cc8c6f05868defd840be6e75919b1c3f462357969ac2c2a0958363b4dc23/regex-2026.2.19-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:31a5f561eb111d6aae14202e7043fb0b406d3c8dddbbb9e60851725c9b38ab1d", size = 907350, upload-time = "2026-02-19T19:00:27.093Z" }, + { url = "https://files.pythonhosted.org/packages/b5/1b/4590db9caa8db3d5a3fe31197c4e42c15aab3643b549ef6a454525fa3a61/regex-2026.2.19-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4584a3ee5f257b71e4b693cc9be3a5104249399f4116fe518c3f79b0c6fc7083", size = 800628, upload-time = "2026-02-19T19:00:29.392Z" }, + { url = "https://files.pythonhosted.org/packages/76/05/513eaa5b96fa579fd0b813e19ec047baaaf573d7374ff010fa139b384bf7/regex-2026.2.19-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:196553ba2a2f47904e5dc272d948a746352e2644005627467e055be19d73b39e", size = 773711, upload-time = "2026-02-19T19:00:30.996Z" }, + { url = "https://files.pythonhosted.org/packages/95/65/5aed06d8c54563d37fea496cf888be504879a3981a7c8e12c24b2c92c209/regex-2026.2.19-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0c10869d18abb759a3317c757746cc913d6324ce128b8bcec99350df10419f18", size = 783186, upload-time = "2026-02-19T19:00:34.598Z" }, + { url = "https://files.pythonhosted.org/packages/2c/57/79a633ad90f2371b4ef9cd72ba3a69a1a67d0cfaab4fe6fa8586d46044ef/regex-2026.2.19-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e689fed279cbe797a6b570bd18ff535b284d057202692c73420cb93cca41aa32", size = 854854, upload-time = "2026-02-19T19:00:37.306Z" }, + { url = "https://files.pythonhosted.org/packages/eb/2d/0f113d477d9e91ec4545ec36c82e58be25038d06788229c91ad52da2b7f5/regex-2026.2.19-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0782bd983f19ac7594039c9277cd6f75c89598c1d72f417e4d30d874105eb0c7", size = 762279, upload-time = "2026-02-19T19:00:39.793Z" }, + { url = "https://files.pythonhosted.org/packages/39/cb/237e9fa4f61469fd4f037164dbe8e675a376c88cf73aaaa0aedfd305601c/regex-2026.2.19-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:dbb240c81cfed5d4a67cb86d7676d9f7ec9c3f186310bec37d8a1415210e111e", size = 846172, upload-time = "2026-02-19T19:00:42.134Z" }, + { url = "https://files.pythonhosted.org/packages/ac/7c/104779c5915cc4eb557a33590f8a3f68089269c64287dd769afd76c7ce61/regex-2026.2.19-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:80d31c3f1fe7e4c6cd1831cd4478a0609903044dfcdc4660abfe6fb307add7f0", size = 789078, upload-time = "2026-02-19T19:00:43.908Z" }, + { url = "https://files.pythonhosted.org/packages/a8/4a/eae4e88b1317fb2ff57794915e0099198f51e760f6280b320adfa0ad396d/regex-2026.2.19-cp311-cp311-win32.whl", hash = "sha256:66e6a43225ff1064f8926adbafe0922b370d381c3330edaf9891cade52daa790", size = 266013, upload-time = "2026-02-19T19:00:47.274Z" }, + { url = "https://files.pythonhosted.org/packages/f9/29/ba89eb8fae79705e07ad1bd69e568f776159d2a8093c9dbc5303ee618298/regex-2026.2.19-cp311-cp311-win_amd64.whl", hash = "sha256:59a7a5216485a1896c5800e9feb8ff9213e11967b482633b6195d7da11450013", size = 277906, upload-time = "2026-02-19T19:00:49.011Z" }, + { url = "https://files.pythonhosted.org/packages/e3/1a/042d8f04b28e318df92df69d8becb0f42221eb3dd4fe5e976522f4337c76/regex-2026.2.19-cp311-cp311-win_arm64.whl", hash = "sha256:ec661807ffc14c8d14bb0b8c1bb3d5906e476bc96f98b565b709d03962ee4dd4", size = 270463, upload-time = "2026-02-19T19:00:50.988Z" }, + { url = "https://files.pythonhosted.org/packages/b3/73/13b39c7c9356f333e564ab4790b6cb0df125b8e64e8d6474e73da49b1955/regex-2026.2.19-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c1665138776e4ac1aa75146669236f7a8a696433ec4e525abf092ca9189247cc", size = 489541, upload-time = "2026-02-19T19:00:52.728Z" }, + { url = "https://files.pythonhosted.org/packages/15/77/fcc7bd9a67000d07fbcc11ed226077287a40d5c84544e62171d29d3ef59c/regex-2026.2.19-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d792b84709021945597e05656aac059526df4e0c9ef60a0eaebb306f8fafcaa8", size = 291414, upload-time = "2026-02-19T19:00:54.51Z" }, + { url = "https://files.pythonhosted.org/packages/f9/87/3997fc72dc59233426ef2e18dfdd105bb123812fff740ee9cc348f1a3243/regex-2026.2.19-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db970bcce4d63b37b3f9eb8c893f0db980bbf1d404a1d8d2b17aa8189de92c53", size = 289140, upload-time = "2026-02-19T19:00:56.841Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d0/b7dd3883ed1cff8ee0c0c9462d828aaf12be63bf5dc55453cbf423523b13/regex-2026.2.19-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03d706fbe7dfec503c8c3cb76f9352b3e3b53b623672aa49f18a251a6c71b8e6", size = 798767, upload-time = "2026-02-19T19:00:59.014Z" }, + { url = "https://files.pythonhosted.org/packages/4a/7e/8e2d09103832891b2b735a2515abf377db21144c6dd5ede1fb03c619bf09/regex-2026.2.19-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8dbff048c042beef60aa1848961384572c5afb9e8b290b0f1203a5c42cf5af65", size = 864436, upload-time = "2026-02-19T19:01:00.772Z" }, + { url = "https://files.pythonhosted.org/packages/8a/2e/afea8d23a6db1f67f45e3a0da3057104ce32e154f57dd0c8997274d45fcd/regex-2026.2.19-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccaaf9b907ea6b4223d5cbf5fa5dff5f33dc66f4907a25b967b8a81339a6e332", size = 912391, upload-time = "2026-02-19T19:01:02.865Z" }, + { url = "https://files.pythonhosted.org/packages/59/3c/ea5a4687adaba5e125b9bd6190153d0037325a0ba3757cc1537cc2c8dd90/regex-2026.2.19-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:75472631eee7898e16a8a20998d15106cb31cfde21cdf96ab40b432a7082af06", size = 803702, upload-time = "2026-02-19T19:01:05.298Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c5/624a0705e8473a26488ec1a3a4e0b8763ecfc682a185c302dfec71daea35/regex-2026.2.19-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d89f85a5ccc0cec125c24be75610d433d65295827ebaf0d884cbe56df82d4774", size = 775980, upload-time = "2026-02-19T19:01:07.047Z" }, + { url = "https://files.pythonhosted.org/packages/4d/4b/ed776642533232b5599b7c1f9d817fe11faf597e8a92b7a44b841daaae76/regex-2026.2.19-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0d9f81806abdca3234c3dd582b8a97492e93de3602c8772013cb4affa12d1668", size = 788122, upload-time = "2026-02-19T19:01:08.744Z" }, + { url = "https://files.pythonhosted.org/packages/8c/58/e93e093921d13b9784b4f69896b6e2a9e09580a265c59d9eb95e87d288f2/regex-2026.2.19-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9dadc10d1c2bbb1326e572a226d2ec56474ab8aab26fdb8cf19419b372c349a9", size = 858910, upload-time = "2026-02-19T19:01:10.488Z" }, + { url = "https://files.pythonhosted.org/packages/85/77/ff1d25a0c56cd546e0455cbc93235beb33474899690e6a361fa6b52d265b/regex-2026.2.19-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6bc25d7e15f80c9dc7853cbb490b91c1ec7310808b09d56bd278fe03d776f4f6", size = 764153, upload-time = "2026-02-19T19:01:12.156Z" }, + { url = "https://files.pythonhosted.org/packages/cd/ef/8ec58df26d52d04443b1dc56f9be4b409f43ed5ae6c0248a287f52311fc4/regex-2026.2.19-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:965d59792f5037d9138da6fed50ba943162160443b43d4895b182551805aff9c", size = 850348, upload-time = "2026-02-19T19:01:14.147Z" }, + { url = "https://files.pythonhosted.org/packages/f5/b3/c42fd5ed91639ce5a4225b9df909180fc95586db071f2bf7c68d2ccbfbe6/regex-2026.2.19-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:38d88c6ed4a09ed61403dbdf515d969ccba34669af3961ceb7311ecd0cef504a", size = 789977, upload-time = "2026-02-19T19:01:15.838Z" }, + { url = "https://files.pythonhosted.org/packages/b6/22/bc3b58ebddbfd6ca5633e71fd41829ee931963aad1ebeec55aad0c23044e/regex-2026.2.19-cp312-cp312-win32.whl", hash = "sha256:5df947cabab4b643d4791af5e28aecf6bf62e6160e525651a12eba3d03755e6b", size = 266381, upload-time = "2026-02-19T19:01:17.952Z" }, + { url = "https://files.pythonhosted.org/packages/fc/4a/6ff550b63e67603ee60e69dc6bd2d5694e85046a558f663b2434bdaeb285/regex-2026.2.19-cp312-cp312-win_amd64.whl", hash = "sha256:4146dc576ea99634ae9c15587d0c43273b4023a10702998edf0fa68ccb60237a", size = 277274, upload-time = "2026-02-19T19:01:19.826Z" }, + { url = "https://files.pythonhosted.org/packages/cc/29/9ec48b679b1e87e7bc8517dff45351eab38f74fbbda1fbcf0e9e6d4e8174/regex-2026.2.19-cp312-cp312-win_arm64.whl", hash = "sha256:cdc0a80f679353bd68450d2a42996090c30b2e15ca90ded6156c31f1a3b63f3b", size = 270509, upload-time = "2026-02-19T19:01:22.075Z" }, +] + [[package]] name = "requests" version = "2.32.4" @@ -3019,6 +4592,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046, upload-time = "2025-07-18T01:05:03.843Z" }, ] +[[package]] +name = "rich" +version = "14.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", size = 310458, upload-time = "2026-02-19T17:23:13.732Z" }, +] + +[[package]] +name = "rich-rst" +version = "1.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "docutils" }, + { name = "rich" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bc/6d/a506aaa4a9eaa945ed8ab2b7347859f53593864289853c5d6d62b77246e0/rich_rst-1.3.2.tar.gz", hash = "sha256:a1196fdddf1e364b02ec68a05e8ff8f6914fee10fbca2e6b6735f166bb0da8d4", size = 14936, upload-time = "2025-10-14T16:49:45.332Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/2f/b4530fbf948867702d0a3f27de4a6aab1d156f406d72852ab902c4d04de9/rich_rst-1.3.2-py3-none-any.whl", hash = "sha256:a99b4907cbe118cf9d18b0b44de272efa61f15117c61e39ebdc431baf5df722a", size = 12567, upload-time = "2025-10-14T16:49:42.953Z" }, +] + [[package]] name = "rpds-py" version = "0.26.0" @@ -3091,6 +4690,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c8/ed/9de62c2150ca8e2e5858acf3f4f4d0d180a38feef9fdab4078bea63d8dba/rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e99685fc95d386da368013e7fb4269dd39c30d99f812a8372d62f244f662709c", size = 555334, upload-time = "2025-07-01T15:56:51.703Z" }, ] +[[package]] +name = "rsa" +version = "4.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, +] + +[[package]] +name = "s3transfer" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/04/74127fc843314818edfa81b5540e26dd537353b123a4edc563109d8f17dd/s3transfer-0.16.0.tar.gz", hash = "sha256:8e990f13268025792229cd52fa10cb7163744bf56e719e0b9cb925ab79abf920", size = 153827, upload-time = "2025-12-01T02:30:59.114Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/51/727abb13f44c1fcf6d145979e1535a35794db0f6e450a0cb46aa24732fe2/s3transfer-0.16.0-py3-none-any.whl", hash = "sha256:18e25d66fed509e3868dc1572b3f427ff947dd2c56f844a5bf09481ad3f3b2fe", size = 86830, upload-time = "2025-12-01T02:30:57.729Z" }, +] + [[package]] name = "scikit-learn" version = "1.7.1" @@ -3196,6 +4819,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ea/b5/29fece1a74c6a94247f8a6fb93f5b28b533338e9c34fdcc9cfe7a939a767/scipy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:adf9b1999323ba335adc5d1dc7add4781cb5a4b0ef1e98b79768c05c796c4e49", size = 38431929, upload-time = "2025-06-22T16:19:49.385Z" }, ] +[[package]] +name = "secretstorage" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "jeepney" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" }, +] + [[package]] name = "send2trash" version = "1.8.3" @@ -3250,6 +4886,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bc/e9/a4560e12b9338842a1f82c9016d2543eaa084fce30a1ca11991143086b57/shapely-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:13d643256f81d55a50013eff6321142781cf777eb6a9e207c2c9e6315ba6044a", size = 1703479, upload-time = "2025-05-19T11:04:18.497Z" }, ] +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, +] + [[package]] name = "sigfig" version = "1.3.19" @@ -3298,6 +4943,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e7/9c/0e6afc12c269578be5c0c1c9f4b49a8d32770a080260c333ac04cc1c832d/soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", size = 36677, upload-time = "2025-04-20T18:50:07.196Z" }, ] +[[package]] +name = "sse-starlette" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "starlette" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/8d/00d280c03ffd39aaee0e86ec81e2d3b9253036a0f93f51d10503adef0e65/sse_starlette-3.2.0.tar.gz", hash = "sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422", size = 27253, upload-time = "2026-01-17T13:11:05.62Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/7f/832f015020844a8b8f7a9cbc103dd76ba8e3875004c41e08440ea3a2b41a/sse_starlette-3.2.0-py3-none-any.whl", hash = "sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf", size = 12763, upload-time = "2026-01-17T13:11:03.775Z" }, +] + [[package]] name = "stack-data" version = "0.6.3" @@ -3312,6 +4970,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, ] +[[package]] +name = "starlette" +version = "0.52.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c4/68/79977123bb7be889ad680d79a40f339082c1978b5cfcf62c2d8d196873ac/starlette-0.52.1.tar.gz", hash = "sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933", size = 2653702, upload-time = "2026-01-18T13:34:11.062Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/0d/13d1d239a25cbfb19e740db83143e95c772a1fe10202dda4b76792b114dd/starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74", size = 74272, upload-time = "2026-01-18T13:34:09.188Z" }, +] + [[package]] name = "strenum" version = "0.4.15" @@ -3330,6 +5001,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252, upload-time = "2022-10-06T17:21:44.262Z" }, ] +[[package]] +name = "temporalio" +version = "1.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nexus-rpc" }, + { name = "protobuf" }, + { name = "python-dateutil", marker = "python_full_version < '3.11'" }, + { name = "types-protobuf" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/21/db/7d5118d28b0918888e1ec98f56f659fdb006351e06d95f30f4274962a76f/temporalio-1.20.0.tar.gz", hash = "sha256:5a6a85b7d298b7359bffa30025f7deac83c74ac095a4c6952fbf06c249a2a67c", size = 1850498, upload-time = "2025-11-25T21:25:20.225Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/1b/e69052aa6003eafe595529485d9c62d1382dd5e671108f1bddf544fb6032/temporalio-1.20.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:fba70314b4068f8b1994bddfa0e2ad742483f0ae714d2ef52e63013ccfd7042e", size = 12061638, upload-time = "2025-11-25T21:24:57.918Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3b/3e8c67ed7f23bedfa231c6ac29a7a9c12b89881da7694732270f3ecd6b0c/temporalio-1.20.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffc5bb6cabc6ae67f0bfba44de6a9c121603134ae18784a2ff3a7f230ad99080", size = 11562603, upload-time = "2025-11-25T21:25:01.721Z" }, + { url = "https://files.pythonhosted.org/packages/6d/be/ed0cc11702210522a79e09703267ebeca06eb45832b873a58de3ca76b9d0/temporalio-1.20.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1e80c1e4cdf88fa8277177f563edc91466fe4dc13c0322f26e55c76b6a219e6", size = 11824016, upload-time = "2025-11-25T21:25:06.771Z" }, + { url = "https://files.pythonhosted.org/packages/9d/97/09c5cafabc80139d97338a2bdd8ec22e08817dfd2949ab3e5b73565006eb/temporalio-1.20.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba92d909188930860c9d89ca6d7a753bc5a67e4e9eac6cea351477c967355eed", size = 12189521, upload-time = "2025-11-25T21:25:12.091Z" }, + { url = "https://files.pythonhosted.org/packages/11/23/5689c014a76aff3b744b3ee0d80815f63b1362637814f5fbb105244df09b/temporalio-1.20.0-cp310-abi3-win_amd64.whl", hash = "sha256:eacfd571b653e0a0f4aa6593f4d06fc628797898f0900d400e833a1f40cad03a", size = 12745027, upload-time = "2025-11-25T21:25:16.827Z" }, +] + +[[package]] +name = "tenacity" +version = "9.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/47/c6/ee486fd809e357697ee8a44d3d69222b344920433d3b6666ccd9b374630c/tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a", size = 49413, upload-time = "2026-02-07T10:45:33.841Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, +] + [[package]] name = "terminado" version = "0.18.1" @@ -3353,6 +5053,39 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, ] +[[package]] +name = "tiktoken" +version = "0.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "regex" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/4d017d0f76ec3171d469d80fc03dfbb4e48a4bcaddaa831b31d526f05edc/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931", size = 37806, upload-time = "2025-10-06T20:22:45.419Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/b3/2cb7c17b6c4cf8ca983204255d3f1d95eda7213e247e6947a0ee2c747a2c/tiktoken-0.12.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3de02f5a491cfd179aec916eddb70331814bd6bf764075d39e21d5862e533970", size = 1051991, upload-time = "2025-10-06T20:21:34.098Z" }, + { url = "https://files.pythonhosted.org/packages/27/0f/df139f1df5f6167194ee5ab24634582ba9a1b62c6b996472b0277ec80f66/tiktoken-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b6cfb6d9b7b54d20af21a912bfe63a2727d9cfa8fbda642fd8322c70340aad16", size = 995798, upload-time = "2025-10-06T20:21:35.579Z" }, + { url = "https://files.pythonhosted.org/packages/ef/5d/26a691f28ab220d5edc09b9b787399b130f24327ef824de15e5d85ef21aa/tiktoken-0.12.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:cde24cdb1b8a08368f709124f15b36ab5524aac5fa830cc3fdce9c03d4fb8030", size = 1129865, upload-time = "2025-10-06T20:21:36.675Z" }, + { url = "https://files.pythonhosted.org/packages/b2/94/443fab3d4e5ebecac895712abd3849b8da93b7b7dec61c7db5c9c7ebe40c/tiktoken-0.12.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:6de0da39f605992649b9cfa6f84071e3f9ef2cec458d08c5feb1b6f0ff62e134", size = 1152856, upload-time = "2025-10-06T20:21:37.873Z" }, + { url = "https://files.pythonhosted.org/packages/54/35/388f941251b2521c70dd4c5958e598ea6d2c88e28445d2fb8189eecc1dfc/tiktoken-0.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6faa0534e0eefbcafaccb75927a4a380463a2eaa7e26000f0173b920e98b720a", size = 1195308, upload-time = "2025-10-06T20:21:39.577Z" }, + { url = "https://files.pythonhosted.org/packages/f8/00/c6681c7f833dd410576183715a530437a9873fa910265817081f65f9105f/tiktoken-0.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:82991e04fc860afb933efb63957affc7ad54f83e2216fe7d319007dab1ba5892", size = 1255697, upload-time = "2025-10-06T20:21:41.154Z" }, + { url = "https://files.pythonhosted.org/packages/5f/d2/82e795a6a9bafa034bf26a58e68fe9a89eeaaa610d51dbeb22106ba04f0a/tiktoken-0.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:6fb2995b487c2e31acf0a9e17647e3b242235a20832642bb7a9d1a181c0c1bb1", size = 879375, upload-time = "2025-10-06T20:21:43.201Z" }, + { url = "https://files.pythonhosted.org/packages/de/46/21ea696b21f1d6d1efec8639c204bdf20fde8bafb351e1355c72c5d7de52/tiktoken-0.12.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e227c7f96925003487c33b1b32265fad2fbcec2b7cf4817afb76d416f40f6bb", size = 1051565, upload-time = "2025-10-06T20:21:44.566Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d9/35c5d2d9e22bb2a5f74ba48266fb56c63d76ae6f66e02feb628671c0283e/tiktoken-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c06cf0fcc24c2cb2adb5e185c7082a82cba29c17575e828518c2f11a01f445aa", size = 995284, upload-time = "2025-10-06T20:21:45.622Z" }, + { url = "https://files.pythonhosted.org/packages/01/84/961106c37b8e49b9fdcf33fe007bb3a8fdcc380c528b20cc7fbba80578b8/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:f18f249b041851954217e9fd8e5c00b024ab2315ffda5ed77665a05fa91f42dc", size = 1129201, upload-time = "2025-10-06T20:21:47.074Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d0/3d9275198e067f8b65076a68894bb52fd253875f3644f0a321a720277b8a/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:47a5bc270b8c3db00bb46ece01ef34ad050e364b51d406b6f9730b64ac28eded", size = 1152444, upload-time = "2025-10-06T20:21:48.139Z" }, + { url = "https://files.pythonhosted.org/packages/78/db/a58e09687c1698a7c592e1038e01c206569b86a0377828d51635561f8ebf/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:508fa71810c0efdcd1b898fda574889ee62852989f7c1667414736bcb2b9a4bd", size = 1195080, upload-time = "2025-10-06T20:21:49.246Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1b/a9e4d2bf91d515c0f74afc526fd773a812232dd6cda33ebea7f531202325/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1af81a6c44f008cba48494089dd98cccb8b313f55e961a52f5b222d1e507967", size = 1255240, upload-time = "2025-10-06T20:21:50.274Z" }, + { url = "https://files.pythonhosted.org/packages/9d/15/963819345f1b1fb0809070a79e9dd96938d4ca41297367d471733e79c76c/tiktoken-0.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e68e3e593637b53e56f7237be560f7a394451cb8c11079755e80ae64b9e6def", size = 879422, upload-time = "2025-10-06T20:21:51.734Z" }, + { url = "https://files.pythonhosted.org/packages/a4/85/be65d39d6b647c79800fd9d29241d081d4eeb06271f383bb87200d74cf76/tiktoken-0.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b97f74aca0d78a1ff21b8cd9e9925714c15a9236d6ceacf5c7327c117e6e21e8", size = 1050728, upload-time = "2025-10-06T20:21:52.756Z" }, + { url = "https://files.pythonhosted.org/packages/4a/42/6573e9129bc55c9bf7300b3a35bef2c6b9117018acca0dc760ac2d93dffe/tiktoken-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b90f5ad190a4bb7c3eb30c5fa32e1e182ca1ca79f05e49b448438c3e225a49b", size = 994049, upload-time = "2025-10-06T20:21:53.782Z" }, + { url = "https://files.pythonhosted.org/packages/66/c5/ed88504d2f4a5fd6856990b230b56d85a777feab84e6129af0822f5d0f70/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:65b26c7a780e2139e73acc193e5c63ac754021f160df919add909c1492c0fb37", size = 1129008, upload-time = "2025-10-06T20:21:54.832Z" }, + { url = "https://files.pythonhosted.org/packages/f4/90/3dae6cc5436137ebd38944d396b5849e167896fc2073da643a49f372dc4f/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:edde1ec917dfd21c1f2f8046b86348b0f54a2c0547f68149d8600859598769ad", size = 1152665, upload-time = "2025-10-06T20:21:56.129Z" }, + { url = "https://files.pythonhosted.org/packages/a3/fe/26df24ce53ffde419a42f5f53d755b995c9318908288c17ec3f3448313a3/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:35a2f8ddd3824608b3d650a000c1ef71f730d0c56486845705a8248da00f9fe5", size = 1194230, upload-time = "2025-10-06T20:21:57.546Z" }, + { url = "https://files.pythonhosted.org/packages/20/cc/b064cae1a0e9fac84b0d2c46b89f4e57051a5f41324e385d10225a984c24/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83d16643edb7fa2c99eff2ab7733508aae1eebb03d5dfc46f5565862810f24e3", size = 1254688, upload-time = "2025-10-06T20:21:58.619Z" }, + { url = "https://files.pythonhosted.org/packages/81/10/b8523105c590c5b8349f2587e2fdfe51a69544bd5a76295fc20f2374f470/tiktoken-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc5288f34a8bc02e1ea7047b8d041104791d2ddbf42d1e5fa07822cbffe16bd", size = 878694, upload-time = "2025-10-06T20:21:59.876Z" }, +] + [[package]] name = "tinycss2" version = "1.4.0" @@ -3371,6 +5104,36 @@ version = "1.2.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/26/2d/1679ecf77ff85ecfc392fd713388580dce5ac6c48fe467c9bf8b8314947c/tinynumpy-1.2.1.tar.gz", hash = "sha256:f4b867eaa6ecfaf594ee64a4d6969acb5bddb94bda0427598f7fadf57a6bb750", size = 16023, upload-time = "2016-01-12T04:12:16.312Z" } +[[package]] +name = "tokenizers" +version = "0.22.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/6f/f80cfef4a312e1fb34baf7d85c72d4411afde10978d4657f8cdd811d3ccc/tokenizers-0.22.2.tar.gz", hash = "sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917", size = 372115, upload-time = "2026-01-05T10:45:15.988Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/97/5dbfabf04c7e348e655e907ed27913e03db0923abb5dfdd120d7b25630e1/tokenizers-0.22.2-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:544dd704ae7238755d790de45ba8da072e9af3eea688f698b137915ae959281c", size = 3100275, upload-time = "2026-01-05T10:41:02.158Z" }, + { url = "https://files.pythonhosted.org/packages/2e/47/174dca0502ef88b28f1c9e06b73ce33500eedfac7a7692108aec220464e7/tokenizers-0.22.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1e418a55456beedca4621dbab65a318981467a2b188e982a23e117f115ce5001", size = 2981472, upload-time = "2026-01-05T10:41:00.276Z" }, + { url = "https://files.pythonhosted.org/packages/d6/84/7990e799f1309a8b87af6b948f31edaa12a3ed22d11b352eaf4f4b2e5753/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249487018adec45d6e3554c71d46eb39fa8ea67156c640f7513eb26f318cec7", size = 3290736, upload-time = "2026-01-05T10:40:32.165Z" }, + { url = "https://files.pythonhosted.org/packages/78/59/09d0d9ba94dcd5f4f1368d4858d24546b4bdc0231c2354aa31d6199f0399/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25b85325d0815e86e0bac263506dd114578953b7b53d7de09a6485e4a160a7dd", size = 3168835, upload-time = "2026-01-05T10:40:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/47/50/b3ebb4243e7160bda8d34b731e54dd8ab8b133e50775872e7a434e524c28/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfb88f22a209ff7b40a576d5324bf8286b519d7358663db21d6246fb17eea2d5", size = 3521673, upload-time = "2026-01-05T10:40:56.614Z" }, + { url = "https://files.pythonhosted.org/packages/e0/fa/89f4cb9e08df770b57adb96f8cbb7e22695a4cb6c2bd5f0c4f0ebcf33b66/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c774b1276f71e1ef716e5486f21e76333464f47bece56bbd554485982a9e03e", size = 3724818, upload-time = "2026-01-05T10:40:44.507Z" }, + { url = "https://files.pythonhosted.org/packages/64/04/ca2363f0bfbe3b3d36e95bf67e56a4c88c8e3362b658e616d1ac185d47f2/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b", size = 3379195, upload-time = "2026-01-05T10:40:51.139Z" }, + { url = "https://files.pythonhosted.org/packages/2e/76/932be4b50ef6ccedf9d3c6639b056a967a86258c6d9200643f01269211ca/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:369cc9fc8cc10cb24143873a0d95438bb8ee257bb80c71989e3ee290e8d72c67", size = 3274982, upload-time = "2026-01-05T10:40:58.331Z" }, + { url = "https://files.pythonhosted.org/packages/1d/28/5f9f5a4cc211b69e89420980e483831bcc29dade307955cc9dc858a40f01/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:29c30b83d8dcd061078b05ae0cb94d3c710555fbb44861139f9f83dcca3dc3e4", size = 9478245, upload-time = "2026-01-05T10:41:04.053Z" }, + { url = "https://files.pythonhosted.org/packages/6c/fb/66e2da4704d6aadebf8cb39f1d6d1957df667ab24cff2326b77cda0dcb85/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:37ae80a28c1d3265bb1f22464c856bd23c02a05bb211e56d0c5301a435be6c1a", size = 9560069, upload-time = "2026-01-05T10:45:10.673Z" }, + { url = "https://files.pythonhosted.org/packages/16/04/fed398b05caa87ce9b1a1bb5166645e38196081b225059a6edaff6440fac/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:791135ee325f2336f498590eb2f11dc5c295232f288e75c99a36c5dbce63088a", size = 9899263, upload-time = "2026-01-05T10:45:12.559Z" }, + { url = "https://files.pythonhosted.org/packages/05/a1/d62dfe7376beaaf1394917e0f8e93ee5f67fea8fcf4107501db35996586b/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38337540fbbddff8e999d59970f3c6f35a82de10053206a7562f1ea02d046fa5", size = 10033429, upload-time = "2026-01-05T10:45:14.333Z" }, + { url = "https://files.pythonhosted.org/packages/fd/18/a545c4ea42af3df6effd7d13d250ba77a0a86fb20393143bbb9a92e434d4/tokenizers-0.22.2-cp39-abi3-win32.whl", hash = "sha256:a6bf3f88c554a2b653af81f3204491c818ae2ac6fbc09e76ef4773351292bc92", size = 2502363, upload-time = "2026-01-05T10:45:20.593Z" }, + { url = "https://files.pythonhosted.org/packages/65/71/0670843133a43d43070abeb1949abfdef12a86d490bea9cd9e18e37c5ff7/tokenizers-0.22.2-cp39-abi3-win_amd64.whl", hash = "sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48", size = 2747786, upload-time = "2026-01-05T10:45:18.411Z" }, + { url = "https://files.pythonhosted.org/packages/72/f4/0de46cfa12cdcbcd464cc59fde36912af405696f687e53a091fb432f694c/tokenizers-0.22.2-cp39-abi3-win_arm64.whl", hash = "sha256:9ce725d22864a1e965217204946f830c37876eee3b2ba6fc6255e8e903d5fcbc", size = 2612133, upload-time = "2026-01-05T10:45:17.232Z" }, + { url = "https://files.pythonhosted.org/packages/84/04/655b79dbcc9b3ac5f1479f18e931a344af67e5b7d3b251d2dcdcd7558592/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:753d47ebd4542742ef9261d9da92cd545b2cacbb48349a1225466745bb866ec4", size = 3282301, upload-time = "2026-01-05T10:40:34.858Z" }, + { url = "https://files.pythonhosted.org/packages/46/cd/e4851401f3d8f6f45d8480262ab6a5c8cb9c4302a790a35aa14eeed6d2fd/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e10bf9113d209be7cd046d40fbabbaf3278ff6d18eb4da4c500443185dc1896c", size = 3161308, upload-time = "2026-01-05T10:40:40.737Z" }, + { url = "https://files.pythonhosted.org/packages/6f/6e/55553992a89982cd12d4a66dddb5e02126c58677ea3931efcbe601d419db/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64d94e84f6660764e64e7e0b22baa72f6cd942279fdbb21d46abd70d179f0195", size = 3718964, upload-time = "2026-01-05T10:40:46.56Z" }, + { url = "https://files.pythonhosted.org/packages/59/8c/b1c87148aa15e099243ec9f0cf9d0e970cc2234c3257d558c25a2c5304e6/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f01a9c019878532f98927d2bacb79bbb404b43d3437455522a00a30718cdedb5", size = 3373542, upload-time = "2026-01-05T10:40:52.803Z" }, +] + [[package]] name = "tomli" version = "2.2.1" @@ -3503,6 +5266,42 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/44/e7/5c072b990bddccc4a78a186d641e50257993c50658cddc0d4bf300acd1e1/tsam-2.3.9-py3-none-any.whl", hash = "sha256:edcc4febb9e1dacc028bc819d710974ede8f563467c3d235a250f46416f93a1b", size = 36816, upload-time = "2025-06-16T07:30:01.562Z" }, ] +[[package]] +name = "typer" +version = "0.23.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc" }, + { name = "click" }, + { name = "rich" }, + { name = "shellingham" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fd/07/b822e1b307d40e263e8253d2384cf98c51aa2368cc7ba9a07e523a1d964b/typer-0.23.1.tar.gz", hash = "sha256:2070374e4d31c83e7b61362fd859aa683576432fd5b026b060ad6b4cd3b86134", size = 120047, upload-time = "2026-02-13T10:04:30.984Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/91/9b286ab899c008c2cb05e8be99814807e7fbbd33f0c0c960470826e5ac82/typer-0.23.1-py3-none-any.whl", hash = "sha256:3291ad0d3c701cbf522012faccfbb29352ff16ad262db2139e6b01f15781f14e", size = 56813, upload-time = "2026-02-13T10:04:32.008Z" }, +] + +[[package]] +name = "typer-slim" +version = "0.23.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/da/22/b9c47b8655937b6877d40791b937931702ba9c5f9d28753199266aa96f50/typer_slim-0.23.1.tar.gz", hash = "sha256:dfe92a6317030ee2380f65bf92e540d7c77fefcc689e10d585b4925b45b5e06a", size = 4762, upload-time = "2026-02-13T10:04:26.416Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/8a/5764b851659345f34787f1b6eb30b9d308bbd6c294825cbe38b6b869c97a/typer_slim-0.23.1-py3-none-any.whl", hash = "sha256:8146d5df1eb89f628191c4c604c8464fa841885d0733c58e6e700ff0228adac5", size = 3397, upload-time = "2026-02-13T10:04:27.132Z" }, +] + +[[package]] +name = "types-protobuf" +version = "6.32.1.20251210" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c2/59/c743a842911887cd96d56aa8936522b0cd5f7a7f228c96e81b59fced45be/types_protobuf-6.32.1.20251210.tar.gz", hash = "sha256:c698bb3f020274b1a2798ae09dc773728ce3f75209a35187bd11916ebfde6763", size = 63900, upload-time = "2025-12-10T03:14:25.451Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/43/58e75bac4219cbafee83179505ff44cae3153ec279be0e30583a73b8f108/types_protobuf-6.32.1.20251210-py3-none-any.whl", hash = "sha256:2641f78f3696822a048cfb8d0ff42ccd85c25f12f871fbebe86da63793692140", size = 77921, upload-time = "2025-12-10T03:14:24.477Z" }, +] + [[package]] name = "types-python-dateutil" version = "2.9.0.20250708" @@ -3521,13 +5320,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/ba/e205cd11c1c7183b23c97e4bcd1de7bc0633e2e867601c32ecfc6ad42675/types_pytz-2025.2.0.20250516-py3-none-any.whl", hash = "sha256:e0e0c8a57e2791c19f718ed99ab2ba623856b11620cb6b637e5f62ce285a7451", size = 10136, upload-time = "2025-05-16T03:07:01.075Z" }, ] +[[package]] +name = "types-requests" +version = "2.32.4.20260107" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0f/f3/a0663907082280664d745929205a89d41dffb29e89a50f753af7d57d0a96/types_requests-2.32.4.20260107.tar.gz", hash = "sha256:018a11ac158f801bfa84857ddec1650750e393df8a004a8a9ae2a9bec6fcb24f", size = 23165, upload-time = "2026-01-07T03:20:54.091Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/12/709ea261f2bf91ef0a26a9eed20f2623227a8ed85610c1e54c5805692ecb/types_requests-2.32.4.20260107-py3-none-any.whl", hash = "sha256:b703fe72f8ce5b31ef031264fe9395cac8f46a04661a79f7ed31a80fb308730d", size = 20676, upload-time = "2026-01-07T03:20:52.929Z" }, +] + [[package]] name = "typing-extensions" -version = "4.14.1" +version = "4.15.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, ] [[package]] @@ -3569,6 +5380,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, ] +[[package]] +name = "uvicorn" +version = "0.41.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/32/ce/eeb58ae4ac36fe09e3842eb02e0eb676bf2c53ae062b98f1b2531673efdd/uvicorn-0.41.0.tar.gz", hash = "sha256:09d11cf7008da33113824ee5a1c6422d89fbc2ff476540d69a34c87fab8b571a", size = 82633, upload-time = "2026-02-16T23:07:24.1Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/e4/d04a086285c20886c0daad0e026f250869201013d18f81d9ff5eada73a88/uvicorn-0.41.0-py3-none-any.whl", hash = "sha256:29e35b1d2c36a04b9e180d4007ede3bcb32a85fbdfd6c6aeb3f26839de088187", size = 68783, upload-time = "2026-02-16T23:07:22.357Z" }, +] + [[package]] name = "validator-collection" version = "1.5.0" @@ -3624,6 +5449,63 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, ] +[[package]] +name = "watchfiles" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/c9/8869df9b2a2d6c59d79220a4db37679e74f807c559ffe5265e08b227a210/watchfiles-1.1.1.tar.gz", hash = "sha256:a173cb5c16c4f40ab19cecf48a534c409f7ea983ab8fed0741304a1c0a31b3f2", size = 94440, upload-time = "2025-10-14T15:06:21.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/1a/206e8cf2dd86fddf939165a57b4df61607a1e0add2785f170a3f616b7d9f/watchfiles-1.1.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:eef58232d32daf2ac67f42dea51a2c80f0d03379075d44a587051e63cc2e368c", size = 407318, upload-time = "2025-10-14T15:04:18.753Z" }, + { url = "https://files.pythonhosted.org/packages/b3/0f/abaf5262b9c496b5dad4ed3c0e799cbecb1f8ea512ecb6ddd46646a9fca3/watchfiles-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:03fa0f5237118a0c5e496185cafa92878568b652a2e9a9382a5151b1a0380a43", size = 394478, upload-time = "2025-10-14T15:04:20.297Z" }, + { url = "https://files.pythonhosted.org/packages/b1/04/9cc0ba88697b34b755371f5ace8d3a4d9a15719c07bdc7bd13d7d8c6a341/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca65483439f9c791897f7db49202301deb6e15fe9f8fe2fed555bf986d10c31", size = 449894, upload-time = "2025-10-14T15:04:21.527Z" }, + { url = "https://files.pythonhosted.org/packages/d2/9c/eda4615863cd8621e89aed4df680d8c3ec3da6a4cf1da113c17decd87c7f/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f0ab1c1af0cb38e3f598244c17919fb1a84d1629cc08355b0074b6d7f53138ac", size = 459065, upload-time = "2025-10-14T15:04:22.795Z" }, + { url = "https://files.pythonhosted.org/packages/84/13/f28b3f340157d03cbc8197629bc109d1098764abe1e60874622a0be5c112/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bc570d6c01c206c46deb6e935a260be44f186a2f05179f52f7fcd2be086a94d", size = 488377, upload-time = "2025-10-14T15:04:24.138Z" }, + { url = "https://files.pythonhosted.org/packages/86/93/cfa597fa9389e122488f7ffdbd6db505b3b915ca7435ecd7542e855898c2/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e84087b432b6ac94778de547e08611266f1f8ffad28c0ee4c82e028b0fc5966d", size = 595837, upload-time = "2025-10-14T15:04:25.057Z" }, + { url = "https://files.pythonhosted.org/packages/57/1e/68c1ed5652b48d89fc24d6af905d88ee4f82fa8bc491e2666004e307ded1/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:620bae625f4cb18427b1bb1a2d9426dc0dd5a5ba74c7c2cdb9de405f7b129863", size = 473456, upload-time = "2025-10-14T15:04:26.497Z" }, + { url = "https://files.pythonhosted.org/packages/d5/dc/1a680b7458ffa3b14bb64878112aefc8f2e4f73c5af763cbf0bd43100658/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:544364b2b51a9b0c7000a4b4b02f90e9423d97fbbf7e06689236443ebcad81ab", size = 455614, upload-time = "2025-10-14T15:04:27.539Z" }, + { url = "https://files.pythonhosted.org/packages/61/a5/3d782a666512e01eaa6541a72ebac1d3aae191ff4a31274a66b8dd85760c/watchfiles-1.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bbe1ef33d45bc71cf21364df962af171f96ecaeca06bd9e3d0b583efb12aec82", size = 630690, upload-time = "2025-10-14T15:04:28.495Z" }, + { url = "https://files.pythonhosted.org/packages/9b/73/bb5f38590e34687b2a9c47a244aa4dd50c56a825969c92c9c5fc7387cea1/watchfiles-1.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1a0bb430adb19ef49389e1ad368450193a90038b5b752f4ac089ec6942c4dff4", size = 622459, upload-time = "2025-10-14T15:04:29.491Z" }, + { url = "https://files.pythonhosted.org/packages/f1/ac/c9bb0ec696e07a20bd58af5399aeadaef195fb2c73d26baf55180fe4a942/watchfiles-1.1.1-cp310-cp310-win32.whl", hash = "sha256:3f6d37644155fb5beca5378feb8c1708d5783145f2a0f1c4d5a061a210254844", size = 272663, upload-time = "2025-10-14T15:04:30.435Z" }, + { url = "https://files.pythonhosted.org/packages/11/a0/a60c5a7c2ec59fa062d9a9c61d02e3b6abd94d32aac2d8344c4bdd033326/watchfiles-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:a36d8efe0f290835fd0f33da35042a1bb5dc0e83cbc092dcf69bce442579e88e", size = 287453, upload-time = "2025-10-14T15:04:31.53Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f8/2c5f479fb531ce2f0564eda479faecf253d886b1ab3630a39b7bf7362d46/watchfiles-1.1.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f57b396167a2565a4e8b5e56a5a1c537571733992b226f4f1197d79e94cf0ae5", size = 406529, upload-time = "2025-10-14T15:04:32.899Z" }, + { url = "https://files.pythonhosted.org/packages/fe/cd/f515660b1f32f65df671ddf6f85bfaca621aee177712874dc30a97397977/watchfiles-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:421e29339983e1bebc281fab40d812742268ad057db4aee8c4d2bce0af43b741", size = 394384, upload-time = "2025-10-14T15:04:33.761Z" }, + { url = "https://files.pythonhosted.org/packages/7b/c3/28b7dc99733eab43fca2d10f55c86e03bd6ab11ca31b802abac26b23d161/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e43d39a741e972bab5d8100b5cdacf69db64e34eb19b6e9af162bccf63c5cc6", size = 448789, upload-time = "2025-10-14T15:04:34.679Z" }, + { url = "https://files.pythonhosted.org/packages/4a/24/33e71113b320030011c8e4316ccca04194bf0cbbaeee207f00cbc7d6b9f5/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f537afb3276d12814082a2e9b242bdcf416c2e8fd9f799a737990a1dbe906e5b", size = 460521, upload-time = "2025-10-14T15:04:35.963Z" }, + { url = "https://files.pythonhosted.org/packages/f4/c3/3c9a55f255aa57b91579ae9e98c88704955fa9dac3e5614fb378291155df/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2cd9e04277e756a2e2d2543d65d1e2166d6fd4c9b183f8808634fda23f17b14", size = 488722, upload-time = "2025-10-14T15:04:37.091Z" }, + { url = "https://files.pythonhosted.org/packages/49/36/506447b73eb46c120169dc1717fe2eff07c234bb3232a7200b5f5bd816e9/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f3f58818dc0b07f7d9aa7fe9eb1037aecb9700e63e1f6acfed13e9fef648f5d", size = 596088, upload-time = "2025-10-14T15:04:38.39Z" }, + { url = "https://files.pythonhosted.org/packages/82/ab/5f39e752a9838ec4d52e9b87c1e80f1ee3ccdbe92e183c15b6577ab9de16/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bb9f66367023ae783551042d31b1d7fd422e8289eedd91f26754a66f44d5cff", size = 472923, upload-time = "2025-10-14T15:04:39.666Z" }, + { url = "https://files.pythonhosted.org/packages/af/b9/a419292f05e302dea372fa7e6fda5178a92998411f8581b9830d28fb9edb/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aebfd0861a83e6c3d1110b78ad54704486555246e542be3e2bb94195eabb2606", size = 456080, upload-time = "2025-10-14T15:04:40.643Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c3/d5932fd62bde1a30c36e10c409dc5d54506726f08cb3e1d8d0ba5e2bc8db/watchfiles-1.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5fac835b4ab3c6487b5dbad78c4b3724e26bcc468e886f8ba8cc4306f68f6701", size = 629432, upload-time = "2025-10-14T15:04:41.789Z" }, + { url = "https://files.pythonhosted.org/packages/f7/77/16bddd9779fafb795f1a94319dc965209c5641db5bf1edbbccace6d1b3c0/watchfiles-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:399600947b170270e80134ac854e21b3ccdefa11a9529a3decc1327088180f10", size = 623046, upload-time = "2025-10-14T15:04:42.718Z" }, + { url = "https://files.pythonhosted.org/packages/46/ef/f2ecb9a0f342b4bfad13a2787155c6ee7ce792140eac63a34676a2feeef2/watchfiles-1.1.1-cp311-cp311-win32.whl", hash = "sha256:de6da501c883f58ad50db3a32ad397b09ad29865b5f26f64c24d3e3281685849", size = 271473, upload-time = "2025-10-14T15:04:43.624Z" }, + { url = "https://files.pythonhosted.org/packages/94/bc/f42d71125f19731ea435c3948cad148d31a64fccde3867e5ba4edee901f9/watchfiles-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:35c53bd62a0b885bf653ebf6b700d1bf05debb78ad9292cf2a942b23513dc4c4", size = 287598, upload-time = "2025-10-14T15:04:44.516Z" }, + { url = "https://files.pythonhosted.org/packages/57/c9/a30f897351f95bbbfb6abcadafbaca711ce1162f4db95fc908c98a9165f3/watchfiles-1.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:57ca5281a8b5e27593cb7d82c2ac927ad88a96ed406aa446f6344e4328208e9e", size = 277210, upload-time = "2025-10-14T15:04:45.883Z" }, + { url = "https://files.pythonhosted.org/packages/74/d5/f039e7e3c639d9b1d09b07ea412a6806d38123f0508e5f9b48a87b0a76cc/watchfiles-1.1.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8c89f9f2f740a6b7dcc753140dd5e1ab9215966f7a3530d0c0705c83b401bd7d", size = 404745, upload-time = "2025-10-14T15:04:46.731Z" }, + { url = "https://files.pythonhosted.org/packages/a5/96/a881a13aa1349827490dab2d363c8039527060cfcc2c92cc6d13d1b1049e/watchfiles-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd404be08018c37350f0d6e34676bd1e2889990117a2b90070b3007f172d0610", size = 391769, upload-time = "2025-10-14T15:04:48.003Z" }, + { url = "https://files.pythonhosted.org/packages/4b/5b/d3b460364aeb8da471c1989238ea0e56bec24b6042a68046adf3d9ddb01c/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8526e8f916bb5b9a0a777c8317c23ce65de259422bba5b31325a6fa6029d33af", size = 449374, upload-time = "2025-10-14T15:04:49.179Z" }, + { url = "https://files.pythonhosted.org/packages/b9/44/5769cb62d4ed055cb17417c0a109a92f007114a4e07f30812a73a4efdb11/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2edc3553362b1c38d9f06242416a5d8e9fe235c204a4072e988ce2e5bb1f69f6", size = 459485, upload-time = "2025-10-14T15:04:50.155Z" }, + { url = "https://files.pythonhosted.org/packages/19/0c/286b6301ded2eccd4ffd0041a1b726afda999926cf720aab63adb68a1e36/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30f7da3fb3f2844259cba4720c3fc7138eb0f7b659c38f3bfa65084c7fc7abce", size = 488813, upload-time = "2025-10-14T15:04:51.059Z" }, + { url = "https://files.pythonhosted.org/packages/c7/2b/8530ed41112dd4a22f4dcfdb5ccf6a1baad1ff6eed8dc5a5f09e7e8c41c7/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8979280bdafff686ba5e4d8f97840f929a87ed9cdf133cbbd42f7766774d2aa", size = 594816, upload-time = "2025-10-14T15:04:52.031Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d2/f5f9fb49489f184f18470d4f99f4e862a4b3e9ac2865688eb2099e3d837a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcc5c24523771db3a294c77d94771abcfcb82a0e0ee8efd910c37c59ec1b31bb", size = 475186, upload-time = "2025-10-14T15:04:53.064Z" }, + { url = "https://files.pythonhosted.org/packages/cf/68/5707da262a119fb06fbe214d82dd1fe4a6f4af32d2d14de368d0349eb52a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db5d7ae38ff20153d542460752ff397fcf5c96090c1230803713cf3147a6803", size = 456812, upload-time = "2025-10-14T15:04:55.174Z" }, + { url = "https://files.pythonhosted.org/packages/66/ab/3cbb8756323e8f9b6f9acb9ef4ec26d42b2109bce830cc1f3468df20511d/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:28475ddbde92df1874b6c5c8aaeb24ad5be47a11f87cde5a28ef3835932e3e94", size = 630196, upload-time = "2025-10-14T15:04:56.22Z" }, + { url = "https://files.pythonhosted.org/packages/78/46/7152ec29b8335f80167928944a94955015a345440f524d2dfe63fc2f437b/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:36193ed342f5b9842edd3532729a2ad55c4160ffcfa3700e0d54be496b70dd43", size = 622657, upload-time = "2025-10-14T15:04:57.521Z" }, + { url = "https://files.pythonhosted.org/packages/0a/bf/95895e78dd75efe9a7f31733607f384b42eb5feb54bd2eb6ed57cc2e94f4/watchfiles-1.1.1-cp312-cp312-win32.whl", hash = "sha256:859e43a1951717cc8de7f4c77674a6d389b106361585951d9e69572823f311d9", size = 272042, upload-time = "2025-10-14T15:04:59.046Z" }, + { url = "https://files.pythonhosted.org/packages/87/0a/90eb755f568de2688cb220171c4191df932232c20946966c27a59c400850/watchfiles-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:91d4c9a823a8c987cce8fa2690923b069966dabb196dd8d137ea2cede885fde9", size = 288410, upload-time = "2025-10-14T15:05:00.081Z" }, + { url = "https://files.pythonhosted.org/packages/36/76/f322701530586922fbd6723c4f91ace21364924822a8772c549483abed13/watchfiles-1.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:a625815d4a2bdca61953dbba5a39d60164451ef34c88d751f6c368c3ea73d404", size = 278209, upload-time = "2025-10-14T15:05:01.168Z" }, + { url = "https://files.pythonhosted.org/packages/ba/4c/a888c91e2e326872fa4705095d64acd8aa2fb9c1f7b9bd0588f33850516c/watchfiles-1.1.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:17ef139237dfced9da49fb7f2232c86ca9421f666d78c264c7ffca6601d154c3", size = 409611, upload-time = "2025-10-14T15:06:05.809Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c7/5420d1943c8e3ce1a21c0a9330bcf7edafb6aa65d26b21dbb3267c9e8112/watchfiles-1.1.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:672b8adf25b1a0d35c96b5888b7b18699d27d4194bac8beeae75be4b7a3fc9b2", size = 396889, upload-time = "2025-10-14T15:06:07.035Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e5/0072cef3804ce8d3aaddbfe7788aadff6b3d3f98a286fdbee9fd74ca59a7/watchfiles-1.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77a13aea58bc2b90173bc69f2a90de8e282648939a00a602e1dc4ee23e26b66d", size = 451616, upload-time = "2025-10-14T15:06:08.072Z" }, + { url = "https://files.pythonhosted.org/packages/83/4e/b87b71cbdfad81ad7e83358b3e447fedd281b880a03d64a760fe0a11fc2e/watchfiles-1.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b495de0bb386df6a12b18335a0285dda90260f51bdb505503c02bcd1ce27a8b", size = 458413, upload-time = "2025-10-14T15:06:09.209Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8e/e500f8b0b77be4ff753ac94dc06b33d8f0d839377fee1b78e8c8d8f031bf/watchfiles-1.1.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:db476ab59b6765134de1d4fe96a1a9c96ddf091683599be0f26147ea1b2e4b88", size = 408250, upload-time = "2025-10-14T15:06:10.264Z" }, + { url = "https://files.pythonhosted.org/packages/bd/95/615e72cd27b85b61eec764a5ca51bd94d40b5adea5ff47567d9ebc4d275a/watchfiles-1.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:89eef07eee5e9d1fda06e38822ad167a044153457e6fd997f8a858ab7564a336", size = 396117, upload-time = "2025-10-14T15:06:11.28Z" }, + { url = "https://files.pythonhosted.org/packages/c9/81/e7fe958ce8a7fb5c73cc9fb07f5aeaf755e6aa72498c57d760af760c91f8/watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce19e06cbda693e9e7686358af9cd6f5d61312ab8b00488bc36f5aabbaf77e24", size = 450493, upload-time = "2025-10-14T15:06:12.321Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d4/ed38dd3b1767193de971e694aa544356e63353c33a85d948166b5ff58b9e/watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e6f39af2eab0118338902798b5aa6664f46ff66bc0280de76fca67a7f262a49", size = 457546, upload-time = "2025-10-14T15:06:13.372Z" }, +] + [[package]] name = "wcwidth" version = "0.2.13" @@ -3660,6 +5542,54 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", size = 58826, upload-time = "2024-04-23T22:16:14.422Z" }, ] +[[package]] +name = "websockets" +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/da/6462a9f510c0c49837bbc9345aca92d767a56c1fb2939e1579df1e1cdcf7/websockets-15.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b", size = 175423, upload-time = "2025-03-05T20:01:35.363Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9f/9d11c1a4eb046a9e106483b9ff69bce7ac880443f00e5ce64261b47b07e7/websockets-15.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205", size = 173080, upload-time = "2025-03-05T20:01:37.304Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4f/b462242432d93ea45f297b6179c7333dd0402b855a912a04e7fc61c0d71f/websockets-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a", size = 173329, upload-time = "2025-03-05T20:01:39.668Z" }, + { url = "https://files.pythonhosted.org/packages/6e/0c/6afa1f4644d7ed50284ac59cc70ef8abd44ccf7d45850d989ea7310538d0/websockets-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e", size = 182312, upload-time = "2025-03-05T20:01:41.815Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d4/ffc8bd1350b229ca7a4db2a3e1c482cf87cea1baccd0ef3e72bc720caeec/websockets-15.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf", size = 181319, upload-time = "2025-03-05T20:01:43.967Z" }, + { url = "https://files.pythonhosted.org/packages/97/3a/5323a6bb94917af13bbb34009fac01e55c51dfde354f63692bf2533ffbc2/websockets-15.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb", size = 181631, upload-time = "2025-03-05T20:01:46.104Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cc/1aeb0f7cee59ef065724041bb7ed667b6ab1eeffe5141696cccec2687b66/websockets-15.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d", size = 182016, upload-time = "2025-03-05T20:01:47.603Z" }, + { url = "https://files.pythonhosted.org/packages/79/f9/c86f8f7af208e4161a7f7e02774e9d0a81c632ae76db2ff22549e1718a51/websockets-15.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9", size = 181426, upload-time = "2025-03-05T20:01:48.949Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b9/828b0bc6753db905b91df6ae477c0b14a141090df64fb17f8a9d7e3516cf/websockets-15.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c", size = 181360, upload-time = "2025-03-05T20:01:50.938Z" }, + { url = "https://files.pythonhosted.org/packages/89/fb/250f5533ec468ba6327055b7d98b9df056fb1ce623b8b6aaafb30b55d02e/websockets-15.0.1-cp310-cp310-win32.whl", hash = "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256", size = 176388, upload-time = "2025-03-05T20:01:52.213Z" }, + { url = "https://files.pythonhosted.org/packages/1c/46/aca7082012768bb98e5608f01658ff3ac8437e563eca41cf068bd5849a5e/websockets-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41", size = 176830, upload-time = "2025-03-05T20:01:53.922Z" }, + { url = "https://files.pythonhosted.org/packages/9f/32/18fcd5919c293a398db67443acd33fde142f283853076049824fc58e6f75/websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431", size = 175423, upload-time = "2025-03-05T20:01:56.276Z" }, + { url = "https://files.pythonhosted.org/packages/76/70/ba1ad96b07869275ef42e2ce21f07a5b0148936688c2baf7e4a1f60d5058/websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57", size = 173082, upload-time = "2025-03-05T20:01:57.563Z" }, + { url = "https://files.pythonhosted.org/packages/86/f2/10b55821dd40eb696ce4704a87d57774696f9451108cff0d2824c97e0f97/websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905", size = 173330, upload-time = "2025-03-05T20:01:59.063Z" }, + { url = "https://files.pythonhosted.org/packages/a5/90/1c37ae8b8a113d3daf1065222b6af61cc44102da95388ac0018fcb7d93d9/websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562", size = 182878, upload-time = "2025-03-05T20:02:00.305Z" }, + { url = "https://files.pythonhosted.org/packages/8e/8d/96e8e288b2a41dffafb78e8904ea7367ee4f891dafc2ab8d87e2124cb3d3/websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792", size = 181883, upload-time = "2025-03-05T20:02:03.148Z" }, + { url = "https://files.pythonhosted.org/packages/93/1f/5d6dbf551766308f6f50f8baf8e9860be6182911e8106da7a7f73785f4c4/websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413", size = 182252, upload-time = "2025-03-05T20:02:05.29Z" }, + { url = "https://files.pythonhosted.org/packages/d4/78/2d4fed9123e6620cbf1706c0de8a1632e1a28e7774d94346d7de1bba2ca3/websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8", size = 182521, upload-time = "2025-03-05T20:02:07.458Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3b/66d4c1b444dd1a9823c4a81f50231b921bab54eee2f69e70319b4e21f1ca/websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3", size = 181958, upload-time = "2025-03-05T20:02:09.842Z" }, + { url = "https://files.pythonhosted.org/packages/08/ff/e9eed2ee5fed6f76fdd6032ca5cd38c57ca9661430bb3d5fb2872dc8703c/websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf", size = 181918, upload-time = "2025-03-05T20:02:11.968Z" }, + { url = "https://files.pythonhosted.org/packages/d8/75/994634a49b7e12532be6a42103597b71098fd25900f7437d6055ed39930a/websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85", size = 176388, upload-time = "2025-03-05T20:02:13.32Z" }, + { url = "https://files.pythonhosted.org/packages/98/93/e36c73f78400a65f5e236cd376713c34182e6663f6889cd45a4a04d8f203/websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065", size = 176828, upload-time = "2025-03-05T20:02:14.585Z" }, + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/d40f779fa16f74d3468357197af8d6ad07e7c5a27ea1ca74ceb38986f77a/websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3", size = 173109, upload-time = "2025-03-05T20:03:17.769Z" }, + { url = "https://files.pythonhosted.org/packages/bc/cd/5b887b8585a593073fd92f7c23ecd3985cd2c3175025a91b0d69b0551372/websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1", size = 173343, upload-time = "2025-03-05T20:03:19.094Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ae/d34f7556890341e900a95acf4886833646306269f899d58ad62f588bf410/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475", size = 174599, upload-time = "2025-03-05T20:03:21.1Z" }, + { url = "https://files.pythonhosted.org/packages/71/e6/5fd43993a87db364ec60fc1d608273a1a465c0caba69176dd160e197ce42/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9", size = 174207, upload-time = "2025-03-05T20:03:23.221Z" }, + { url = "https://files.pythonhosted.org/packages/2b/fb/c492d6daa5ec067c2988ac80c61359ace5c4c674c532985ac5a123436cec/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04", size = 174155, upload-time = "2025-03-05T20:03:25.321Z" }, + { url = "https://files.pythonhosted.org/packages/68/a1/dcb68430b1d00b698ae7a7e0194433bce4f07ded185f0ee5fb21e2a2e91e/websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122", size = 176884, upload-time = "2025-03-05T20:03:27.934Z" }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +] + [[package]] name = "widgetsnbextension" version = "4.0.14" @@ -3668,3 +5598,132 @@ sdist = { url = "https://files.pythonhosted.org/packages/41/53/2e0253c5efd69c965 wheels = [ { url = "https://files.pythonhosted.org/packages/ca/51/5447876806d1088a0f8f71e16542bf350918128d0a69437df26047c8e46f/widgetsnbextension-4.0.14-py3-none-any.whl", hash = "sha256:4875a9eaf72fbf5079dc372a51a9f268fc38d46f767cbf85c43a36da5cb9b575", size = 2196503, upload-time = "2025-04-10T13:01:23.086Z" }, ] + +[[package]] +name = "wrapt" +version = "1.17.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/23/bb82321b86411eb51e5a5db3fb8f8032fd30bd7c2d74bfe936136b2fa1d6/wrapt-1.17.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04", size = 53482, upload-time = "2025-08-12T05:51:44.467Z" }, + { url = "https://files.pythonhosted.org/packages/45/69/f3c47642b79485a30a59c63f6d739ed779fb4cc8323205d047d741d55220/wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2", size = 38676, upload-time = "2025-08-12T05:51:32.636Z" }, + { url = "https://files.pythonhosted.org/packages/d1/71/e7e7f5670c1eafd9e990438e69d8fb46fa91a50785332e06b560c869454f/wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c", size = 38957, upload-time = "2025-08-12T05:51:54.655Z" }, + { url = "https://files.pythonhosted.org/packages/de/17/9f8f86755c191d6779d7ddead1a53c7a8aa18bccb7cea8e7e72dfa6a8a09/wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775", size = 81975, upload-time = "2025-08-12T05:52:30.109Z" }, + { url = "https://files.pythonhosted.org/packages/f2/15/dd576273491f9f43dd09fce517f6c2ce6eb4fe21681726068db0d0467096/wrapt-1.17.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd", size = 83149, upload-time = "2025-08-12T05:52:09.316Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c4/5eb4ce0d4814521fee7aa806264bf7a114e748ad05110441cd5b8a5c744b/wrapt-1.17.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05", size = 82209, upload-time = "2025-08-12T05:52:10.331Z" }, + { url = "https://files.pythonhosted.org/packages/31/4b/819e9e0eb5c8dc86f60dfc42aa4e2c0d6c3db8732bce93cc752e604bb5f5/wrapt-1.17.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418", size = 81551, upload-time = "2025-08-12T05:52:31.137Z" }, + { url = "https://files.pythonhosted.org/packages/f8/83/ed6baf89ba3a56694700139698cf703aac9f0f9eb03dab92f57551bd5385/wrapt-1.17.3-cp310-cp310-win32.whl", hash = "sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390", size = 36464, upload-time = "2025-08-12T05:53:01.204Z" }, + { url = "https://files.pythonhosted.org/packages/2f/90/ee61d36862340ad7e9d15a02529df6b948676b9a5829fd5e16640156627d/wrapt-1.17.3-cp310-cp310-win_amd64.whl", hash = "sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6", size = 38748, upload-time = "2025-08-12T05:53:00.209Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c3/cefe0bd330d389c9983ced15d326f45373f4073c9f4a8c2f99b50bfea329/wrapt-1.17.3-cp310-cp310-win_arm64.whl", hash = "sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18", size = 36810, upload-time = "2025-08-12T05:52:51.906Z" }, + { url = "https://files.pythonhosted.org/packages/52/db/00e2a219213856074a213503fdac0511203dceefff26e1daa15250cc01a0/wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7", size = 53482, upload-time = "2025-08-12T05:51:45.79Z" }, + { url = "https://files.pythonhosted.org/packages/5e/30/ca3c4a5eba478408572096fe9ce36e6e915994dd26a4e9e98b4f729c06d9/wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85", size = 38674, upload-time = "2025-08-12T05:51:34.629Z" }, + { url = "https://files.pythonhosted.org/packages/31/25/3e8cc2c46b5329c5957cec959cb76a10718e1a513309c31399a4dad07eb3/wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f", size = 38959, upload-time = "2025-08-12T05:51:56.074Z" }, + { url = "https://files.pythonhosted.org/packages/5d/8f/a32a99fc03e4b37e31b57cb9cefc65050ea08147a8ce12f288616b05ef54/wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311", size = 82376, upload-time = "2025-08-12T05:52:32.134Z" }, + { url = "https://files.pythonhosted.org/packages/31/57/4930cb8d9d70d59c27ee1332a318c20291749b4fba31f113c2f8ac49a72e/wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1", size = 83604, upload-time = "2025-08-12T05:52:11.663Z" }, + { url = "https://files.pythonhosted.org/packages/a8/f3/1afd48de81d63dd66e01b263a6fbb86e1b5053b419b9b33d13e1f6d0f7d0/wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5", size = 82782, upload-time = "2025-08-12T05:52:12.626Z" }, + { url = "https://files.pythonhosted.org/packages/1e/d7/4ad5327612173b144998232f98a85bb24b60c352afb73bc48e3e0d2bdc4e/wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2", size = 82076, upload-time = "2025-08-12T05:52:33.168Z" }, + { url = "https://files.pythonhosted.org/packages/bb/59/e0adfc831674a65694f18ea6dc821f9fcb9ec82c2ce7e3d73a88ba2e8718/wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89", size = 36457, upload-time = "2025-08-12T05:53:03.936Z" }, + { url = "https://files.pythonhosted.org/packages/83/88/16b7231ba49861b6f75fc309b11012ede4d6b0a9c90969d9e0db8d991aeb/wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77", size = 38745, upload-time = "2025-08-12T05:53:02.885Z" }, + { url = "https://files.pythonhosted.org/packages/9a/1e/c4d4f3398ec073012c51d1c8d87f715f56765444e1a4b11e5180577b7e6e/wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a", size = 36806, upload-time = "2025-08-12T05:52:53.368Z" }, + { url = "https://files.pythonhosted.org/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0", size = 53998, upload-time = "2025-08-12T05:51:47.138Z" }, + { url = "https://files.pythonhosted.org/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba", size = 39020, upload-time = "2025-08-12T05:51:35.906Z" }, + { url = "https://files.pythonhosted.org/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd", size = 39098, upload-time = "2025-08-12T05:51:57.474Z" }, + { url = "https://files.pythonhosted.org/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828", size = 88036, upload-time = "2025-08-12T05:52:34.784Z" }, + { url = "https://files.pythonhosted.org/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9", size = 88156, upload-time = "2025-08-12T05:52:13.599Z" }, + { url = "https://files.pythonhosted.org/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396", size = 87102, upload-time = "2025-08-12T05:52:14.56Z" }, + { url = "https://files.pythonhosted.org/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc", size = 87732, upload-time = "2025-08-12T05:52:36.165Z" }, + { url = "https://files.pythonhosted.org/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe", size = 36705, upload-time = "2025-08-12T05:53:07.123Z" }, + { url = "https://files.pythonhosted.org/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c", size = 38877, upload-time = "2025-08-12T05:53:05.436Z" }, + { url = "https://files.pythonhosted.org/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6", size = 36885, upload-time = "2025-08-12T05:52:54.367Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, +] + +[[package]] +name = "xai-sdk" +version = "1.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "googleapis-common-protos" }, + { name = "grpcio" }, + { name = "opentelemetry-sdk" }, + { name = "packaging" }, + { name = "protobuf" }, + { name = "pydantic" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/3e/cf9ffdf444ec3d495b8f4a6b3934c86088900aeb131cf2d81535b218e615/xai_sdk-1.7.0.tar.gz", hash = "sha256:649e7c3bff01510326f13a709dff824256fcdfd2850e21606d25870208989bd1", size = 390582, upload-time = "2026-02-18T20:53:23.352Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/e9/e0fb57dc5b2580aa6390a836cf81d507f8017888ab8197600489118cc677/xai_sdk-1.7.0-py3-none-any.whl", hash = "sha256:332672c46ee73a7aad9b05e82db5a5044174bb3f5f038a7acf703f0b0ce6bad0", size = 241650, upload-time = "2026-02-18T20:53:22.016Z" }, +] + +[[package]] +name = "yarl" +version = "1.22.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/43/a2204825342f37c337f5edb6637040fa14e365b2fcc2346960201d457579/yarl-1.22.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e", size = 140517, upload-time = "2025-10-06T14:08:42.494Z" }, + { url = "https://files.pythonhosted.org/packages/44/6f/674f3e6f02266428c56f704cd2501c22f78e8b2eeb23f153117cc86fb28a/yarl-1.22.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f", size = 93495, upload-time = "2025-10-06T14:08:46.2Z" }, + { url = "https://files.pythonhosted.org/packages/b8/12/5b274d8a0f30c07b91b2f02cba69152600b47830fcfb465c108880fcee9c/yarl-1.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf", size = 94400, upload-time = "2025-10-06T14:08:47.855Z" }, + { url = "https://files.pythonhosted.org/packages/e2/7f/df1b6949b1fa1aa9ff6de6e2631876ad4b73c4437822026e85d8acb56bb1/yarl-1.22.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a", size = 347545, upload-time = "2025-10-06T14:08:49.683Z" }, + { url = "https://files.pythonhosted.org/packages/84/09/f92ed93bd6cd77872ab6c3462df45ca45cd058d8f1d0c9b4f54c1704429f/yarl-1.22.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c", size = 319598, upload-time = "2025-10-06T14:08:51.215Z" }, + { url = "https://files.pythonhosted.org/packages/c3/97/ac3f3feae7d522cf7ccec3d340bb0b2b61c56cb9767923df62a135092c6b/yarl-1.22.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147", size = 363893, upload-time = "2025-10-06T14:08:53.144Z" }, + { url = "https://files.pythonhosted.org/packages/06/49/f3219097403b9c84a4d079b1d7bda62dd9b86d0d6e4428c02d46ab2c77fc/yarl-1.22.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb", size = 371240, upload-time = "2025-10-06T14:08:55.036Z" }, + { url = "https://files.pythonhosted.org/packages/35/9f/06b765d45c0e44e8ecf0fe15c9eacbbde342bb5b7561c46944f107bfb6c3/yarl-1.22.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6", size = 346965, upload-time = "2025-10-06T14:08:56.722Z" }, + { url = "https://files.pythonhosted.org/packages/c5/69/599e7cea8d0fcb1694323b0db0dda317fa3162f7b90166faddecf532166f/yarl-1.22.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0", size = 342026, upload-time = "2025-10-06T14:08:58.563Z" }, + { url = "https://files.pythonhosted.org/packages/95/6f/9dfd12c8bc90fea9eab39832ee32ea48f8e53d1256252a77b710c065c89f/yarl-1.22.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda", size = 335637, upload-time = "2025-10-06T14:09:00.506Z" }, + { url = "https://files.pythonhosted.org/packages/57/2e/34c5b4eb9b07e16e873db5b182c71e5f06f9b5af388cdaa97736d79dd9a6/yarl-1.22.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc", size = 359082, upload-time = "2025-10-06T14:09:01.936Z" }, + { url = "https://files.pythonhosted.org/packages/31/71/fa7e10fb772d273aa1f096ecb8ab8594117822f683bab7d2c5a89914c92a/yarl-1.22.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737", size = 357811, upload-time = "2025-10-06T14:09:03.445Z" }, + { url = "https://files.pythonhosted.org/packages/26/da/11374c04e8e1184a6a03cf9c8f5688d3e5cec83ed6f31ad3481b3207f709/yarl-1.22.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467", size = 351223, upload-time = "2025-10-06T14:09:05.401Z" }, + { url = "https://files.pythonhosted.org/packages/82/8f/e2d01f161b0c034a30410e375e191a5d27608c1f8693bab1a08b089ca096/yarl-1.22.0-cp310-cp310-win32.whl", hash = "sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea", size = 82118, upload-time = "2025-10-06T14:09:11.148Z" }, + { url = "https://files.pythonhosted.org/packages/62/46/94c76196642dbeae634c7a61ba3da88cd77bed875bf6e4a8bed037505aa6/yarl-1.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca", size = 86852, upload-time = "2025-10-06T14:09:12.958Z" }, + { url = "https://files.pythonhosted.org/packages/af/af/7df4f179d3b1a6dcb9a4bd2ffbc67642746fcafdb62580e66876ce83fff4/yarl-1.22.0-cp310-cp310-win_arm64.whl", hash = "sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b", size = 82012, upload-time = "2025-10-06T14:09:14.664Z" }, + { url = "https://files.pythonhosted.org/packages/4d/27/5ab13fc84c76a0250afd3d26d5936349a35be56ce5785447d6c423b26d92/yarl-1.22.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511", size = 141607, upload-time = "2025-10-06T14:09:16.298Z" }, + { url = "https://files.pythonhosted.org/packages/6a/a1/d065d51d02dc02ce81501d476b9ed2229d9a990818332242a882d5d60340/yarl-1.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6", size = 94027, upload-time = "2025-10-06T14:09:17.786Z" }, + { url = "https://files.pythonhosted.org/packages/c1/da/8da9f6a53f67b5106ffe902c6fa0164e10398d4e150d85838b82f424072a/yarl-1.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028", size = 94963, upload-time = "2025-10-06T14:09:19.662Z" }, + { url = "https://files.pythonhosted.org/packages/68/fe/2c1f674960c376e29cb0bec1249b117d11738db92a6ccc4a530b972648db/yarl-1.22.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d", size = 368406, upload-time = "2025-10-06T14:09:21.402Z" }, + { url = "https://files.pythonhosted.org/packages/95/26/812a540e1c3c6418fec60e9bbd38e871eaba9545e94fa5eff8f4a8e28e1e/yarl-1.22.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503", size = 336581, upload-time = "2025-10-06T14:09:22.98Z" }, + { url = "https://files.pythonhosted.org/packages/0b/f5/5777b19e26fdf98563985e481f8be3d8a39f8734147a6ebf459d0dab5a6b/yarl-1.22.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65", size = 388924, upload-time = "2025-10-06T14:09:24.655Z" }, + { url = "https://files.pythonhosted.org/packages/86/08/24bd2477bd59c0bbd994fe1d93b126e0472e4e3df5a96a277b0a55309e89/yarl-1.22.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e", size = 392890, upload-time = "2025-10-06T14:09:26.617Z" }, + { url = "https://files.pythonhosted.org/packages/46/00/71b90ed48e895667ecfb1eaab27c1523ee2fa217433ed77a73b13205ca4b/yarl-1.22.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d", size = 365819, upload-time = "2025-10-06T14:09:28.544Z" }, + { url = "https://files.pythonhosted.org/packages/30/2d/f715501cae832651d3282387c6a9236cd26bd00d0ff1e404b3dc52447884/yarl-1.22.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7", size = 363601, upload-time = "2025-10-06T14:09:30.568Z" }, + { url = "https://files.pythonhosted.org/packages/f8/f9/a678c992d78e394e7126ee0b0e4e71bd2775e4334d00a9278c06a6cce96a/yarl-1.22.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967", size = 358072, upload-time = "2025-10-06T14:09:32.528Z" }, + { url = "https://files.pythonhosted.org/packages/2c/d1/b49454411a60edb6fefdcad4f8e6dbba7d8019e3a508a1c5836cba6d0781/yarl-1.22.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed", size = 385311, upload-time = "2025-10-06T14:09:34.634Z" }, + { url = "https://files.pythonhosted.org/packages/87/e5/40d7a94debb8448c7771a916d1861d6609dddf7958dc381117e7ba36d9e8/yarl-1.22.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6", size = 381094, upload-time = "2025-10-06T14:09:36.268Z" }, + { url = "https://files.pythonhosted.org/packages/35/d8/611cc282502381ad855448643e1ad0538957fc82ae83dfe7762c14069e14/yarl-1.22.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e", size = 370944, upload-time = "2025-10-06T14:09:37.872Z" }, + { url = "https://files.pythonhosted.org/packages/2d/df/fadd00fb1c90e1a5a8bd731fa3d3de2e165e5a3666a095b04e31b04d9cb6/yarl-1.22.0-cp311-cp311-win32.whl", hash = "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca", size = 81804, upload-time = "2025-10-06T14:09:39.359Z" }, + { url = "https://files.pythonhosted.org/packages/b5/f7/149bb6f45f267cb5c074ac40c01c6b3ea6d8a620d34b337f6321928a1b4d/yarl-1.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b", size = 86858, upload-time = "2025-10-06T14:09:41.068Z" }, + { url = "https://files.pythonhosted.org/packages/2b/13/88b78b93ad3f2f0b78e13bfaaa24d11cbc746e93fe76d8c06bf139615646/yarl-1.22.0-cp311-cp311-win_arm64.whl", hash = "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376", size = 81637, upload-time = "2025-10-06T14:09:42.712Z" }, + { url = "https://files.pythonhosted.org/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" }, + { url = "https://files.pythonhosted.org/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" }, + { url = "https://files.pythonhosted.org/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" }, + { url = "https://files.pythonhosted.org/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" }, + { url = "https://files.pythonhosted.org/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" }, + { url = "https://files.pythonhosted.org/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" }, + { url = "https://files.pythonhosted.org/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" }, + { url = "https://files.pythonhosted.org/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" }, + { url = "https://files.pythonhosted.org/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" }, + { url = "https://files.pythonhosted.org/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" }, + { url = "https://files.pythonhosted.org/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" }, + { url = "https://files.pythonhosted.org/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" }, + { url = "https://files.pythonhosted.org/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" }, + { url = "https://files.pythonhosted.org/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" }, + { url = "https://files.pythonhosted.org/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" }, + { url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" }, +] + +[[package]] +name = "zipp" +version = "3.23.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, +]