diff --git a/.gitignore b/.gitignore index 8eb2344f..23b3db0f 100644 --- a/.gitignore +++ b/.gitignore @@ -68,6 +68,7 @@ target/ /ipyautoui/.ipynb_checkpoints /ipyautoui/__pycache__ /docs/autoui_mapping.xlsx +/docs/images/.ipynb_checkpoints /src/ipyautoui/custom/.ipynb_checkpoints /src/ipyautoui/custom/__pycache__ /src/ipyautoui/custom/.virtual_documents @@ -75,6 +76,7 @@ target/ /src/ipyautoui/.ipynb_checkpoints /src/ipyautoui/_version.py /src/ipyautoui/demo_schemas/.ipynb_checkpoints/ +/src/ipyautoui/data/.ipynb_checkpoints /src/ipyautoui/demo_schemas/.__pycache__/ /tests/.ipynb_checkpoints /tests/__pycache__ diff --git a/.vscode/settings.json b/.vscode/settings.json index b2a32a65..e2a8169c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,5 +10,8 @@ "[python]": { "editor.defaultFormatter": "ms-python.black-formatter" }, - "python.formatting.provider": "none" + "python.formatting.provider": "none", + "python-envs.defaultEnvManager": "renan-r-santos.pixi-code:pixi", + "python-envs.pythonProjects": [], + "python-envs.defaultPackageManager": "renan-r-santos.pixi-code:pixi" } \ No newline at end of file diff --git a/docs/EditableGrid.csv b/docs/EditableGrid.csv new file mode 100644 index 00000000..e6e0d1f2 --- /dev/null +++ b/docs/EditableGrid.csv @@ -0,0 +1,3 @@ +string,integer,floater,something_else +how long,1,3.14,324 +how long,2,3.4,123 diff --git a/docs/EditableGridTransposed.csv b/docs/EditableGridTransposed.csv new file mode 100644 index 00000000..155d6cec --- /dev/null +++ b/docs/EditableGridTransposed.csv @@ -0,0 +1,4 @@ +string,not long,veryyyyy looooooooooooooooongggg +integer,1,2 +floater,3,4 +something_else,5,6 diff --git a/docs/demo.ipynb b/docs/demo.ipynb index ae3ab669..8781c4dd 100644 --- a/docs/demo.ipynb +++ b/docs/demo.ipynb @@ -35,7 +35,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "ed74cefa3dc34242b65dd016588406ac", + "model_id": "1cb701fd46484e2891326506652a3aca", "version_major": 2, "version_minor": 0 }, @@ -52,11 +52,18 @@ "from ipyautoui import demo\n", "demo()\n" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "default", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -70,7 +77,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.13.2" + "version": "3.12.12" }, "widgets": { "application/vnd.jupyter.widget-state+json": { @@ -30538,5 +30545,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/docs/digital-schedules-issue.py b/docs/digital-schedules-issue.py new file mode 100644 index 00000000..2ac42293 --- /dev/null +++ b/docs/digital-schedules-issue.py @@ -0,0 +1,740 @@ +from ipyautoui.automapschema import pydantic_model_from_json_schema +from ipyautoui.automapschema import pydantic_model_file_from_json_schema +from ipyautoui.custom.edittsv import EditTsvWithDiff +from ipyautoui.custom.edittsv_with_diff_and_key_mapping import EditTsvWithDiffAndKeyMapping +import pathlib + + +json_schema = { + "$defs": { + "DistributionBoardItem": { + "properties": { + "InstanceReference": { + "anyOf": [{"type": "integer"}, {"type": "null"}], + "default": 1, + "description": "equipment instance reference, integer only. Refers to equipment instance.", + "title": "Instance Reference", + }, + "LevelReference": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "default": None, + "description": "indicates the floor level an element is located on", + "title": "Level Reference", + }, + "VolumeReference": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "default": None, + "description": "indicates the floor level an element is located on", + "title": "Volume Reference", + }, + "TypeMark": { + "anyOf": [{"$ref": "#/$defs/TypeMark"}, {"type": "null"}], + "default": None, + "description": "", + "title": "Type Mark", + }, + "TypeSpecId": { + "anyOf": [{"type": "integer"}, {"type": "null"}], + "default": None, + "description": "", + "title": "Type Spec Id", + }, + "Id": { + "anyOf": [{"type": "integer"}, {"type": "null"}], + "default": None, + "description": "", + "title": "Id", + }, + }, + "title": "DistributionBoardItem", + "type": "object", + }, + "TypeMark": { + "enum": ["DB-Type1", "DB-Type2", "DB-Type3"], + "title": "TypeMark", + "type": "string", + }, + }, + "items": {"$ref": "#/$defs/DistributionBoardItem"}, + "title": "DistributionBoard", + "type": "array", +} + + +# + + +fpth = pathlib.Path("test-schema.py") +model_file = pydantic_model_file_from_json_schema(json_schema, fpth) +model = pydantic_model_from_json_schema(json_schema) +edittsvwdiff = EditTsvWithDiff(model=model, value=( + {'InstanceReference': 2, 'LevelReference': '1', 'VolumeReference': '1', 'TypeMark': 'DB-Type1', 'TypeSpecId': 2, 'Id': 3}, + {'InstanceReference': 3, 'LevelReference': None, 'VolumeReference': None, 'TypeMark': 'DB-Type1', 'TypeSpecId': 2, 'Id': 4} + ) +) +display(edittsvwdiff) +# - +type_spec_json_schema = {'datagrid_index_name': ['section', 'title', 'unit'], + 'format': 'DataFrame', + 'hide_nan': True, + 'items': {'classification': 'Pr_60_70_22_22', + 'description': 'A standardised distribution board divides an ' + 'electrical power feed into subsidiary circuits, ' + 'while providing a protective fuse or circuit ' + 'breaker for each circuit, in a common enclosure.', + 'id': 3, + 'override_units': True, + 'parameter_type': 'T', + 'properties': {'Abbreviation': {'category': 'Specifications', + 'default': 'DB', + 'description': 'equipment type ' + 'abbreviation, ' + 'alphabetic ' + 'characters only, ' + 'variable length, ' + 'between 2 and 6 ' + 'characters', + 'enum': ['DB'], + 'guid': '4ec7e9b3-b1f0-4b76-b0d4-9dd1338b8c2f', + 'guid_source': 'MXF', + 'id': 7, + 'ifc_data_type': 'IfcText', + 'name': 'Abbreviation', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'TEXT', + 'section': 'Identity Data', + 'title': 'Abbreviation', + 'tooltip': 'asset abbreviation is ' + 'defined by the ' + '[BDNS](https://github.com/theodi/BDNS). ' + 'Abbreviations must be ' + 'from those defined in ' + 'the ' + '[BDNS_Abbreviations_Register.csv](https://github.com/theodi/BDNS/blob/master/BDNS_Abbreviations_Register.csv)', + 'type': 'string', + 'unit': '', + 'unit_code': ''}, + 'ClassificationUniclassProductNumber': {'autoui': 'aectemplater_ui.widgets.uniclass.UniclassPr', + 'category': 'Specifications', + 'default': 'Pr_60_70_22_22', + 'description': 'Product ' + 'Code ' + 'that ' + 'matches ' + 'a ' + 'code ' + 'within ' + 'the ' + 'Uniclass ' + 'Pr ' + 'tables. ' + 'https://uniclass.thenbs.com/taxon/pr', + 'guid': '8212e2e8-d020-4127-bada-a9cc7f5f4dcc', + 'guid_source': 'MXF', + 'id': 4, + 'ifc_data_type': 'IfcText', + 'name': 'ClassificationUniclassProductNumber', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'TEXT', + 'section': 'Identity ' + 'Data', + 'title': 'Classification ' + 'Uniclass ' + 'Product ' + 'Number', + 'tooltip': 'Created ' + 'and ' + 'used ' + 'by ' + 'the ' + 'Autodesk ' + 'Classification ' + 'Manager ' + 'for ' + 'Revit', + 'type': 'string', + 'unit': '', + 'unit_code': ''}, + 'ClassificationUniclassSystemNumber': {'autoui': 'aectemplater_ui.widgets.uniclass.UniclassSs', + 'category': 'Specifications', + 'default': '', + 'description': 'System ' + 'Code ' + 'that ' + 'matches ' + 'a ' + 'code ' + 'within ' + 'the ' + 'Uniclass ' + 'Ss ' + 'tables. ' + 'https://uniclass.thenbs.com/taxon/ss', + 'guid': 'f16eb500-0976-4c80-b5d1-082470821ef8', + 'guid_source': 'MXF', + 'id': 5, + 'ifc_data_type': 'IfcText', + 'name': 'ClassificationUniclassSystemNumber', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'TEXT', + 'section': 'Identity ' + 'Data', + 'title': 'Classification ' + 'Uniclass ' + 'System ' + 'Number', + 'tooltip': 'Created ' + 'and ' + 'used ' + 'by ' + 'the ' + 'Autodesk ' + 'Classification ' + 'Manager ' + 'for ' + 'Revit', + 'type': 'string', + 'unit': '', + 'unit_code': ''}, + 'FunctionReference': {'category': 'Specifications', + 'description': 'indicates the ' + 'functional use ' + 'of an element', + 'guid': 'af5e6360-50bd-4b57-90c7-2a4afea96937', + 'guid_source': 'MXF', + 'id': 1, + 'ifc_data_type': 'IfcText', + 'name': 'FunctionReference', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'TEXT', + 'section': 'Identity Data', + 'title': 'Function Reference', + 'tooltip': None, + 'type': 'string', + 'unit': '', + 'unit_code': ''}, + 'Id': {'anyOf': [{'type': 'integer'}, + {'type': 'null'}], + 'category': 'Undefined', + 'description': '', + 'format': 'default', + 'guid': '958e6995-9f04-49d3-ba03-738b6bd66fd0', + 'guid_source': 'MXF', + 'id': 0, + 'ifc_data_type': 'IfcInteger', + 'name': 'Id', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': '', + 'revit_data_type': 'INTEGER', + 'section': 'Identity Data', + 'title': 'Id', + 'tooltip': None, + 'unit': '', + 'unit_code': ''}, + 'ManufacturerWebsite': {'anyOf': [{'type': 'string'}, + {'type': 'null'}], + 'category': 'Specifications', + 'description': '', + 'guid': '2e28aa00-71ac-4225-85be-b9fc09e4484e', + 'guid_source': 'BSDD', + 'id': 16, + 'ifc_data_type': 'IfcText', + 'name': 'ManufacturerWebsite', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_DistributionBoard', + 'revit_data_type': 'URL', + 'section': 'Manufacturer', + 'title': 'Manufacturer ' + 'Website', + 'tooltip': 'Website...', + 'unit': '', + 'unit_code': ''}, + 'Notes': {'anyOf': [{'type': 'string'}, + {'type': 'null'}], + 'autoui': 'aectemplater_ui.widgets.notes.MarkdownWidget', + 'category': 'Specifications', + 'description': 'free flowing notes section', + 'guid': '9faa8b0b-ab25-4dce-bb4d-3f8320522146', + 'guid_source': 'MXF', + 'id': 12, + 'ifc_data_type': 'IfcText', + 'name': 'Notes', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_DistributionBoard', + 'revit_data_type': 'TEXT', + 'section': 'Application', + 'title': 'Notes', + 'tooltip': '...', + 'unit': '', + 'unit_code': ''}, + 'OverallLength': {'anyOf': [{'type': 'number'}, + {'type': 'null'}], + 'category': 'Specifications', + 'description': '', + 'guid': '2c27007d-549f-4664-8232-5efdb8d7c1dc', + 'guid_source': 'MXF', + 'id': 13, + 'ifc_data_type': 'IfcLengthMeasure', + 'name': 'OverallLength', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_DistributionBoard', + 'revit_data_type': 'LENGTH', + 'section': 'Manufacturer', + 'title': 'Overall Length', + 'tooltip': None, + 'unit': 'mm', + 'unit_code': 'mm'}, + 'Symbol': {'category': 'Specifications', + 'default': '', + 'description': 'equipment type symbol. ' + 'Filename of PNG image', + 'guid': 'e30c1dbe-9dd5-4b20-b102-8cbbd07faa70', + 'guid_source': 'MXF', + 'id': 10, + 'ifc_data_type': 'IfcText', + 'name': 'Symbol', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'TEXT', + 'section': 'Identity Data', + 'title': 'Symbol', + 'tooltip': 'this is the same name as the ' + 'symbol imported in Revit for ' + 'schematics', + 'type': 'string', + 'unit': '', + 'unit_code': ''}, + 'TypeReference': {'category': 'Specifications', + 'default': 1, + 'description': 'equipment type ' + 'reference, integer ' + 'only. Refers to ' + 'equipment type, ' + 'there may be ' + 'multiple instances ' + 'of the same type', + 'guid': 'f2cb3fad-ff04-4e62-bffa-80d6d3fd2862', + 'guid_source': 'MXF', + 'id': 8, + 'ifc_data_type': 'IfcInteger', + 'name': 'TypeReference', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'INTEGER', + 'section': 'Identity Data', + 'title': 'Type Reference', + 'tooltip': '', + 'type': 'integer', + 'unit': '', + 'unit_code': ''}, + 'Voltage': {'anyOf': [{'type': 'number'}, + {'type': 'null'}], + 'category': 'Specifications', + 'description': '', + 'guid': '10044af7-e223-443c-a89d-10b20f2b766e', + 'guid_source': 'BSDD', + 'id': 11, + 'ifc_data_type': 'IfcElectricVoltageMeasure', + 'name': 'Voltage', + 'namespace_uri': 'https://identifier.buildingsmart.org/uri/buildingsmart/ifc/4.3/prop/Voltage', + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_DistributionBoard', + 'revit_data_type': 'ELECTRICAL_POTENTIAL', + 'section': 'Electrical', + 'title': 'Voltage', + 'tooltip': 'Voltage...', + 'unit': 'V', + 'unit_code': 'V'}}, + 'title': 'Distribution Board', + 'type': 'object'}, + 'title': 'Distribution Board', + 'type': 'array'} + + + + +fpth = pathlib.Path("type-spec-test-schema.py") +model_file = pydantic_model_file_from_json_schema(type_spec_json_schema, fpth) +model = pydantic_model_from_json_schema(type_spec_json_schema) +tsedittsvwdiff = EditTsvWithDiff(transposed=True,model=model, value=[{'Abbreviation': 'DB', + 'TypeReference': 1, + 'Symbol': '', + 'ClassificationUniclassProductNumber': 'Pr_60_70_22_22', + 'ClassificationUniclassSystemNumber': '', + 'FunctionReference': '', + 'Notes': '', + 'OverallLength': 1.0, + 'ManufacturerWebsite': 'https://maxfordham.com/', + 'Voltage': 1.0, + 'Id': 2}] +) +display(tsedittsvwdiff) + +print(model) + +# + + +# Imports and schema +from typing import Optional, List, Literal +from datetime import date, datetime, time, timedelta +from enum import Enum +from pydantic import BaseModel, Field, RootModel, ConfigDict, StringConstraints, conint, constr +from ipyautoui.custom.edittsv import EditTsvWithDiff, EditTsvFileUpload +from ipyautoui.custom.edittsv_with_diff_and_key_mapping import EditTsvWithDiffAndKeyMapping +from ipyautoui.custom.fileupload import TempFileUploadProcessor +from typing_extensions import Annotated +import xlsxdatagrid as xdg +import pathlib +import ipywidgets as w +from IPython.display import display + +class Test(BaseModel): + a_int: int = Field( + 1, + title="A Int", + ) + + a_string: str = Field( + "empty", + title="A String", + ) + + a_list: str = Field( + "[]", + title="A List", + ) + +class TestArray(RootModel[List[Test]]): + model_config = ConfigDict( + title="TestArrayString", + ) + root: List[Test] + + + +# - + +edit_tsv_w_diff = EditTsvWithDiff( + model=TestArray, + transposed=False, + primary_key_name="a_int", + header_depth=1, + exclude_metadata=True, + value=[{"a_int": 1, "a_string": "hm", "a_list": "['Hello', 'Hey']"}] +) +display(edit_tsv_w_diff) + +print(edit_tsv_w_diff.changes) +print(f'\n\n\nValue:{edit_tsv_w_diff.value}') + +eval(edit_tsv_w_diff.value[0]["a_list"]) + +# + +"""Issue with Date Validation (Project Building Area in Digital Schedules)""" +from __future__ import annotations + +from enum import Enum, IntEnum +from typing import List, Optional + +from pydantic import BaseModel, Field, RootModel + + +class Abbreviation(Enum): + BLDG = 'BLDG' + + +class TargetYear(IntEnum): + INTEGER_2025 = 2025 + INTEGER_2026 = 2026 + INTEGER_2027 = 2027 + INTEGER_2028 = 2028 + INTEGER_2029 = 2029 + INTEGER_2030 = 2030 + INTEGER_2031 = 2031 + INTEGER_2032 = 2032 + INTEGER_2033 = 2033 + INTEGER_2034 = 2034 + INTEGER_2035 = 2035 + INTEGER_2036 = 2036 + INTEGER_2037 = 2037 + INTEGER_2038 = 2038 + INTEGER_2039 = 2039 + INTEGER_2040 = 2040 + INTEGER_2050 = 2050 + + +class ProjectBuildingAreaItem(BaseModel): + Abbreviation_1: Optional[Abbreviation] = Field( + 'BLDG', + alias='Abbreviation', + description='equipment type abbreviation, alphabetic characters only, variable length, between 2 and 6 characters', + title='Abbreviation', + ) + TypeReference: Optional[int] = Field( + 1, + description='equipment type reference, integer only. Refers to equipment type, there may be multiple instances of the same type', + title='Type Reference', + ) + TargetYear_1: Optional[TargetYear] = Field( + None, + alias='TargetYear', + description='Net Zero Carbon targets change annually. This defined what year the Benchmark Targets should be defined by.', + title='Target Year', + ) + Name: Optional[str] = Field( + None, + description='Optional. Add a building name as used in the project for easier identification.', + title='Building Name', + ) + Id: Optional[int] = Field(None, description='', title='Id') + + +class ProjectBuildingArea(RootModel[List[ProjectBuildingAreaItem]]): + root: List[ProjectBuildingAreaItem] = Field(..., title='ProjectBuildingArea') + +model = ProjectBuildingArea + +pbas_edt=EditTsvWithDiffAndKeyMapping( + model=model, + transposed=True, + primary_key_name="a_int", + header_depth=1, + exclude_metadata=True, + value=[{'Abbreviation': 'BLDG', + 'TypeReference': 1, + 'TargetYear': 2025, + 'Name': 'Block A'}, + {'Abbreviation': 'BLDG', + 'TypeReference': 3, + 'TargetYear': 2026, + 'Name': 'Block B'}] +) +display(pbas_edt) +# + +from __future__ import annotations + +from datetime import date +from enum import Enum +from typing import List, Optional + +from pydantic import BaseModel, Field, RootModel + + +class EnergyEndUse(Enum): + HEATING = 'Heating' + DOMESTIC_HOT_WATER = 'Domestic Hot Water' + HEATING___DOMESTIC_HOT_WATER = 'Heating & Domestic Hot Water' + COOLING = 'Cooling' + AUXILIARY = 'Auxiliary' + LIGHTING = 'Lighting' + SMALL_POWER = 'Small Power' + IT_SERVERS = 'IT/Servers' + PV_GENERATION = 'PV Generation' + LIFTS = 'Lifts' + CATERING = 'Catering' + OTHER = 'Other' + UNKNOWN = 'Unknown' + + +class EnergyEndUseTag(Enum): + HEATING = 'Heating' + HEATING___DISTRIBUTION_LOSS = 'Heating - Distribution Loss' + DOMESTIC_HOT_WATER = 'Domestic Hot Water' + COOLING = 'Cooling' + AUXILIARY = 'Auxiliary' + LIGHTING = 'Lighting' + LIGHTING___EXTERNAL = 'Lighting - External' + SMALL_POWER = 'Small Power' + IT_SERVERS = 'IT/Servers' + PV_GENERATION = 'PV Generation' + POOL = 'Pool' + LIFTS = 'Lifts' + CATERING = 'Catering' + OTHER = 'Other' + UNKNOWN = 'Unknown' + + +class FuelType(Enum): + ELECTRICITY = 'Electricity' + GAS___NG = 'Gas - NG' + GAS___BIOGAS = 'Gas - Biogas' + GAS___LPG = 'Gas - LPG' + GAS___OTHER = 'Gas - Other' + UNKNOWN = 'Unknown' + UNSET = 'Unset' + + +class OperationalEnergyAnalysisType(Enum): + PART_L = 'Part L' + SCOTTISH_PART_L = 'Scottish Part L' + TM54 = 'TM54' + PASSIVHAUS = 'Passivhaus' + CUSTOM = 'Custom' + + +class PredictedEnergyUseItem(BaseModel): + InstanceReference: Optional[int] = Field( + 1, + description='equipment instance reference, integer only. Refers to equipment instance.', + title='Instance Reference', + ) + BuildingID: Optional[str] = Field( + None, + description='A unique identifier within the project assigned to a building', + title='Building ID', + ) + AssessmentDate: Optional[date] = Field( + None, + description='Date on which the overall condition is assessed', + title='Assessment Date', + ) + Notes: Optional[str] = Field(None, description='', title='Notes') + OperationalEnergyAnalysisType_1: Optional[OperationalEnergyAnalysisType] = Field( + None, + alias='OperationalEnergyAnalysisType', + description='defines the type of analysis', + title='Operational Energy Analysis Type', + ) + FuelType_1: Optional[FuelType] = Field( + None, alias='FuelType', description='', title='Fuel Type' + ) + EnergyConsumption: Optional[float] = Field( + None, + description='Annual energy consumption requirement. NOTE: PV Generation should be a -ve value.', + title='Energy Consumption', + ) + EnergyEndUse_1: Optional[EnergyEndUse] = Field( + None, + alias='EnergyEndUse', + description='The end-use of the energy consumption within a building. Pick the most appropriate.', + title='Energy End Use', + ) + EnergyEndUseTags: Optional[List[EnergyEndUseTag]] = Field( + None, + description='Avoid where possible. Use only when the "Energy End Use" does not correctly describe usage (e.g. mostly DHW, but add a lighting tag to indicate some lights).', + title='Energy End Use Tags', + ) + TypeMark: Optional[str] = Field(None, description='', title='Type Mark') + TypeSpecId: Optional[int] = Field(None, description='', title='Type Spec Id') + Id: Optional[int] = Field(None, description='', title='Id') + + +class PredictedEnergyUse(RootModel[List[PredictedEnergyUseItem]]): + root: List[PredictedEnergyUseItem] = Field(..., title='PredictedEnergyUse') + + +# - + + +"""Date format null warning (Predicted Energy Use in Digital Schedules)""" +value = [{'InstanceReference': 1, + 'BuildingID': 'BLDG-1', + 'AssessmentDate': None, + 'Notes': None, + 'OperationalEnergyAnalysisType': 'Part L', + 'FuelType': 'Electricity', + 'EnergyConsumption': 50.0, + 'EnergyEndUse': 'Heating', + 'EnergyEndUseTags': [], + 'TypeMark': None}, + {'InstanceReference': 2, + 'BuildingID': 'BLDG-1', + 'AssessmentDate': None, + 'Notes': None, + 'OperationalEnergyAnalysisType': 'Part L', + 'FuelType': 'Electricity', + 'EnergyConsumption': 25.0, + 'EnergyEndUse': 'Cooling', + 'EnergyEndUseTags': [], + 'TypeMark': None}, + {'InstanceReference': 3, + 'BuildingID': 'BLDG-1', + 'AssessmentDate': None, + 'Notes': None, + 'OperationalEnergyAnalysisType': 'Part L', + 'FuelType': 'Electricity', + 'EnergyConsumption': -30.0, + 'EnergyEndUse': 'PV Generation', + 'EnergyEndUseTags': [], + 'TypeMark': None}, + {'InstanceReference': 4, + 'BuildingID': 'BLDG-3', + 'AssessmentDate': None, + 'Notes': None, + 'OperationalEnergyAnalysisType': 'TM54', + 'FuelType': 'Electricity', + 'EnergyConsumption': 200.0, + 'EnergyEndUse': 'Heating', + 'EnergyEndUseTags': [], + 'TypeMark': None}] +peu_edt=EditTsvWithDiffAndKeyMapping( + model=PredictedEnergyUse, + primary_key_name=["", ""], + header_depth=1, + exclude_metadata=True, + value=value +) +display(peu_edt) + +peu_edt.model.model_fields['root'].annotation.__args__[0].model_fields + + +# + +class Role(Enum): + ADMIN = 'Admin' + USER = 'User' + GUEST = 'Guest' + +class UserItem(BaseModel): + UserId: Optional[int] = Field(None, description='Numeric user ID', title='User ID') + Username: constr(pattern=r'^[A-Za-z0-9_]{3,20}$') = Field( + ..., + description='A username consisting of 3–20 alphanumeric characters or underscores', + title='Username', + ) + String: Optional[constr(pattern=r'^[A-Za-z]{2}_(\d{2})(_\d{2}){0,3}$')] = Field( + None, description='A regex string', title='String' + ) + +class UserList(RootModel[List[UserItem]]): + root: List[UserItem] = Field(..., title='UserList') + + +# - + +edit_tsv_w_diff = EditTsvWithDiff( + model=UserList, + transposed=False, + header_depth=1, + exclude_metadata=True, + value=[{"Username": "abc1"}] +) +display(edit_tsv_w_diff) + + + + diff --git a/docs/digital-schedules-phantom-changes-issue.py b/docs/digital-schedules-phantom-changes-issue.py new file mode 100644 index 00000000..2ad453f4 --- /dev/null +++ b/docs/digital-schedules-phantom-changes-issue.py @@ -0,0 +1,344 @@ +from ipyautoui.automapschema import pydantic_model_from_json_schema +from ipyautoui.automapschema import pydantic_model_file_from_json_schema +from ipyautoui.custom.edittsv import EditTsvWithDiff +import pathlib +import numpy as np + +type_spec_json_schema = {'datagrid_index_name': ['section', 'title', 'unit'], + 'format': 'DataFrame', + 'hide_nan': True, + 'items': {'classification': 'Pr_60_70_22_22', + 'description': 'A standardised distribution board divides an ' + 'electrical power feed into subsidiary circuits, ' + 'while providing a protective fuse or circuit ' + 'breaker for each circuit, in a common enclosure.', + 'id': 3, + 'override_units': True, + 'parameter_type': 'T', + 'properties': {'Abbreviation': {'category': 'Specifications', + 'default': 'DB', + 'description': 'equipment type ' + 'abbreviation, ' + 'alphabetic ' + 'characters only, ' + 'variable length, ' + 'between 2 and 6 ' + 'characters', + 'enum': ['DB'], + 'guid': '4ec7e9b3-b1f0-4b76-b0d4-9dd1338b8c2f', + 'guid_source': 'MXF', + 'id': 7, + 'ifc_data_type': 'IfcText', + 'name': 'Abbreviation', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'TEXT', + 'section': 'Identity Data', + 'title': 'Abbreviation', + 'tooltip': 'asset abbreviation is ' + 'defined by the ' + '[BDNS](https://github.com/theodi/BDNS). ' + 'Abbreviations must be ' + 'from those defined in ' + 'the ' + '[BDNS_Abbreviations_Register.csv](https://github.com/theodi/BDNS/blob/master/BDNS_Abbreviations_Register.csv)', + 'type': 'string', + 'unit': '', + 'unit_code': ''}, + 'ClassificationUniclassProductNumber': {'autoui': 'aectemplater_ui.widgets.uniclass.UniclassPr', + 'category': 'Specifications', + 'default': 'Pr_60_70_22_22', + 'description': 'Product ' + 'Code ' + 'that ' + 'matches ' + 'a ' + 'code ' + 'within ' + 'the ' + 'Uniclass ' + 'Pr ' + 'tables. ' + 'https://uniclass.thenbs.com/taxon/pr', + 'guid': '8212e2e8-d020-4127-bada-a9cc7f5f4dcc', + 'guid_source': 'MXF', + 'id': 4, + 'ifc_data_type': 'IfcText', + 'name': 'ClassificationUniclassProductNumber', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'TEXT', + 'section': 'Identity ' + 'Data', + 'title': 'Classification ' + 'Uniclass ' + 'Product ' + 'Number', + 'tooltip': 'Created ' + 'and ' + 'used ' + 'by ' + 'the ' + 'Autodesk ' + 'Classification ' + 'Manager ' + 'for ' + 'Revit', + 'type': 'string', + 'unit': '', + 'unit_code': ''}, + 'ClassificationUniclassSystemNumber': {'autoui': 'aectemplater_ui.widgets.uniclass.UniclassSs', + 'category': 'Specifications', + 'default': '', + 'description': 'System ' + 'Code ' + 'that ' + 'matches ' + 'a ' + 'code ' + 'within ' + 'the ' + 'Uniclass ' + 'Ss ' + 'tables. ' + 'https://uniclass.thenbs.com/taxon/ss', + 'guid': 'f16eb500-0976-4c80-b5d1-082470821ef8', + 'guid_source': 'MXF', + 'id': 5, + 'ifc_data_type': 'IfcText', + 'name': 'ClassificationUniclassSystemNumber', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'TEXT', + 'section': 'Identity ' + 'Data', + 'title': 'Classification ' + 'Uniclass ' + 'System ' + 'Number', + 'tooltip': 'Created ' + 'and ' + 'used ' + 'by ' + 'the ' + 'Autodesk ' + 'Classification ' + 'Manager ' + 'for ' + 'Revit', + 'type': 'string', + 'unit': '', + 'unit_code': ''}, + 'FunctionReference': {'category': 'Specifications', + 'description': 'indicates the ' + 'functional use ' + 'of an element', + 'guid': 'af5e6360-50bd-4b57-90c7-2a4afea96937', + 'guid_source': 'MXF', + 'id': 1, + 'ifc_data_type': 'IfcText', + 'name': 'FunctionReference', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'TEXT', + 'section': 'Identity Data', + 'title': 'Function Reference', + 'tooltip': None, + 'type': 'string', + 'unit': '', + 'unit_code': ''}, + 'Id': {'anyOf': [{'type': 'integer'}, + {'type': 'null'}], + 'category': 'Undefined', + 'description': '', + 'format': 'default', + 'guid': '958e6995-9f04-49d3-ba03-738b6bd66fd0', + 'guid_source': 'MXF', + 'id': 0, + 'ifc_data_type': 'IfcInteger', + 'name': 'Id', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': '', + 'revit_data_type': 'INTEGER', + 'section': 'Identity Data', + 'title': 'Id', + 'tooltip': None, + 'unit': '', + 'unit_code': ''}, + 'ManufacturerWebsite': {'anyOf': [{'type': 'string'}, + {'type': 'null'}], + 'category': 'Specifications', + 'description': '', + 'guid': '2e28aa00-71ac-4225-85be-b9fc09e4484e', + 'guid_source': 'BSDD', + 'id': 16, + 'ifc_data_type': 'IfcText', + 'name': 'ManufacturerWebsite', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_DistributionBoard', + 'revit_data_type': 'URL', + 'section': 'Manufacturer', + 'title': 'Manufacturer ' + 'Website', + 'tooltip': 'Website...', + 'unit': '', + 'unit_code': ''}, + 'Notes': {'anyOf': [{'type': 'string'}, + {'type': 'null'}], + 'autoui': 'aectemplater_ui.widgets.notes.MarkdownWidget', + 'category': 'Specifications', + 'description': 'free flowing notes section', + 'guid': '9faa8b0b-ab25-4dce-bb4d-3f8320522146', + 'guid_source': 'MXF', + 'id': 12, + 'ifc_data_type': 'IfcText', + 'name': 'Notes', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_DistributionBoard', + 'revit_data_type': 'TEXT', + 'section': 'Application', + 'title': 'Notes', + 'tooltip': '...', + 'unit': '', + 'unit_code': ''}, + 'OverallLength': {'anyOf': [{'type': 'number'}, + {'type': 'null'}], + 'category': 'Specifications', + 'description': '', + 'guid': '2c27007d-549f-4664-8232-5efdb8d7c1dc', + 'guid_source': 'MXF', + 'id': 13, + 'ifc_data_type': 'IfcLengthMeasure', + 'name': 'OverallLength', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_DistributionBoard', + 'revit_data_type': 'LENGTH', + 'section': 'Manufacturer', + 'title': 'Overall Length', + 'tooltip': None, + 'unit': 'mm', + 'unit_code': 'mm'}, + 'Symbol': {'category': 'Specifications', + 'default': '', + 'description': 'equipment type symbol. ' + 'Filename of PNG image', + 'guid': 'e30c1dbe-9dd5-4b20-b102-8cbbd07faa70', + 'guid_source': 'MXF', + 'id': 10, + 'ifc_data_type': 'IfcText', + 'name': 'Symbol', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'TEXT', + 'section': 'Identity Data', + 'title': 'Symbol', + 'tooltip': 'this is the same name as the ' + 'symbol imported in Revit for ' + 'schematics', + 'type': 'string', + 'unit': '', + 'unit_code': ''}, + 'TypeReference': {'category': 'Specifications', + 'default': 1, + 'description': 'equipment type ' + 'reference, integer ' + 'only. Refers to ' + 'equipment type, ' + 'there may be ' + 'multiple instances ' + 'of the same type', + 'guid': 'f2cb3fad-ff04-4e62-bffa-80d6d3fd2862', + 'guid_source': 'MXF', + 'id': 8, + 'ifc_data_type': 'IfcInteger', + 'name': 'TypeReference', + 'namespace_uri': None, + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_IdentityExtra', + 'revit_data_type': 'INTEGER', + 'section': 'Identity Data', + 'title': 'Type Reference', + 'tooltip': '', + 'type': 'integer', + 'unit': '', + 'unit_code': ''}, + 'Voltage': {'anyOf': [{'type': 'number'}, + {'type': 'null'}], + 'category': 'Specifications', + 'description': '', + 'guid': '10044af7-e223-443c-a89d-10b20f2b766e', + 'guid_source': 'BSDD', + 'id': 11, + 'ifc_data_type': 'IfcElectricVoltageMeasure', + 'name': 'Voltage', + 'namespace_uri': 'https://identifier.buildingsmart.org/uri/buildingsmart/ifc/4.3/prop/Voltage', + 'parameter_type': 'T', + 'property_value_kind': 'Single', + 'pset': 'Pset_DistributionBoard', + 'revit_data_type': 'ELECTRICAL_POTENTIAL', + 'section': 'Electrical', + 'title': 'Voltage', + 'tooltip': 'Voltage...', + 'unit': 'V', + 'unit_code': 'V'}}, + 'title': 'Distribution Board', + 'type': 'object'}, + 'title': 'Distribution Board', + 'type': 'array'} + + +fpth = pathlib.Path("type-spec-test-schema.py") +model_file = pydantic_model_file_from_json_schema(type_spec_json_schema, fpth) +model = pydantic_model_from_json_schema(type_spec_json_schema) +tsedittsvwdiff = EditTsvWithDiff(transposed=True, model=model, primary_key_name = "Id", value=[{'Abbreviation': 'DB', + 'TypeReference': 1, + 'Symbol': '', + 'ClassificationUniclassProductNumber': 'Pr_60_70_22_22', + 'ClassificationUniclassSystemNumber': '', + 'FunctionReference': None, + 'Notes': None, + 'OverallLength': None, + 'ManufacturerWebsite': 'https://maxfordham.com/', + 'Voltage': None, + 'Id': 2}] +) +display(tsedittsvwdiff) + +if __name__ == "__main__": + display(tsedittsvwdiff.text.value) + display(tsedittsvwdiff.value) + +# if __name__ == "__main__": +# display(tsedittsvwdiff.value) + # display(tsedittsvwdiff.text.value) + # cleaned_val = xdg.read_records(tsedittsvwdiff.value, model, only_for=["FunctionReference", "Notes", "Voltage", "OverallLength"]) + # display(cleaned_val) + +# if __name__ == "__main__": +# display(tsedittsvwdiff.value) +# cleaned_val = xdg.read_records(tsedittsvwdiff.value, model, only_for=["FunctionReference", "Notes"]) +# display(cleaned_val) +# tsedittsvwdiff.value = xdg.read_records(tsedittsvwdiff.value, model, only_for=["FunctionReference", "Notes"]) +# display(tsedittsvwdiff.value) + # display(tsedittsvwdiff.ddiff.diff) + + diff --git a/docs/edit_tsv_widgets.ipynb b/docs/edit_tsv_widgets.ipynb new file mode 100644 index 00000000..cef76f23 --- /dev/null +++ b/docs/edit_tsv_widgets.ipynb @@ -0,0 +1,381 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2b4ea1ab", + "metadata": {}, + "source": [ + "\n", + "# EditTsv\n", + "\n", + "This notebook showcases two widgets for working with tabular data using **ipyautoui**:\n", + "\n", + "- **`EditTsvWithDiff`**: paste TSV/CSV-style text (e.g., from Excel), validate against a Pydantic model, review changes with **DeepDiff**, then **confirm or cancel**.\n", + "- **`EditTsvFileUpload`**: upload an **Excel (.xlsx)** file; data is parsed/validated just like the text editor version, but the text area is **disabled**.\n", + "- **`EditTsvWithDiffAndKeyMapping`**: Similar to EditTsvWithDiff, but instead of diffing being done based on a primary key, a composite key is used, based on the `unique_fields` trait. It also modifies the pydantic model to exclude the fields specified in the `exclude_fields_from_model` trait.\n", + "\n", + "> In **all** cases you must ensure the Pydantic model (schema) matches the expected file columns and constraints.\n" + ] + }, + { + "cell_type": "markdown", + "id": "99cf3c04", + "metadata": {}, + "source": [ + "\n", + "## Define the Pydantic schema\n", + "\n", + "We declare a `Test` model for one row and a `TestArray` root model (list of rows). \n", + "Key points:\n", + "\n", + "- Numeric constraints (e.g., `ge=1, le=10`) are captured in the schema and used for validation and Excel data validation.\n", + "- Enums (e.g., `MyColor`) become dropdowns in Excel.\n", + "- `b_calcfloat` is frozen/read-only and can include a **formula** hint (used by the Excel writer).\n", + "- `json_schema_extra` carries UI hints (e.g., `section`, `formula`, `datagrid_index_name`).\n", + "\n", + "> The **same schema** is used by both widgets.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "96f48b4f", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "# Imports and schema\n", + "from typing import Optional, List, Literal\n", + "from datetime import date, datetime, time, timedelta\n", + "from enum import Enum\n", + "from pydantic import BaseModel, Field, RootModel, ConfigDict, StringConstraints, conint, constr\n", + "from ipyautoui.custom.edittsv import EditTsvWithDiff, EditTsvFileUpload\n", + "from ipyautoui.custom.edittsv_with_diff_and_key_mapping import EditTsvWithDiffAndKeyMapping\n", + "from ipyautoui.custom.fileupload import TempFileUploadProcessor\n", + "from typing_extensions import Annotated\n", + "import xlsxdatagrid as xdg\n", + "import pathlib\n", + "import ipywidgets as w\n", + "from IPython.display import display\n", + "\n", + "class MyColor(str, Enum):\n", + " red = 'red'\n", + " green = 'green'\n", + " blue = 'blue'\n", + "\n", + "class Test(BaseModel):\n", + " a_constrainedint: Annotated[int, Field(ge=1, le=10)] = Field(\n", + " 3,\n", + " title=\"A Constrainedint\",\n", + " json_schema_extra=dict(section=\"numeric\"),\n", + " )\n", + "\n", + " a_int: Optional[int] = Field(\n", + " 1,\n", + " title=\"A Int\",\n", + " json_schema_extra=dict(section=\"numeric\"),\n", + " )\n", + "\n", + " b_calcfloat: Optional[float] = Field(\n", + " None,\n", + " title=\"B Calcfloat\",\n", + " description=\"calc value\",\n", + " frozen=True,\n", + " json_schema_extra=dict(section=\"numeric\", formula=\"a_int * b_float\"),\n", + " )\n", + "\n", + " b_float: Optional[float] = Field(\n", + " 1.5,\n", + " title=\"B Float\",\n", + " json_schema_extra=dict(section=\"numeric\"),\n", + " )\n", + "\n", + " c_constrainedstr: Annotated[str, StringConstraints(min_length=0, max_length=20)] = Field(\n", + " \"string\",\n", + " title=\"C Constrainedstr\",\n", + " json_schema_extra=dict(section=\"unicode\"),\n", + " )\n", + "\n", + " c_str: Optional[str] = Field(\n", + " \"string\",\n", + " title=\"C Str\",\n", + " json_schema_extra=dict(section=\"unicode\"),\n", + " )\n", + "\n", + " d_enum: MyColor = Field(\n", + " \"red\",\n", + " title=\"D Enum\",\n", + " json_schema_extra=dict(section=\"unicode\"),\n", + " )\n", + "\n", + " e_bool: Optional[bool] = Field(\n", + " True,\n", + " title=\"E Bool\",\n", + " json_schema_extra=dict(section=\"boolean\"),\n", + " )\n", + "\n", + " f_date: Optional[date] = Field(\n", + " \"2024-06-06\",\n", + " title=\"F Date\",\n", + " json_schema_extra=dict(section=\"datetime\"),\n", + " )\n", + "\n", + " g_datetime: Optional[datetime] = Field(\n", + " \"2024-06-06T10:42:54.822063\",\n", + " title=\"G Datetime\",\n", + " json_schema_extra=dict(section=\"datetime\"),\n", + " )\n", + "\n", + " h_time: Optional[time] = Field(\n", + " \"10:42:54.822257\",\n", + " title=\"H Time\",\n", + " json_schema_extra=dict(section=\"datetime\"),\n", + " )\n", + "\n", + " i_duration: Optional[timedelta] = Field(\n", + " \"PT2H33M3S\",\n", + " title=\"I Duration\",\n", + " json_schema_extra=dict(section=\"datetime\"),\n", + " )\n", + "\n", + " model_config = ConfigDict(\n", + " title=\"Test\",\n", + " json_schema_extra=dict(required=[\"d_enum\", \"b_calcfloat\"]),\n", + " )\n", + "\n", + "class TestArray(RootModel[List[Test]]):\n", + " model_config = ConfigDict(\n", + " title=\"TestArrayTransposed\",\n", + " json_schema_extra=dict(datagrid_index_name=(\"section\", \"title\", \"name\")),\n", + " )\n", + " root: List[Test]\n" + ] + }, + { + "cell_type": "markdown", + "id": "2f2ea393", + "metadata": {}, + "source": [ + "\n", + "## `EditTsvWithDiff` — paste TSV, validate, review diff, confirm\n", + "\n", + "**What it does**\n", + "- Accepts TSV text (e.g., copy from Excel → paste).\n", + "- Parses and validates rows using `TestArray`.\n", + "- On **Save** (`💾`), shows a DeepDiff view of changes.\n", + "- You can **confirm** ✅ to finalize (and call your `fn_upload`), or **cancel** 🚫 to go back and edit.\n", + "\n", + "**How to use**\n", + "1. Paste TSV data into the text area. The first row should be the headers derived from your schema.\n", + "2. Click the **save** button.\n", + "3. Review the diff; click **✔️** to confirm or **⛔** to cancel.\n", + "\n", + "> Make sure `primary_key_name`, `header_depth`, and `transposed` match how your data is structured.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "926f3bdb", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e3f61b76135f4f46bad55fdf026facd6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "EditTsvWithDiff(children=(VBox(), HBox(children=(VBox(children=(Button(icon='copy', layout=Layout(width='44px'…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "# Example: EditTsvWithDiff\n", + "edit_tsv_w_diff = EditTsvWithDiff(\n", + " model=TestArray,\n", + " transposed=False,\n", + " primary_key_name=\"a_int\",\n", + " header_depth=3,\n", + " exclude_metadata=True,\n", + ")\n", + "display(edit_tsv_w_diff)\n" + ] + }, + { + "cell_type": "markdown", + "id": "99280d23", + "metadata": {}, + "source": [ + "\n", + "## `EditTsvFileUpload` — upload Excel, validate, review diff, confirm\n", + "\n", + "**What it does**\n", + "- Disables manual text editing.\n", + "- Lets you **upload** a `.xlsx` file.\n", + "- Parses and validates rows using `TestArray`.\n", + "- On **Save**, shows a DeepDiff of changes before confirming.\n", + "\n", + "**How to use**\n", + "1. Click the upload button to pick an Excel file.\n", + "2. The widget reads the sheet using the same schema validations.\n", + "3. Click **save** to review and confirm changes.\n", + "\n", + "> The Excel must match the schema (column names and constraints). If your schema is transposed in display, set `transposed=True`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "ee9e0bc6", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9509cb50fabd4bbf9740c33e8c2dd98c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "EditTsvFileUpload(children=(VBox(), HBox(children=(VBox(children=(Button(icon='copy', layout=Layout(width='44p…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "# Example: EditTsvFileUpload\n", + "edit_tsv_upload = EditTsvFileUpload(\n", + " model=TestArray,\n", + " transposed=True,\n", + " primary_key_name=\"a_int\",\n", + " header_depth=3,\n", + " exclude_metadata=True,\n", + ")\n", + "display(edit_tsv_upload)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "00bc9045-da12-4409-b189-5d9c75758be6", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "903eae6df7e145ff8f9e6eeff682df6c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "EditTsvWithDiffAndKeyMapping(children=(VBox(), HBox(children=(VBox(children=(Button(icon='copy', layout=Layout…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "# Example: EditTsvWithDiffAndKeyMapping\n", + "value= [\n", + " {\n", + " 'a_int': '1',\n", + " 'a_constrainedint': '3',\n", + " 'b_float': '1.5',\n", + " 'c_str': 'string',\n", + " 'c_constrainedstr': 'string',\n", + " 'd_enum': 'green',\n", + " 'e_bool': 'TRUE',\n", + " 'f_date': '2025-11-03',\n", + " 'g_datetime': '2025-11-03T13:17:53+00:00',\n", + " 'h_time': '13:17:53+00:00',\n", + " 'i_duration': 'PT2H33M03S',\n", + " 'b_calcfloat': '1.5'\n", + " },\n", + " {\n", + " 'a_int': '2',\n", + " 'a_constrainedint': '3',\n", + " 'b_float': '2.5',\n", + " 'c_str': 'asdf',\n", + " 'c_constrainedstr': 'string',\n", + " 'd_enum': 'green',\n", + " 'e_bool': 'TRUE',\n", + " 'f_date': '2025-11-03',\n", + " 'g_datetime': '2025-11-03T13:17:53+00:00',\n", + " 'h_time': '13:17:53+00:00',\n", + " 'i_duration': 'PT2H33M03S',\n", + " 'b_calcfloat': '5'\n", + " },\n", + " {\n", + " 'a_int': '3',\n", + " 'a_constrainedint': '3',\n", + " 'b_float': '3.5',\n", + " 'c_str': 'bluey',\n", + " 'c_constrainedstr': 'string',\n", + " 'd_enum': 'blue',\n", + " 'e_bool': 'FALSE',\n", + " 'f_date': '2025-11-03',\n", + " 'g_datetime': '2025-11-03T13:17:53+00:00',\n", + " 'h_time': '13:17:53+00:00',\n", + " 'i_duration': 'PT2H33M03S',\n", + " 'b_calcfloat': '10.5'\n", + " }\n", + "]\n", + "\n", + "edit_tsv_w_diff_and_key_mapping = EditTsvWithDiffAndKeyMapping(\n", + " model=TestArray,\n", + " value=value,\n", + " transposed=False,\n", + " unique_id_fields=[\"c_str\", \"c_constrainedstr\", \"d_enum\"],\n", + " exclude_metadata=True,\n", + ")\n", + "display(edit_tsv_w_diff_and_key_mapping)\n" + ] + }, + { + "cell_type": "markdown", + "id": "c314af6c", + "metadata": {}, + "source": [ + "\n", + "## Notes & Troubleshooting\n", + "\n", + "- If constraints (e.g., enum dropdowns or min/max) don't show up in Excel exports, check that your Pydantic fields carry the appropriate constraints (e.g., `Field(ge=..., le=...)`, `Enum`, or `StringConstraints`).\n", + "- `frozen=True` on a field makes it read-only and is treated as `readOnly` in JSON Schema.\n", + "- Ensure your headers match the schema; mis-ordered or missing headers will produce validation errors.\n", + "- `primary_key_name` should point to a unique field in your data to show meaningful row-level diffs.\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/editgrid.qmd b/docs/editgrid.qmd index 2b30df14..c26aa876 100644 --- a/docs/editgrid.qmd +++ b/docs/editgrid.qmd @@ -1,5 +1,16 @@ --- -title: "EditGrid" +title: EditGrid +jupyter: + jupytext: + text_representation: + extension: .qmd + format_name: quarto + format_version: '1.0' + jupytext_version: 1.18.1 + kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 --- ::: {.callout-warning} @@ -26,12 +37,9 @@ class TestDataFrame(BaseModel): """a description of TestDataFrame""" a: str df: ty.List[DataFrameCols] = Field([DataFrameCols().model_dump(mode="json")], format="dataframe") - ``` - ```{python} - from ipyautoui.custom.editgrid import EditGrid class TestDataFrame(RootModel): """a description of TestDataFrame""" @@ -54,14 +62,9 @@ egrid.value = [ {"string": "morning", "integer": 5, "floater": 3.14, "something_else": 12}, {"string": "number", "integer": 3, "floater": 3.14, "something_else": 123}, ] - ``` - - - ```{python} - from pydantic import RootModel # Test: EditGrid instance with multi-indexing. @@ -121,8 +124,6 @@ display(editgrid) ``` ```{python} - - class TestProperties(BaseModel): string: str nullable_string: ty.Optional[str] = None @@ -144,44 +145,20 @@ egrid = EditGrid( egrid ``` - - - ```{python} -from ipyautoui.autoobject import AutoObjectForm -from ipyautoui.demo_schemas import CoreIpywidgets -ui = AutoObjectForm.from_pydantic_model(CoreIpywidgets) -ui +eg = EditGrid(schema=None) +eg ``` - - ```{python} -# Row Validation (WIP) - -from pydantic import RootModel - - -class Sub(BaseModel): - a: str = "a" - b: int = 1 - - -class Table(RootModel): - root: list[Sub] - - -class NestedTable(BaseModel): - table: list[Sub] +eg.ui_edit +``` +```{python} +eg.row_schema +``` -# for simple root tables it is simple to extract the pydantic model for the row -RowSchema = Table.__pydantic_core_schema__["schema"]["items_schema"]["cls"] -print(RowSchema) +```{python} +eg.update_from_schema(TestGridSchema) +``` -# more difficult for nested rows -NestedRowSchema = NestedTable.__pydantic_core_schema__["schema"]["fields"]["table"][ - "schema" -]["items_schema"]["cls"] -print(NestedRowSchema) -``` \ No newline at end of file diff --git a/docs/generate-model-file.py b/docs/generate-model-file.py new file mode 100644 index 00000000..e8daf5a5 --- /dev/null +++ b/docs/generate-model-file.py @@ -0,0 +1,564 @@ +import pathlib +from ipyautoui.automapschema import pydantic_model_file_from_json_schema + +predicted_energy_use_item = {'$defs': {'EnergyEndUse': {'enum': ['Heating', + 'Domestic Hot Water', + 'Heating & Domestic Hot Water', + 'Cooling', + 'Auxiliary', + 'Lighting', + 'Small Power', + 'IT/Servers', + 'PV Generation', + 'Lifts', + 'Catering', + 'Other', + 'Unknown'], + 'title': 'EnergyEndUse', + 'type': 'string'}, + 'EnergyEndUseTag': {'enum': ['Heating', + 'Heating - Distribution Loss', + 'Domestic Hot Water', + 'Cooling', + 'Auxiliary', + 'Lighting', + 'Lighting - External', + 'Small Power', + 'IT/Servers', + 'PV Generation', + 'Pool', + 'Lifts', + 'Catering', + 'Other', + 'Unknown'], + 'title': 'EnergyEndUseTag', + 'type': 'string'}, + 'FuelType': {'enum': ['Electricity', + 'Gas - NG', + 'Gas - Biogas', + 'Gas - LPG', + 'Gas - Other', + 'Unknown', + 'Unset'], + 'title': 'FuelType', + 'type': 'string'}, + 'OperationalEnergyAnalysisType': {'enum': ['Part L', + 'Scottish Part L', + 'TM54', + 'Passivhaus', + 'Custom'], + 'title': 'OperationalEnergyAnalysisType', + 'type': 'string'}, + 'PredictedEnergyUseItem': {'properties': {'InstanceReference': {'anyOf': [{'type': 'integer'}, + {'type': 'null'}], + 'default': 1, + 'description': 'equipment instance reference, integer only. Refers to equipment instance.', + 'title': 'Instance Reference'}, + 'BuildingID': {'anyOf': [{'type': 'string'}, {'type': 'null'}], + 'default': None, + 'description': 'A unique identifier within the project assigned to a building', + 'title': 'Building ID'}, + 'AssessmentDate': {'anyOf': [{'format': 'date', 'type': 'string'}, + {'type': 'null'}], + 'default': None, + 'description': 'Date on which the overall condition is assessed', + 'title': 'Assessment Date'}, + 'Notes': {'anyOf': [{'type': 'string'}, {'type': 'null'}], + 'default': None, + 'description': '', + 'title': 'Notes'}, + 'OperationalEnergyAnalysisType': {'anyOf': [{'$ref': '#/$defs/OperationalEnergyAnalysisType'}, + {'type': 'null'}], + 'default': None, + 'description': 'defines the type of analysis', + 'title': 'Operational Energy Analysis Type'}, + 'FuelType': {'anyOf': [{'$ref': '#/$defs/FuelType'}, {'type': 'null'}], + 'default': None, + 'description': '', + 'title': 'Fuel Type'}, + 'EnergyConsumption': {'anyOf': [{'type': 'number'}, {'type': 'null'}], + 'default': None, + 'description': 'Annual energy consumption requirement. NOTE: PV Generation should be a -ve value.', + 'title': 'Energy Consumption'}, + 'EnergyEndUse': {'anyOf': [{'$ref': '#/$defs/EnergyEndUse'}, + {'type': 'null'}], + 'default': None, + 'description': 'The end-use of the energy consumption within a building. Pick the most appropriate.', + 'title': 'Energy End Use'}, + 'EnergyEndUseTags': {'anyOf': [{'items': {'$ref': '#/$defs/EnergyEndUseTag'}, + 'type': 'array'}, + {'type': 'null'}], + 'default': None, + 'description': 'Avoid where possible. Use only when the "Energy End Use" does not correctly describe usage (e.g. mostly DHW, but add a lighting tag to indicate some lights).', + 'title': 'Energy End Use Tags'}, + 'TypeMark': {'anyOf': [{'type': 'string'}, {'type': 'null'}], + 'default': None, + 'description': '', + 'title': 'Type Mark'}, + 'TypeSpecId': {'anyOf': [{'type': 'integer'}, {'type': 'null'}], + 'default': None, + 'description': '', + 'title': 'Type Spec Id'}, + 'Id': {'anyOf': [{'type': 'integer'}, {'type': 'null'}], + 'default': None, + 'description': '', + 'title': 'Id'}}, + 'title': 'PredictedEnergyUseItem', + 'type': 'object'}}, + 'items': {'$ref': '#/$defs/PredictedEnergyUseItem'}, + 'title': 'PredictedEnergyUse', + 'type': 'array'} + +fpth=pathlib.Path("pydantic-model-predicted_energy_use_item.py") +model_file = pydantic_model_file_from_json_schema(predicted_energy_use_item, fpth) + + + +project_building_area_schema = {'title': 'Project Building Area', + 'type': 'array', + 'format': 'DataFrame', + 'hide_nan': True, + 'datagrid_index_name': ['section', 'title'], + 'items': {'title': 'Project Buildings', + 'description': 'Add any buildings that exist within the project', + 'type': 'object', + 'parameter_type': 'T', + 'override_units': True, + 'classification': '', + 'properties': {'Abbreviation': {'enum': ['BLDG'], + 'type': 'string', + 'revit_data_type': 'TEXT', + 'ifc_data_type': 'IfcText', + 'namespace_uri': None, + 'guid': '4ec7e9b3-b1f0-4b76-b0d4-9dd1338b8c2f', + 'guid_source': 'MXF', + 'title': 'Abbreviation', + 'name': 'Abbreviation', + 'description': 'equipment type abbreviation, alphabetic characters only, variable length, between 2 and 6 characters', + 'category': 'Specifications', + 'section': 'Identity Data', + 'tooltip': 'asset abbreviation is defined by the [BDNS](https://github.com/theodi/BDNS). Abbreviations must be from those defined in the [BDNS_Abbreviations_Register.csv](https://github.com/theodi/BDNS/blob/master/BDNS_Abbreviations_Register.csv)', + 'property_value_kind': 'Single', + 'unit': '', + 'unit_code': '', + 'parameter_type': 'T', + 'pset': 'Pset_IdentityCore', + 'id': 2696, + 'default': 'BLDG'}, + 'TypeReference': {'type': 'integer', + 'revit_data_type': 'INTEGER', + 'ifc_data_type': 'IfcInteger', + 'namespace_uri': None, + 'guid': 'f2cb3fad-ff04-4e62-bffa-80d6d3fd2862', + 'guid_source': 'MXF', + 'title': 'Type Reference', + 'name': 'TypeReference', + 'description': 'equipment type reference, integer only. Refers to equipment type, there may be multiple instances of the same type', + 'category': 'Specifications', + 'section': 'Identity Data', + 'tooltip': '', + 'property_value_kind': 'Single', + 'unit': '', + 'unit_code': '', + 'parameter_type': 'T', + 'pset': 'Pset_IdentityCore', + 'id': 2698, + 'default': 1}, + 'TargetYear': {'enum': [2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032, + 2033, + 2034, + 2035, + 2036, + 2037, + 2038, + 2039, + 2040, + 2050], + 'revit_data_type': 'INTEGER', + 'ifc_data_type': 'IfcInteger', + 'namespace_uri': None, + 'guid': '38d4ec6a-9fbb-458f-88a2-b29b33c1ec48', + 'guid_source': 'MXF', + 'title': 'Target Year', + 'name': 'TargetYear', + 'description': 'Net Zero Carbon targets change annually. This defined what year the Benchmark Targets should be defined by.', + 'category': 'Specifications', + 'section': 'Identity Data', + 'tooltip': None, + 'property_value_kind': 'Single', + 'unit': '', + 'unit_code': '', + 'parameter_type': 'T', + 'pset': 'BuildingArea', + 'id': 3090, + 'type': 'integer'}, + 'Name': {'revit_data_type': 'TEXT', + 'ifc_data_type': 'IfcText', + 'namespace_uri': 'https://identifier.buildingsmart.org/uri/buildingsmart/ifc/4.3/prop/Name', + 'guid': 'a13b623a-94ea-4864-a42c-76d3a40acd47', + 'guid_source': 'MXF', + 'title': 'Building Name', + 'name': 'Name', + 'description': 'Optional. Add a building name as used in the project for easier identification.', + 'category': 'Facilities/Asset Management', + 'section': 'Identity Data', + 'tooltip': None, + 'property_value_kind': 'Single', + 'unit': '', + 'unit_code': '', + 'parameter_type': 'T', + 'pset': 'BuildingArea', + 'id': 3091, + 'type': 'string'}, + 'Id': {'format': 'default', + 'revit_data_type': 'INTEGER', + 'ifc_data_type': 'IfcInteger', + 'namespace_uri': None, + 'guid': '958e6995-9f04-49d3-ba03-738b6bd66fd0', + 'guid_source': 'MXF', + 'title': 'Id', + 'name': 'Id', + 'description': '', + 'category': 'Undefined', + 'section': 'Identity Data', + 'tooltip': None, + 'property_value_kind': 'Single', + 'unit': '', + 'unit_code': '', + 'parameter_type': 'T', + 'pset': '', + 'id': 0, + 'type': 'integer'}}, + 'id': 835}} + +fpth=pathlib.Path("pydantic-model-project-building-area.py") +model_file = pydantic_model_file_from_json_schema(project_building_area_schema, fpth) + +building_type_schema = {'$defs': {'BuildingType': {'enum': ['Commercial Resi - Student Residential', + 'Commercial Resi - Care Home', + 'Culture & Enterainment - Performance', + 'Culture & Enterainment - Collection (e.g. museum)', + 'Culture & Enterainment - Archive', + 'Healthcare', + 'Healthcare - Acute Trust', + 'Healthcare - Care Trust', + 'Healthcare - Community Trust', + 'Healthcare - Mental Health & Learning Trust', + 'Healthcare - Ambulance Trust', + 'Higher Education', + 'Homes - Single family homes', + 'Homes - Flats', + 'Hotel', + 'Office - General', + 'Office - Call Centre', + 'Office - Trading Floors', + 'Retail - Supermarket', + 'Retail - High street retail e.g. dept. store', + 'Retail - F&B without catering (a)', + 'Retail - F&B with catering (b)', + 'Retail - Landlord areas (c)', + 'Retail - warehouse', + 'School - Early years', + 'School - Primary', + 'School - Secondary or SEN', + 'Science and Technology', + 'Sport & Leisure - Dry', + 'Sport & Leisure - Wet', + 'Sport & Leisure - Fitness', + 'Storage & Distribution - Unconditioned', + 'Storage & Distribution - Conditioned', + 'Storage & Distribution - Cold Store'], + 'title': 'BuildingType', + 'type': 'string'}, + 'ProjectBuildingAreaItem': {'properties': {'InstanceReference': {'anyOf': [{'type': 'integer'}, + {'type': 'null'}], + 'default': 1, + 'description': 'equipment instance reference, integer only. Refers to equipment instance.', + 'title': 'Instance Reference'}, + 'BuildingType': {'anyOf': [{'$ref': '#/$defs/BuildingType'}, + {'type': 'null'}], + 'default': None, + 'description': 'Description of what the building (or subset of building) is used for. Must match with types from reference XXX', + 'title': 'Building Type'}, + 'GrossInternalArea': {'anyOf': [{'type': 'number'}, {'type': 'null'}], + 'default': None, + 'description': 'all area internal of the perimeter walls of the building (not including the perimeter wall build-up).\n\nhttps://www.designingbuildings.co.uk/wiki/Gross_internal_area_GIA', + 'title': 'Gross Internal Area'}, + 'IsNewBuild': {'anyOf': [{'type': 'boolean'}, {'type': 'null'}], + 'default': None, + 'description': 'is the building (or subset of building) a new build or refurb?', + 'title': 'Is New Build'}, + 'TypeMark': {'anyOf': [{'type': 'string'}, {'type': 'null'}], + 'default': None, + 'description': 'Select the building to link the area to', + 'title': 'Building ID'}, + 'TypeSpecId': {'anyOf': [{'type': 'integer'}, {'type': 'null'}], + 'default': None, + 'description': '', + 'title': 'Type Spec Id'}, + 'Id': {'anyOf': [{'type': 'integer'}, {'type': 'null'}], + 'default': None, + 'description': '', + 'title': 'Id'}}, + 'title': 'ProjectBuildingAreaItem', + 'type': 'object'}}, + 'items': {'$ref': '#/$defs/ProjectBuildingAreaItem'}, + 'title': 'ProjectBuildingArea', + 'type': 'array'} + +fpth=pathlib.Path("pydantic-model-building-type.py") +model_file = pydantic_model_file_from_json_schema(building_type_schema, fpth) + +uset_type_area_schema = {'title': 'Project Building Area', + 'type': 'array', + 'format': 'DataFrame', + 'hide_nan': True, + 'datagrid_index_name': ['section', 'title', 'unit'], + 'items': {'title': 'Project Building Area', + 'description': 'Entry for the area of a building or sub-section of a building', + 'type': 'object', + 'parameter_type': 'I', + 'override_units': True, + 'classification': '', + 'properties': {'InstanceReference': {'type': 'integer', + 'revit_data_type': 'INTEGER', + 'ifc_data_type': 'IfcInteger', + 'namespace_uri': None, + 'guid': '2705c5f3-e588-4d32-aac4-3bba358c898b', + 'guid_source': 'MXF', + 'title': 'Instance Reference', + 'name': 'InstanceReference', + 'description': 'equipment instance reference, integer only. Refers to equipment instance.', + 'category': 'Specifications', + 'section': 'Identity Data', + 'tooltip': '', + 'property_value_kind': 'Single', + 'unit': '', + 'unit_code': '', + 'parameter_type': 'I', + 'pset': 'Pset_IdentityCore', + 'id': 2866, + 'default': 1}, + 'BuildingType': {'enum': ['Commercial Resi - Student Residential', + 'Commercial Resi - Care Home', + 'Culture & Enterainment - Performance', + 'Culture & Enterainment - Collection (e.g. museum)', + 'Culture & Enterainment - Archive', + 'Healthcare', + 'Healthcare - Acute Trust', + 'Healthcare - Care Trust', + 'Healthcare - Community Trust', + 'Healthcare - Mental Health & Learning Trust', + 'Healthcare - Ambulance Trust', + 'Higher Education', + 'Homes - Single family homes', + 'Homes - Flats', + 'Hotel', + 'Office - General', + 'Office - Call Centre', + 'Office - Trading Floors', + 'Retail - Supermarket', + 'Retail - High street retail e.g. dept. store', + 'Retail - F&B without catering (a)', + 'Retail - F&B with catering (b)', + 'Retail - Landlord areas (c)', + 'Retail - warehouse', + 'School - Early years', + 'School - Primary', + 'School - Secondary or SEN', + 'Science and Technology', + 'Sport & Leisure - Dry', + 'Sport & Leisure - Wet', + 'Sport & Leisure - Fitness', + 'Storage & Distribution - Unconditioned', + 'Storage & Distribution - Conditioned', + 'Storage & Distribution - Cold Store'], + 'revit_data_type': 'TEXT', + 'ifc_data_type': 'IfcText', + 'namespace_uri': None, + 'guid': 'c3108630-93b0-4bd2-b30c-6e37f370aea8', + 'guid_source': 'MXF', + 'title': 'Building Type', + 'name': 'BuildingType', + 'description': 'Description of what the building (or subset of building) is used for. Must match with types from reference XXX', + 'category': 'Specifications', + 'section': 'Application', + 'tooltip': None, + 'property_value_kind': 'Single', + 'unit': '', + 'unit_code': '', + 'parameter_type': 'I', + 'pset': 'BuildingArea', + 'id': 3088, + 'type': 'string'}, + 'GrossInternalArea': {'revit_data_type': 'AREA', + 'ifc_data_type': 'IfcAreaMeasure', + 'namespace_uri': None, + 'guid': '0f5ba3d3-d2eb-4b94-b6f1-faed9db068f3', + 'guid_source': 'MXF', + 'title': 'Gross Internal Area', + 'name': 'GrossInternalArea', + 'description': 'all area internal of the perimeter walls of the building (not including the perimeter wall build-up).\n\nhttps://www.designingbuildings.co.uk/wiki/Gross_internal_area_GIA', + 'category': 'Specifications', + 'section': 'Dimensions', + 'tooltip': None, + 'property_value_kind': 'Single', + 'unit': 'm²', + 'unit_code': 'm**2', + 'parameter_type': 'I', + 'pset': 'BuildingArea', + 'id': 3086, + 'type': 'number'}, + 'IsNewBuild': {'revit_data_type': 'YESNO', + 'ifc_data_type': 'IfcBoolean', + 'namespace_uri': None, + 'guid': '1d2bcf6f-885d-4434-bd99-af248eb97ed2', + 'guid_source': 'MXF', + 'title': 'Is New Build', + 'name': 'IsNewBuild', + 'description': 'is the building (or subset of building) a new build or refurb?', + 'category': 'Specifications', + 'section': 'Dimensions', + 'tooltip': None, + 'property_value_kind': 'Single', + 'unit': '', + 'unit_code': '', + 'parameter_type': 'I', + 'pset': 'BuildingArea', + 'id': 3089, + 'type': 'boolean'}, + 'TypeMark': {'enum': ['BLDG-1', 'BLDG-3', 'BLDG-4'], + 'type': 'string', + 'revit_data_type': 'TEXT', + 'ifc_data_type': 'IfcText', + 'namespace_uri': None, + 'guid': '95cba5f9-706b-49e1-9100-c423f2c1f6f5', + 'guid_source': 'MXF', + 'title': 'Building ID', + 'name': 'BuildingID', + 'description': 'Select the building to link the area to', + 'category': 'Undefined', + 'section': 'Identity Data', + 'tooltip': None, + 'property_value_kind': 'Single', + 'unit': '', + 'unit_code': '', + 'parameter_type': 'I', + 'pset': '', + 'id': 0, + 'autoui': 'ipywidgets.Dropdown'}, + 'TypeSpecId': {'format': 'default', + 'revit_data_type': 'INTEGER', + 'ifc_data_type': 'IfcInteger', + 'namespace_uri': None, + 'guid': 'f5bdea0b-8648-43a6-b85a-5cc443d86e8e', + 'guid_source': 'MXF', + 'title': 'Type Spec Id', + 'name': 'TypeSpecId', + 'description': '', + 'category': 'Undefined', + 'section': 'Identity Data', + 'tooltip': None, + 'property_value_kind': 'Single', + 'unit': '', + 'unit_code': '', + 'parameter_type': 'I', + 'pset': '', + 'id': 0, + 'type': 'integer'}, + 'Id': {'format': 'default', + 'revit_data_type': 'INTEGER', + 'ifc_data_type': 'IfcInteger', + 'namespace_uri': None, + 'guid': '958e6995-9f04-49d3-ba03-738b6bd66fd0', + 'guid_source': 'MXF', + 'title': 'Id', + 'name': 'Id', + 'description': '', + 'category': 'Undefined', + 'section': 'Identity Data', + 'tooltip': None, + 'property_value_kind': 'Single', + 'unit': '', + 'unit_code': '', + 'parameter_type': 'I', + 'pset': '', + 'id': 0, + 'type': 'integer'}}, + 'id': 835}} + +fpth=pathlib.Path("pydantic-model-use-type-area.py") +model_file = pydantic_model_file_from_json_schema(uset_type_area_schema, fpth) + +# + +"""Pydantic Model with Regex validation on a field""" +regex_schema = { + "$defs": { + "Role": { + "enum": ["Admin", "User", "Guest"], + "title": "Role", + "type": "string" + }, + "UserItem": { + "title": "UserItem", + "type": "object", + "properties": { + "UserId": { + "anyOf": [ + { "type": "integer" }, + { "type": "null" } + ], + "default": None, + "description": "Numeric user ID", + "title": "User ID" + }, + "Username": { + "type": "string", + "title": "Username", + "description": "A username consisting of 3–20 alphanumeric characters or underscores", + "pattern": "^[A-Za-z0-9_]{3,20}$" + }, + "String": { + "type": "string", + "title": "String", + "description": "A regex string", + "pattern": "^[A-Za-z]{2}_(\\d{2})(_\\d{2}){0,3}$" + }, + "Tags": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-z0-9-]{1,32}$" + } + }, + { "type": "null" } + ], + "default": None, + "title": "Tags", + "description": "Optional list of lowercase tag identifiers" + } + }, + "required": ["Username"] + } + }, + "items": { + "$ref": "#/$defs/UserItem" + }, + "title": "UserList", + "type": "array" +} + +fpth=pathlib.Path("pydantic-model-regex_schema.py") +model_file = pydantic_model_file_from_json_schema(regex_schema, fpth) +# - + + diff --git a/docs/import-export-io-test.py b/docs/import-export-io-test.py new file mode 100644 index 00000000..31841fc0 --- /dev/null +++ b/docs/import-export-io-test.py @@ -0,0 +1,147 @@ +# + +from typing import Optional, List, Literal +from datetime import date, datetime, time, timedelta +from enum import Enum +from pydantic import BaseModel, Field, RootModel, ConfigDict, StringConstraints, conint, constr +from ipyautoui.custom.edittsv import EditTsvWithDiff, EditTsvFileUpload +from ipyautoui.custom.fileupload import TempFileUploadProcessor +from typing_extensions import Annotated +import xlsxdatagrid as xdg +import pathlib +import ipywidgets as w + + +class MyColor(str, Enum): + red = 'red' + green = 'green' + blue = 'blue' + +class Test(BaseModel): + a_constrainedint: Annotated[int, Field(ge=1, le=10)] = Field( + 3, + title="A Constrainedint", + json_schema_extra=dict( + section="numeric", + ), + ) + + a_int: Optional[int] = Field( + 1, + title="A Int", + json_schema_extra=dict(section="numeric"), + ) + + b_calcfloat: Optional[float] = Field( + None, + title="B Calcfloat", + description="calc value", + frozen=True, + json_schema_extra=dict(section="numeric", formula="a_int * b_float"), + ) + + b_float: Optional[float] = Field( + 1.5, + title="B Float", + json_schema_extra=dict(section="numeric"), + ) + + c_constrainedstr: Annotated[str, StringConstraints(min_length=0, max_length=20)] = Field( + "string", + title="C Constrainedstr", + json_schema_extra=dict( + section="unicode", + ), + ) + + c_str: Optional[str] = Field( + "string", + title="C Str", + json_schema_extra=dict(section="unicode"), + ) + + d_enum: MyColor = Field( + "red", + title="D Enum", + json_schema_extra=dict( + section="unicode", + ), + ) + + e_bool: Optional[bool] = Field( + True, + title="E Bool", + json_schema_extra=dict(section="boolean"), + ) + + f_date: Optional[date] = Field( + "2024-06-06", + title="F Date", + json_schema_extra=dict(section="datetime"), + ) + + g_datetime: Optional[datetime] = Field( + "2024-06-06T10:42:54.822063", + title="G Datetime", + json_schema_extra=dict(section="datetime"), + ) + + h_time: Optional[time] = Field( + "10:42:54.822257", + title="H Time", + json_schema_extra=dict(section="datetime"), + ) + + i_duration: Optional[timedelta] = Field( + "PT2H33M3S", + title="I Duration", + json_schema_extra=dict(section="datetime"), + ) + + model_config = ConfigDict( + title="Test", + json_schema_extra=dict( + required=["d_enum", "b_calcfloat"], + ), + ) + + +class TestArray(RootModel[List[Test]]): + model_config = ConfigDict( + title="TestArrayTransposed", + json_schema_extra=dict( + datagrid_index_name=("section", "title", "name"), + ), + ) + root: List[Test] + + +# - +edit_tsv_w_diff = EditTsvWithDiff(model=TestArray, + transposed = True, + primary_key_name="a_int", + header_depth=3, + exclude_metadata=True, + ) +display(edit_tsv_w_diff) + + +# + + +edit_tsv_w_diff = EditTsvFileUpload(model=TestArray, + transposed = False, + primary_key_name="a_int", + header_depth=3, + exclude_metadata=False, + ) +display(edit_tsv_w_diff) + + +# - + +def process_file_callback(path: pathlib.Path): + value, errors = xdg.read_excel(path, is_transposed=False, header_depth=3,model=TestArray) + print(value) +upload_widget = TempFileUploadProcessor(fn_process=process_file_callback) +display(upload_widget) + + diff --git a/docs/int-enum-issue.py b/docs/int-enum-issue.py new file mode 100644 index 00000000..bbe37d10 --- /dev/null +++ b/docs/int-enum-issue.py @@ -0,0 +1,41 @@ +from datamodel_code_generator import DataModelType, InputFileType, generate +import json +import pathlib +import importlib.util + +model_json_schema = { + "title": "ExampleModel", + "type": "object", + "properties": { + "targetYear": { + "type": "integer", + "enum": [2025, 2030, 2050] + } + }, + "required": ["targetYear"] +} + +fpth = pathlib.Path("generated_model.py") + +generate( + input_=json.dumps(model_json_schema), + input_file_type=InputFileType.JsonSchema, + output=fpth, + output_model_type=DataModelType.PydanticV2BaseModel, + capitalise_enum_members=True, +) + +# ------ load the generated file ------ +spec = importlib.util.spec_from_file_location("generated_model", fpth) +module = importlib.util.module_from_spec(spec) +spec.loader.exec_module(module) + +ExampleModel = module.ExampleModel +TargetYear = module.TargetYear + +ExampleModel.model_rebuild(_types_namespace={"TargetYear": TargetYear}) + +print(ExampleModel.model_validate({"targetYear": 2025})) # ✅ works +print(ExampleModel.model_validate({"targetYear": "2025"})) # ❌ fails + + diff --git a/docs/row-validation.ipynb b/docs/row-validation.ipynb new file mode 100644 index 00000000..046ce755 --- /dev/null +++ b/docs/row-validation.ipynb @@ -0,0 +1,84 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "de1360df-0548-42e6-94f3-e2009547df13", + "metadata": {}, + "source": [ + "# Row Validation (WIP)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "6eefc667-7959-412e-9ca0-414915ccf511", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n" + ] + } + ], + "source": [ + "from pydantic import RootModel, BaseModel\n", + "\n", + "\n", + "class Sub(BaseModel):\n", + " a: str = \"a\"\n", + " b: int = 1\n", + "\n", + "\n", + "class Table(RootModel):\n", + " root: list[Sub]\n", + "\n", + "\n", + "class NestedTable(BaseModel):\n", + " table: list[Sub]\n", + "\n", + "\n", + "# for simple root tables it is simple to extract the pydantic model for the row\n", + "RowSchema = Table.__pydantic_core_schema__[\"schema\"][\"items_schema\"][\"cls\"]\n", + "print(RowSchema)\n", + "\n", + "# more difficult for nested rows\n", + "NestedRowSchema = NestedTable.__pydantic_core_schema__[\"schema\"][\"fields\"][\"table\"][\n", + " \"schema\"\n", + "][\"items_schema\"][\"cls\"]\n", + "print(NestedRowSchema)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3bdcb520-47fe-417c-b762-0efbbf6013c5", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/pixi.lock b/pixi.lock index 211e7c0c..03870490 100644 --- a/pixi.lock +++ b/pixi.lock @@ -9,81 +9,132 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.8.3-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1423503_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1aa0949_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.0-hee844dc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-h4852527_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.2-h26f9b46_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.5-hec9711d_102_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-hc97d973_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/f5/9373290775639cb67a2fce7f629a1c240dce9f12fe927bc32b2736e16dfc/argcomplete-3.6.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/fe/49b0768f8c9ae57eb74cc10a1f87b4c70453551d8ad498959721cc345cb7/black-25.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/73/03/6b5370fc626e6f480c4a0b4cb25b3459d390745010618b21b4b573423a53/bqplot-0.12.45-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f1/6a/1766f8c163951a3c9aeb30a4e6f5de9b2eed8389e3906c4cf30fcb475be6/casefy-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/95/ef/0ed17459fe6076219fcd45f69a0bb4bd1cb041b39095ca2946808a9b5f04/datamodel_code_generator-0.35.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/e6/efe534ef0952b531b630780e19cabd416e2032697019d5295defc6ef9bd9/deepdiff-8.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/87/0fc6e51f9db3a3b3de88fb0c9cf6414d4572d565f4ba4d166023cbd4354d/dirty_equals-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a9/7a/dac76d31584bb4f874ae860490c9465f5b59bd8c110f68fbbb07aba48845/frictionless-5.18.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b6/48/583c032b79ae5b3daa02225a675aeb673e58d2cb698e78510feceb11958c/gast-0.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f8/5c/e226de133afd8bb267ec27eead9ae3d784b95b39a287ed404caab39a5f50/genson-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c3/5b/9512c5fb6c8218332b530f13500c6ff5f3ce3342f35e0dd7be9ac3856fd3/humanize-4.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/a5/5fda0ee4a261a85124011ac0750fec678f00e1b2d4a5502b149a3b4d86d9/immutables-0.21-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8a/eb/427ed2b20a38a4ee29f24dbe4ae2dafab198674fe9a85e3d6adf9e5f5f41/inflect-7.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/40/36/de3566f8a2140d403e66cd2d96dbbd6b425157473166a7ab295a0d217764/ipydatagrid-1.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/60/249e3444fcd9c833704741769981cd02fe2c7ce94126b1394e7a3b26e543/ipyfilechooser-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/63/f8/0031ee2b906a15a33d6bfc12dd09c3dfa966b3cb5b284ecfb7549e6ac3c4/ipython-9.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/05/aa/62893d6a591d337aa59dcc4c6f6c842f1fe20cd72c8c5c1f980255243252/ipython-9.7.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0a/c5/226ff8aaf6248edf16246498d7885805e2c8b122631ac133130b0612b1ad/ipyvue-1.11.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/48/f4/93c187f69bbd58669d315f5463124ef62484a24335bc6702d19c83d1311e/ipyvue-1.11.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/47/4d/fd1a6a888f8abb6b8dc316cc78b5153e75eff7ae66a94cf30b144fadd09d/ipyvuetify-1.11.3-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/6a/9166369a2f092bd286d24e6307de555d63616e8ddb373ebad2b5635ca4cd/ipywidgets-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/cc/9b681a170efab4868a032631dea1e8446d8ec718a7f657b94d49d1a12643/isort-6.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/6a/ca128561b22b60bd5a0c4ea26649e68c8556b82bc70a0c396eebc977fe86/jupyterlab_widgets-3.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/96/2b/34cc11786bc00d0f04d0f5fdc3a2b1ae0b6239eef72d3d345805f9ad92a1/markdown-3.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1d/0f/571b2c7a3833ae419fe69ff7b479a78d313581785203cc70a8db90121b9a/numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/73/de/65dfc670e50c9db92b750db1d7c87292b8f3ba9be2c1154594d1a7d1afb4/marko-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/7e/7d306ff7cb143e6d975cfa7eb98a93e73495c4deabb7d1b5ecf09ea0fd69/numpy-2.3.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8f/52/0634adaace9be2d8cac9ef78f05c47f3a675882e068438b9d7ec7ef0c13f/pandas-2.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/12/27/fb8d7338b4d551900fa3e580acbe7a0cf655d940e164cb5c00ec31961094/orderly_set-5.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/f7/3367feadd4ab56783b0971c9b7edfbdd68e0c70ce877949a5dd2117ed4a0/palettable-3.3.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9f/5c/ea831abc18dd3268046d7d9a0119f1f8ddc69642e0a5245f839602b8114d/petl-1.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/73/cb/ac7874b3e5d58441674fb70742e6c374b28b0c7cb988d37d991cde47166c/platformdirs-4.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/87/9e/bb60e40f1414884cf0408c975f75cf81935c00f52f0156e039ccd4b69ee3/py2vega-0.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/70/1a/5f4fd9e7285f10c44095a4f9fe17d0f358d1702a7c74a9278c794e8a7537/pydantic_extra_types-2.10.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1b/8b/5362443737a5307a7b67c1017c42cd104213189b4970bf607e05faf9c525/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/93/04/5c918669096da8d1c9ec7bb716bd72e755526103a61bc5e76a3e4fb23b53/pydantic_extra_types-2.10.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/4f/a5f167a95ef57c3e37fe8ae0a41745061442f44e4c0c4395d70c8740e453/python_calamine-0.5.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/25/d9db8be44e205a124f6c98bc0324b2bb149b7431c53877fc6d1038dddaf5/pytokens-0.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/ee/a324d3198da151820a326c1f988caaa4f37fc27955148a76fff7a2d787a9/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/e9/e58082fbb8cecbb6fb4133033c40cc50c248b1a331582be3a0f39138d65b/simpleeval-1.0.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9c/d1/8d5bd662703cc1764d986f6908a608777305946fa634d34c470cd4a1e729/traittypes-0.2.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/6e/3e955517e22cbdd565f2f8b2e73d52528b14b8bcfdb04f62466b071de847/validators-0.35.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/d8/0d1d2e9d3fabcf5d6840362adcf05f8cf3cd06a73358140c3a97189238ae/wcmatch-10.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ca/51/5447876806d1088a0f8f71e16542bf350918128d0a69437df26047c8e46f/widgetsnbextension-4.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/23/66/d0ce2f2e05a04c1d020f7cad5c7d211810a904772ca2178488d47c7ef3e4/xlsxdatagrid-0.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/0c/3662f4a66880196a590b202f0db82d919dd2f89e99a27fadef91c4a33d41/xlsxwriter-3.2.9-py3-none-any.whl - pypi: ./ dev: channels: @@ -96,71 +147,74 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.12.15-py312h8a5da7c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.13.2-py312h27b7581_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.10.0-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.11.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.0.5-pyh29332c3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-25.3.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/authlib-1.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-25.4.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/authlib-1.6.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/backports-1.0-pyhd8ed1ab_5.conda - conda: https://conda.anaconda.org/conda-forge/noarch/backports.tarfile-1.2.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.13.5-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.2-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.2.0-pyh29332c3_4.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.2.0-h82add2a_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py312h2ec8cdc_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.8.3-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312h67db365_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.8.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.1-py312h06ac9bb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.2.1-pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.11.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h460c074_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.0-pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.11-py312hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.12-py312hd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-43.0.3-py312hda17c39_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cyclopts-3.23.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.1-h2ff5cdb_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cyclopts-4.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/dart-sass-1.59.1-ha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-h3c4dab8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.16-py312h8285ef7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.17-py312h8285ef7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/deno-1.46.3-hcab8b69_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/deno-2.3.1-hbf66b88_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/deno-dom-0.1.41-h4768de7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/docstring_parser-0.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.22-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/esbuild-0.25.9-hfc2019e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.22.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/esbuild-0.27.0-hfc2019e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fastmcp-2.10.6-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.19.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fastmcp-2.12.5-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.7.0-py312h447239a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2025.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2025.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fuzy-jon-0.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/hf-xet-1.1.8-py39h598437d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/hf-xet-1.2.0-py310hb823017_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-sse-0.4.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/huggingface_hub-0.34.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-sse-0.4.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/huggingface_hub-1.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.10-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-6.30.1-pyh82676e8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.4.0-pyhfa0c392_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.1.0-pyha191276_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.7.0-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isodate-0.7.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.classes-3.4.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.context-6.0.1-pyhd8ed1ab_0.conda @@ -168,141 +222,149 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jeepney-0.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/jiter-0.10.0-py312h12e396e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/jiter-0.12.0-py312h0ccc70a_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/jsonpointer-3.0.0-py312h7900ff3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/jsonpointer-3.0.0-py312h7900ff3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.25.1-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.4.1-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-path-0.3.4-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.25.1-he01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.2.6-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.6.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.8.1-pyh31011fe_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.0-pyh29332c3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.4.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.4.10-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.27.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupytext-1.17.2-pyh80e38bb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupytext-1.18.1-pyh80e38bb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/keyring-25.6.0-pyha804496_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.2.2-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1423503_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lazy-object-proxy-1.12.0-py312h4c3975b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1aa0949_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.84.3-hf39c6af_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.1-h32235b2_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.0-hee844dc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-h4852527_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/litellm-1.73.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.2-py312h178313f_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.1.7-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mcp-1.12.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mdit-py-plugins-0.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.1.3-pyh29332c3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.1.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.8.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.6.3-py312h178313f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.6-hb482800_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyh29332c3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.6-hed9df3c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.6-hc388f54_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.6-h7d6f222_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-22.19.0-heeeca48_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/notebook_intelligence-2.3.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ollama-0.11.7-cpu_hba3e463_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ollama-python-0.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook_intelligence-2.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ollama-0.12.10-cuda_130h9684303_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ollama-python-0.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/openai-1.99.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/openapi-core-0.19.5-pyh29332c3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/openapi-pydantic-0.5.1-pyh3cfb1c2_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.2-h26f9b46_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/openapi-schema-validator-0.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/openapi-spec-validator-0.7.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pandoc-3.6.3-ha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parse-1.20.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.45-hc749103_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathable-0.4.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.46-h1321c63_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pickleshare-0.7.5-pyhd8ed1ab_1004.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.4.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.22.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.23.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/propcache-0.3.1-py312h178313f_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.0.0-py312h4c3975b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.1.3-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.11.7-pyh3cfb1c2_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.33.2-py312h680f630_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-settings-2.10.1-pyh3cfb1c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.4-pyh3cfb1c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py312h868fb18_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-settings-2.12.0-pyh3cfb1c2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pyperclip-1.9.0-pyha804496_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyperclip-1.11.0-pyha804496_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.11-h9e4cc4f_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.12-hd63d673_1_cpython.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.1.1-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.11-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.12-hd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-multipart-0.0.18-pyhff2d567_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pywin32-on-windows-0.1.0-pyh1179c8e_3.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.2-py312h178313f_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.0.2-py312hfb55c3c_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/quarto-1.7.33-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hfb55c3c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/quarto-1.8.25-hbf95b10_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.36.2-pyh29332c3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2025.7.34-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2025.11.3-py312h4c3975b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.1.0-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-rst-1.3.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.27.1-py312h868fb18_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/secretstorage-3.3.3-py312h7900ff3_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-rst-1.3.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.28.0-py312h868fb18_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/secretstorage-3.4.0-py312h7900ff3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-1.8.3-pyh0d859eb_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sse-starlette-3.0.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sse-starlette-3.0.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sseclient-py-1.8.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-0.47.3-pyhfdc7a7d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/starlette-0.50.0-pyhfdc7a7d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh0d859eb_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.9.0-py312h14ff09d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py312hd04cf1f_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tokenizers-0.21.4-py312h6be956c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhe01879c_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.2-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tokenizers-0.22.1-py312h6be956c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.2-py312h4c3975b_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typer-0.16.1-pyhc167863_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-0.16.1-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-standard-0.16.1-h810d63d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/types-python-dateutil-2.9.0.20250822-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typer-0.20.0-pyhefaf540_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-0.20.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-standard-0.20.0-h4daf872_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/typst-0.13.0-h53e704d_0.conda @@ -311,49 +373,80 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/uvicorn-0.29.0-py312h7900ff3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/voila-0.5.11-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.13-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-24.11.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.14-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.8.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-15.0.1-py312h66e93f0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-15.0.1-py312h5253ce2_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xclip-0.13-hb9d3cd8_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.12-h4f16b4b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb9d3cd8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.6-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxmu-1.2.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xsel-1.2.1-hb9d3cd8_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.20.1-py312h178313f_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h3b0a872_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.22.0-py312h8a5da7c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h387f397_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py312h4c3975b_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py312h5253ce2_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda + - pypi: https://files.pythonhosted.org/packages/74/f5/9373290775639cb67a2fce7f629a1c240dce9f12fe927bc32b2736e16dfc/argcomplete-3.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/b5/2bfc18330eddbcfb5aab8d2d720663cd410f51b2ed01375f5be3751595b0/black-25.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/73/03/6b5370fc626e6f480c4a0b4cb25b3459d390745010618b21b4b573423a53/bqplot-0.12.45-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/6a/1766f8c163951a3c9aeb30a4e6f5de9b2eed8389e3906c4cf30fcb475be6/casefy-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/95/ef/0ed17459fe6076219fcd45f69a0bb4bd1cb041b39095ca2946808a9b5f04/datamodel_code_generator-0.35.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/e6/efe534ef0952b531b630780e19cabd416e2032697019d5295defc6ef9bd9/deepdiff-8.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/87/0fc6e51f9db3a3b3de88fb0c9cf6414d4572d565f4ba4d166023cbd4354d/dirty_equals-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a9/7a/dac76d31584bb4f874ae860490c9465f5b59bd8c110f68fbbb07aba48845/frictionless-5.18.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b6/48/583c032b79ae5b3daa02225a675aeb673e58d2cb698e78510feceb11958c/gast-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f8/5c/e226de133afd8bb267ec27eead9ae3d784b95b39a287ed404caab39a5f50/genson-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c3/5b/9512c5fb6c8218332b530f13500c6ff5f3ce3342f35e0dd7be9ac3856fd3/humanize-4.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/a4/25df835a9b9b372a4a869a8a1ac30a32199f2b3f581ad0e249f7e3d19eed/immutables-0.21-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8a/eb/427ed2b20a38a4ee29f24dbe4ae2dafab198674fe9a85e3d6adf9e5f5f41/inflect-7.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/40/36/de3566f8a2140d403e66cd2d96dbbd6b425157473166a7ab295a0d217764/ipydatagrid-1.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/60/249e3444fcd9c833704741769981cd02fe2c7ce94126b1394e7a3b26e543/ipyfilechooser-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0a/c5/226ff8aaf6248edf16246498d7885805e2c8b122631ac133130b0612b1ad/ipyvue-1.11.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/48/f4/93c187f69bbd58669d315f5463124ef62484a24335bc6702d19c83d1311e/ipyvue-1.11.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/47/4d/fd1a6a888f8abb6b8dc316cc78b5153e75eff7ae66a94cf30b144fadd09d/ipyvuetify-1.11.3-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/6a/9166369a2f092bd286d24e6307de555d63616e8ddb373ebad2b5635ca4cd/ipywidgets-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/cc/9b681a170efab4868a032631dea1e8446d8ec718a7f657b94d49d1a12643/isort-6.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7e/6b/a3c4d85f8f609c78336e76b78733d5cdd0871b79fcce1fa66533849aab0c/jupyterlab_quarto-0.3.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/6a/ca128561b22b60bd5a0c4ea26649e68c8556b82bc70a0c396eebc977fe86/jupyterlab_widgets-3.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/96/2b/34cc11786bc00d0f04d0f5fdc3a2b1ae0b6239eef72d3d345805f9ad92a1/markdown-3.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/59/ef/f96536f1df42c668cbacb727a8c6da7afc9c05ece6d558927fb1722693e1/numpy-2.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/73/de/65dfc670e50c9db92b750db1d7c87292b8f3ba9be2c1154594d1a7d1afb4/marko-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f9/58/30a85127bfee6f108282107caf8e06a1f0cc997cb6b52cdee699276fcce4/numpy-2.3.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d3/a4/f7edcfa47e0a88cda0be8b068a5bae710bf264f867edfdf7b71584ace362/pandas-2.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/12/27/fb8d7338b4d551900fa3e580acbe7a0cf655d940e164cb5c00ec31961094/orderly_set-5.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/f7/3367feadd4ab56783b0971c9b7edfbdd68e0c70ce877949a5dd2117ed4a0/palettable-3.3.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/63/cd7d615331b328e287d8233ba9fdf191a9c2d11b6af0c7a59cfcec23de68/pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9f/5c/ea831abc18dd3268046d7d9a0119f1f8ddc69642e0a5245f839602b8114d/petl-1.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/87/9e/bb60e40f1414884cf0408c975f75cf81935c00f52f0156e039ccd4b69ee3/py2vega-0.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/70/1a/5f4fd9e7285f10c44095a4f9fe17d0f358d1702a7c74a9278c794e8a7537/pydantic_extra_types-2.10.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9c/d1/8d5bd662703cc1764d986f6908a608777305946fa634d34c470cd4a1e729/traittypes-0.2.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/aec81f781c75cd10554dc17a25849c720d54feafb6f7847690478dcf5ef8/pyarrow-22.0.0-cp312-cp312-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/93/04/5c918669096da8d1c9ec7bb716bd72e755526103a61bc5e76a3e4fb23b53/pydantic_extra_types-2.10.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/f5/aec030f567ee14c60b6fc9028a78767687f484071cb080f7cfa328d6496e/python_calamine-0.5.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/25/d9db8be44e205a124f6c98bc0324b2bb149b7431c53877fc6d1038dddaf5/pytokens-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/e9/e58082fbb8cecbb6fb4133033c40cc50c248b1a331582be3a0f39138d65b/simpleeval-1.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/6e/3e955517e22cbdd565f2f8b2e73d52528b14b8bcfdb04f62466b071de847/validators-0.35.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/d8/0d1d2e9d3fabcf5d6840362adcf05f8cf3cd06a73358140c3a97189238ae/wcmatch-10.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ca/51/5447876806d1088a0f8f71e16542bf350918128d0a69437df26047c8e46f/widgetsnbextension-4.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/23/66/d0ce2f2e05a04c1d020f7cad5c7d211810a904772ca2178488d47c7ef3e4/xlsxdatagrid-0.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/0c/3662f4a66880196a590b202f0db82d919dd2f89e99a27fadef91c4a33d41/xlsxwriter-3.2.9-py3-none-any.whl - pypi: ./ docs: channels: @@ -365,36 +458,36 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.10.0-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.11.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py313h07c4f96_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py313h07c4f96_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.0.5-pyh29332c3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-25.3.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-25.4.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.13.5-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.2-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.2.0-pyh29332c3_4.conda - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.2.0-h82add2a_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py313h46c70d0_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.8.3-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py313h09d1b84_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.8.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.1-py313hfab6e84_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.11.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.13.5-py313hd8ed1ab_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.13.9-py313hd8ed1ab_101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/dart-sass-1.59.1-ha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.16-py313h5d5ffb9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.17-py313h5d5ffb9_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/deno-1.46.3-hcab8b69_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/deno-2.3.1-hbf66b88_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/deno-dom-0.1.41-h4768de7_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/esbuild-0.25.9-hfc2019e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/esbuild-0.27.0-hfc2019e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda @@ -402,102 +495,104 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.10-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-6.30.1-pyh82676e8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.4.0-pyhfa0c392_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.1.0-pyha191276_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.7.0-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/jsonpointer-3.0.0-py313h78bf25f_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/jsonpointer-3.0.0-py313h78bf25f_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.25.1-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.4.1-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.25.1-he01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.2.6-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.6.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.8.1-pyh31011fe_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.0-pyh29332c3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.4.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.4.10-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.27.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.2.2-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1423503_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1aa0949_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.0-hee844dc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-h4852527_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.2-py313h8060acc_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.1.7-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.1.3-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py313h3dea7bd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.1.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-22.19.0-heeeca48_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.2-h26f9b46_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pandoc-3.6.3-ha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pickleshare-0.7.5-pyhd8ed1ab_1004.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.4.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.22.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.23.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.0.0-py313h07c4f96_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.1.3-py313h54dd161_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.5-hec9711d_102_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-hc97d973_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.13.5-h4df99d1_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.13.9-h4df99d1_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.2-py313h8060acc_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.0.2-py312hfb55c3c_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/quarto-1.7.33-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py313h3dea7bd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hfb55c3c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/quarto-1.8.25-hbf95b10_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.36.2-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.27.1-py313h843e2db_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.28.0-py313h843e2db_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-1.8.3-pyh0d859eb_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh0d859eb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhe01879c_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.2-py313h07c4f96_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.2-py313h07c4f96_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/types-python-dateutil-2.9.0.20250822-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda @@ -505,42 +600,80 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.13-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-24.11.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.14-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.8.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h3b0a872_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h387f397_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py313h07c4f96_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py313h54dd161_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/f5/9373290775639cb67a2fce7f629a1c240dce9f12fe927bc32b2736e16dfc/argcomplete-3.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/fe/49b0768f8c9ae57eb74cc10a1f87b4c70453551d8ad498959721cc345cb7/black-25.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/73/03/6b5370fc626e6f480c4a0b4cb25b3459d390745010618b21b4b573423a53/bqplot-0.12.45-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/6a/1766f8c163951a3c9aeb30a4e6f5de9b2eed8389e3906c4cf30fcb475be6/casefy-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/95/ef/0ed17459fe6076219fcd45f69a0bb4bd1cb041b39095ca2946808a9b5f04/datamodel_code_generator-0.35.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/e6/efe534ef0952b531b630780e19cabd416e2032697019d5295defc6ef9bd9/deepdiff-8.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/87/0fc6e51f9db3a3b3de88fb0c9cf6414d4572d565f4ba4d166023cbd4354d/dirty_equals-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a9/7a/dac76d31584bb4f874ae860490c9465f5b59bd8c110f68fbbb07aba48845/frictionless-5.18.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b6/48/583c032b79ae5b3daa02225a675aeb673e58d2cb698e78510feceb11958c/gast-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f8/5c/e226de133afd8bb267ec27eead9ae3d784b95b39a287ed404caab39a5f50/genson-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c3/5b/9512c5fb6c8218332b530f13500c6ff5f3ce3342f35e0dd7be9ac3856fd3/humanize-4.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/a5/5fda0ee4a261a85124011ac0750fec678f00e1b2d4a5502b149a3b4d86d9/immutables-0.21-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8a/eb/427ed2b20a38a4ee29f24dbe4ae2dafab198674fe9a85e3d6adf9e5f5f41/inflect-7.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/40/36/de3566f8a2140d403e66cd2d96dbbd6b425157473166a7ab295a0d217764/ipydatagrid-1.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/60/249e3444fcd9c833704741769981cd02fe2c7ce94126b1394e7a3b26e543/ipyfilechooser-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0a/c5/226ff8aaf6248edf16246498d7885805e2c8b122631ac133130b0612b1ad/ipyvue-1.11.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/48/f4/93c187f69bbd58669d315f5463124ef62484a24335bc6702d19c83d1311e/ipyvue-1.11.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/47/4d/fd1a6a888f8abb6b8dc316cc78b5153e75eff7ae66a94cf30b144fadd09d/ipyvuetify-1.11.3-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/6a/9166369a2f092bd286d24e6307de555d63616e8ddb373ebad2b5635ca4cd/ipywidgets-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/cc/9b681a170efab4868a032631dea1e8446d8ec718a7f657b94d49d1a12643/isort-6.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/6a/ca128561b22b60bd5a0c4ea26649e68c8556b82bc70a0c396eebc977fe86/jupyterlab_widgets-3.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/96/2b/34cc11786bc00d0f04d0f5fdc3a2b1ae0b6239eef72d3d345805f9ad92a1/markdown-3.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1d/0f/571b2c7a3833ae419fe69ff7b479a78d313581785203cc70a8db90121b9a/numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/73/de/65dfc670e50c9db92b750db1d7c87292b8f3ba9be2c1154594d1a7d1afb4/marko-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/7e/7d306ff7cb143e6d975cfa7eb98a93e73495c4deabb7d1b5ecf09ea0fd69/numpy-2.3.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8f/52/0634adaace9be2d8cac9ef78f05c47f3a675882e068438b9d7ec7ef0c13f/pandas-2.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/12/27/fb8d7338b4d551900fa3e580acbe7a0cf655d940e164cb5c00ec31961094/orderly_set-5.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/f7/3367feadd4ab56783b0971c9b7edfbdd68e0c70ce877949a5dd2117ed4a0/palettable-3.3.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9f/5c/ea831abc18dd3268046d7d9a0119f1f8ddc69642e0a5245f839602b8114d/petl-1.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/87/9e/bb60e40f1414884cf0408c975f75cf81935c00f52f0156e039ccd4b69ee3/py2vega-0.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/70/1a/5f4fd9e7285f10c44095a4f9fe17d0f358d1702a7c74a9278c794e8a7537/pydantic_extra_types-2.10.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9c/d1/8d5bd662703cc1764d986f6908a608777305946fa634d34c470cd4a1e729/traittypes-0.2.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1b/8b/5362443737a5307a7b67c1017c42cd104213189b4970bf607e05faf9c525/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/93/04/5c918669096da8d1c9ec7bb716bd72e755526103a61bc5e76a3e4fb23b53/pydantic_extra_types-2.10.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/4f/a5f167a95ef57c3e37fe8ae0a41745061442f44e4c0c4395d70c8740e453/python_calamine-0.5.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/25/d9db8be44e205a124f6c98bc0324b2bb149b7431c53877fc6d1038dddaf5/pytokens-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/e9/e58082fbb8cecbb6fb4133033c40cc50c248b1a331582be3a0f39138d65b/simpleeval-1.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/6e/3e955517e22cbdd565f2f8b2e73d52528b14b8bcfdb04f62466b071de847/validators-0.35.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/d8/0d1d2e9d3fabcf5d6840362adcf05f8cf3cd06a73358140c3a97189238ae/wcmatch-10.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ca/51/5447876806d1088a0f8f71e16542bf350918128d0a69437df26047c8e46f/widgetsnbextension-4.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/23/66/d0ce2f2e05a04c1d020f7cad5c7d211810a904772ca2178488d47c7ef3e4/xlsxdatagrid-0.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/0c/3662f4a66880196a590b202f0db82d919dd2f89e99a27fadef91c4a33d41/xlsxwriter-3.2.9-py3-none-any.whl - pypi: ./ tests: channels: @@ -551,22 +684,22 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.10.0-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.11.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/backports-1.0-pyhd8ed1ab_5.conda - conda: https://conda.anaconda.org/conda-forge/noarch/backports.tarfile-1.2.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.8.3-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/casefy-1.1.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.8.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.1-py313hfab6e84_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.2.1-pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.11.12-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.0-pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-45.0.6-py313hafb0bba_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-46.0.3-py313hafb0bba_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-h3c4dab8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/editables-0.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.19.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hatch-1.14.1-pyhd8ed1ab_0.conda @@ -576,116 +709,154 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperlink-21.0.0-pyh29332c3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.10-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.classes-3.4.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.context-6.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.functools-4.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jeepney-0.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/keyring-25.6.0-pyha804496_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1423503_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1aa0949_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.84.3-hf39c6af_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.1-h32235b2_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.0-hee844dc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-h4852527_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.8.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.2-h26f9b46_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.45-hc749103_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.46-h1321c63_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.5-hec9711d_102_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-hc97d973_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.1.0-pyhe01879c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/secretstorage-3.3.3-py313h78bf25f_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/secretstorage-3.4.0-py313h78bf25f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-w-1.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2025.8.26.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2025.9.11.17-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/userpath-1.9.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.8.13-heb9285d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.34.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.9.9-h76e24b7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.35.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py313h07c4f96_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py313h54dd161_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/f5/9373290775639cb67a2fce7f629a1c240dce9f12fe927bc32b2736e16dfc/argcomplete-3.6.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/fe/49b0768f8c9ae57eb74cc10a1f87b4c70453551d8ad498959721cc345cb7/black-25.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/73/03/6b5370fc626e6f480c4a0b4cb25b3459d390745010618b21b4b573423a53/bqplot-0.12.45-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/95/ef/0ed17459fe6076219fcd45f69a0bb4bd1cb041b39095ca2946808a9b5f04/datamodel_code_generator-0.35.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/e6/efe534ef0952b531b630780e19cabd416e2032697019d5295defc6ef9bd9/deepdiff-8.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/87/0fc6e51f9db3a3b3de88fb0c9cf6414d4572d565f4ba4d166023cbd4354d/dirty_equals-0.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a9/7a/dac76d31584bb4f874ae860490c9465f5b59bd8c110f68fbbb07aba48845/frictionless-5.18.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b6/48/583c032b79ae5b3daa02225a675aeb673e58d2cb698e78510feceb11958c/gast-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f8/5c/e226de133afd8bb267ec27eead9ae3d784b95b39a287ed404caab39a5f50/genson-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c3/5b/9512c5fb6c8218332b530f13500c6ff5f3ce3342f35e0dd7be9ac3856fd3/humanize-4.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/a5/5fda0ee4a261a85124011ac0750fec678f00e1b2d4a5502b149a3b4d86d9/immutables-0.21-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8a/eb/427ed2b20a38a4ee29f24dbe4ae2dafab198674fe9a85e3d6adf9e5f5f41/inflect-7.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/40/36/de3566f8a2140d403e66cd2d96dbbd6b425157473166a7ab295a0d217764/ipydatagrid-1.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/60/249e3444fcd9c833704741769981cd02fe2c7ce94126b1394e7a3b26e543/ipyfilechooser-0.6.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/63/f8/0031ee2b906a15a33d6bfc12dd09c3dfa966b3cb5b284ecfb7549e6ac3c4/ipython-9.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/05/aa/62893d6a591d337aa59dcc4c6f6c842f1fe20cd72c8c5c1f980255243252/ipython-9.7.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0a/c5/226ff8aaf6248edf16246498d7885805e2c8b122631ac133130b0612b1ad/ipyvue-1.11.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/48/f4/93c187f69bbd58669d315f5463124ef62484a24335bc6702d19c83d1311e/ipyvue-1.11.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/47/4d/fd1a6a888f8abb6b8dc316cc78b5153e75eff7ae66a94cf30b144fadd09d/ipyvuetify-1.11.3-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/6a/9166369a2f092bd286d24e6307de555d63616e8ddb373ebad2b5635ca4cd/ipywidgets-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/cc/9b681a170efab4868a032631dea1e8446d8ec718a7f657b94d49d1a12643/isort-6.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/6a/ca128561b22b60bd5a0c4ea26649e68c8556b82bc70a0c396eebc977fe86/jupyterlab_widgets-3.0.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/96/2b/34cc11786bc00d0f04d0f5fdc3a2b1ae0b6239eef72d3d345805f9ad92a1/markdown-3.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/73/de/65dfc670e50c9db92b750db1d7c87292b8f3ba9be2c1154594d1a7d1afb4/marko-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1d/0f/571b2c7a3833ae419fe69ff7b479a78d313581785203cc70a8db90121b9a/numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/9e/7e/7d306ff7cb143e6d975cfa7eb98a93e73495c4deabb7d1b5ecf09ea0fd69/numpy-2.3.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8f/52/0634adaace9be2d8cac9ef78f05c47f3a675882e068438b9d7ec7ef0c13f/pandas-2.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/12/27/fb8d7338b4d551900fa3e580acbe7a0cf655d940e164cb5c00ec31961094/orderly_set-5.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/f7/3367feadd4ab56783b0971c9b7edfbdd68e0c70ce877949a5dd2117ed4a0/palettable-3.3.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9f/5c/ea831abc18dd3268046d7d9a0119f1f8ddc69642e0a5245f839602b8114d/petl-1.7.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/87/9e/bb60e40f1414884cf0408c975f75cf81935c00f52f0156e039ccd4b69ee3/py2vega-0.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/70/1a/5f4fd9e7285f10c44095a4f9fe17d0f358d1702a7c74a9278c794e8a7537/pydantic_extra_types-2.10.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1b/8b/5362443737a5307a7b67c1017c42cd104213189b4970bf607e05faf9c525/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/93/04/5c918669096da8d1c9ec7bb716bd72e755526103a61bc5e76a3e4fb23b53/pydantic_extra_types-2.10.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/09/52/7bbfb6e987d9a8a945f22941a8da63e3529465f1b106ef0e26f5df7c780d/pytest_examples-0.0.18-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/4f/a5f167a95ef57c3e37fe8ae0a41745061442f44e4c0c4395d70c8740e453/python_calamine-0.5.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/25/d9db8be44e205a124f6c98bc0324b2bb149b7431c53877fc6d1038dddaf5/pytokens-0.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c0/1d/b4207ec35e7babaee62c462769e77457e26eb853fbdc877af29417033333/ruff-0.12.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/ee/a324d3198da151820a326c1f988caaa4f37fc27955148a76fff7a2d787a9/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ee/79/6ad4dda2cfd55e41ac9ed6d73ef9ab9475b1eef69f3a85957210c74ba12c/ruff-0.14.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a0/e9/e58082fbb8cecbb6fb4133033c40cc50c248b1a331582be3a0f39138d65b/simpleeval-1.0.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9c/d1/8d5bd662703cc1764d986f6908a608777305946fa634d34c470cd4a1e729/traittypes-0.2.1-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/6e/3e955517e22cbdd565f2f8b2e73d52528b14b8bcfdb04f62466b071de847/validators-0.35.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/eb/d8/0d1d2e9d3fabcf5d6840362adcf05f8cf3cd06a73358140c3a97189238ae/wcmatch-10.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ca/51/5447876806d1088a0f8f71e16542bf350918128d0a69437df26047c8e46f/widgetsnbextension-4.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/23/66/d0ce2f2e05a04c1d020f7cad5c7d211810a904772ca2178488d47c7ef3e4/xlsxdatagrid-0.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/0c/3662f4a66880196a590b202f0db82d919dd2f89e99a27fadef91c4a33d41/xlsxwriter-3.2.9-py3-none-any.whl - pypi: ./ packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 @@ -731,9 +902,9 @@ packages: - pkg:pypi/aiohappyeyeballs?source=hash-mapping size: 19750 timestamp: 1741775303303 -- conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.12.15-py312h8a5da7c_0.conda - sha256: 524f7e7bcf2f68ec69fc4e097373b2affee48419b1568b9b7c60c09fca260caf - md5: 26123b7166da2af08afb6172b5a4806c +- conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.13.2-py312h27b7581_0.conda + sha256: baf2bbf52aeecdbfe6e03a373b2664169cbdc37a92a2ac68bc7ef45353f65d61 + md5: ad84ca57d502eead2df0233090261dfb depends: - __glibc >=2.17,<3.0.a0 - aiohappyeyeballs >=2.5.0 @@ -750,8 +921,8 @@ packages: license_family: Apache purls: - pkg:pypi/aiohttp?source=hash-mapping - size: 1007572 - timestamp: 1753805448349 + size: 1014925 + timestamp: 1761727721839 - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.4.0-pyhd8ed1ab_0.conda sha256: 8dc149a6828d19bf104ea96382a9d04dae185d4a03cc6beb1bc7b84c428e3ca2 md5: 421a865222cd0c9d83ff08bc78bf3a61 @@ -784,25 +955,36 @@ packages: - pkg:pypi/annotated-types?source=hash-mapping size: 18074 timestamp: 1733247158254 -- conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.10.0-pyhe01879c_0.conda - sha256: d1b50686672ebe7041e44811eda563e45b94a8354db67eca659040392ac74d63 - md5: cc2613bfa71dec0eb2113ee21ac9ccbf +- conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.11.0-pyhcf101f3_0.conda + sha256: 7378b5b9d81662d73a906fabfc2fb81daddffe8dc0680ed9cda7a9562af894b0 + md5: 814472b61da9792fae28156cb9ee54f5 depends: - exceptiongroup >=1.0.2 - idna >=2.8 - - python >=3.9 + - python >=3.10 - sniffio >=1.1 - typing_extensions >=4.5 - python constrains: - - trio >=0.26.1 + - trio >=0.31.0 - uvloop >=0.21 license: MIT license_family: MIT purls: - - pkg:pypi/anyio?source=compressed-mapping - size: 134857 - timestamp: 1754315087747 + - pkg:pypi/anyio?source=hash-mapping + size: 138159 + timestamp: 1758634638734 +- pypi: https://files.pythonhosted.org/packages/74/f5/9373290775639cb67a2fce7f629a1c240dce9f12fe927bc32b2736e16dfc/argcomplete-3.6.3-py3-none-any.whl + name: argcomplete + version: 3.6.3 + sha256: f5007b3a600ccac5d25bbce33089211dfd49eab4a7718da3f10e3082525a92ce + requires_dist: + - coverage ; extra == 'test' + - mypy ; extra == 'test' + - pexpect ; extra == 'test' + - ruff ; extra == 'test' + - wheel ; extra == 'test' + requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda sha256: bea62005badcb98b1ae1796ec5d70ea0fc9539e7d59708ac4e7d41e2f4bb0bad md5: 8ac12aff0860280ee0cff7fa2cf63f3b @@ -818,9 +1000,9 @@ packages: - pkg:pypi/argon2-cffi?source=hash-mapping size: 18715 timestamp: 1749017288144 -- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_0.conda - sha256: d072b579af12d86e239487cea16ec860e2bc2f26edca9f9697a5b3a031735228 - md5: fdcda5c2e5c6970e9f629c37ec321037 +- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_2.conda + sha256: 7988c207b2b766dad5ebabf25a92b8d75cb8faed92f256fd7a4e0875c9ec6d58 + md5: 1567f06d717246abab170736af8bad1b depends: - __glibc >=2.17,<3.0.a0 - cffi >=1.0.1 @@ -831,11 +1013,11 @@ packages: license_family: MIT purls: - pkg:pypi/argon2-cffi-bindings?source=hash-mapping - size: 35575 - timestamp: 1753994865409 -- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py313h07c4f96_0.conda - sha256: 659d3876bd07ae8548b9be869708507bf56112ac300e43ca05860d5fbe73072e - md5: 99b4a1dea9e1d402c26dbbc0aef4f47c + size: 35646 + timestamp: 1762509443854 +- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py313h07c4f96_2.conda + sha256: ad188ccc06a06c633dc124b09e9e06fb9df4c32ffc38acc96ecc86e506062090 + md5: 27bbec9f2f3a15d32b60ec5734f5b41c depends: - __glibc >=2.17,<3.0.a0 - cffi >=1.0.1 @@ -846,21 +1028,22 @@ packages: license_family: MIT purls: - pkg:pypi/argon2-cffi-bindings?source=hash-mapping - size: 35811 - timestamp: 1753994992173 -- conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.3.0-pyhd8ed1ab_1.conda - sha256: c4b0bdb3d5dee50b60db92f99da3e4c524d5240aafc0a5fcc15e45ae2d1a3cd1 - md5: 46b53236fdd990271b03c3978d4218a9 + size: 35943 + timestamp: 1762509452935 +- conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + sha256: 792da8131b1b53ff667bd6fc617ea9087b570305ccb9913deb36b8e12b3b5141 + md5: 85c4f19f377424eafc4ed7911b291642 depends: - - python >=3.9 + - python >=3.10 - python-dateutil >=2.7.0 - - types-python-dateutil >=2.8.10 + - python-tzdata + - python license: Apache-2.0 - license_family: Apache + license_family: APACHE purls: - pkg:pypi/arrow?source=hash-mapping - size: 99951 - timestamp: 1733584345583 + size: 113854 + timestamp: 1760831179410 - pypi: https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl name: asttokens version: 3.0.0 @@ -898,20 +1081,25 @@ packages: - pkg:pypi/async-lru?source=hash-mapping size: 17335 timestamp: 1742153708859 -- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-25.3.0-pyh71513ae_0.conda - sha256: 99c53ffbcb5dc58084faf18587b215f9ac8ced36bbfb55fa807c00967e419019 - md5: a10d11958cadc13fdb43df75f8b1903f +- pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl + name: attrs + version: 25.4.0 + sha256: adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-25.4.0-pyh71513ae_0.conda + sha256: f6c3c19fa599a1a856a88db166c318b148cac3ee4851a9905ed8a04eeec79f45 + md5: c7944d55af26b6d2d7629e27e9a972c1 depends: - - python >=3.9 + - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/attrs?source=hash-mapping - size: 57181 - timestamp: 1741918625732 -- conda: https://conda.anaconda.org/conda-forge/noarch/authlib-1.6.3-pyhd8ed1ab_0.conda - sha256: 760a7d0f2a198c98f4a18825a77b8a8256ecfd69426cc54d1e8eb2b18affb920 - md5: d27a5ebc43eecbf7b2cc4981791bde9c + size: 60101 + timestamp: 1759762331492 +- conda: https://conda.anaconda.org/conda-forge/noarch/authlib-1.6.5-pyhd8ed1ab_0.conda + sha256: 8a42f951fe03f83c69c37820d8ee36323f1155f1f4241541ff6ec84bb377756c + md5: 0db7d91f2313bcf05506e7260d881514 depends: - cryptography - python >=3.10 @@ -920,8 +1108,8 @@ packages: license_family: BSD purls: - pkg:pypi/authlib?source=hash-mapping - size: 142921 - timestamp: 1756271202925 + size: 145831 + timestamp: 1759437390042 - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda sha256: 1c656a35800b7f57f7371605bc6507c8d3ad60fbaaec65876fce7f73df1fc8ac md5: 0a01c169f0ab0f91b26e77a3301fbfe4 @@ -956,9 +1144,9 @@ packages: - pkg:pypi/backports-tarfile?source=hash-mapping size: 32786 timestamp: 1733325872620 -- conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.13.5-pyha770c72_0.conda - sha256: d2124c0ea13527c7f54582269b3ae19541141a3740d6d779e7aa95aa82eaf561 - md5: de0fd9702fd4c1186e930b8c35af6b6b +- conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.2-pyha770c72_0.conda + sha256: b949bd0121bb1eabc282c4de0551cc162b621582ee12b415e6f8297398e3b3b4 + md5: 749ebebabc2cae99b2e5b3edd04c6ca2 depends: - python >=3.10 - soupsieve >=1.2 @@ -966,19 +1154,39 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/beautifulsoup4?source=compressed-mapping - size: 88278 - timestamp: 1756094375546 -- pypi: https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl + - pkg:pypi/beautifulsoup4?source=hash-mapping + size: 89146 + timestamp: 1759146127397 +- pypi: https://files.pythonhosted.org/packages/99/fe/49b0768f8c9ae57eb74cc10a1f87b4c70453551d8ad498959721cc345cb7/black-25.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl name: black - version: 25.1.0 - sha256: 030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171 + version: 25.11.0 + sha256: 936c4dd07669269f40b497440159a221ee435e3fddcf668e0c05244a9be71993 requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 - packaging>=22.0 - pathspec>=0.9.0 - platformdirs>=2 + - pytokens>=0.3.0 + - tomli>=1.1.0 ; python_full_version < '3.11' + - typing-extensions>=4.0.1 ; python_full_version < '3.11' + - colorama>=0.4.3 ; extra == 'colorama' + - aiohttp>=3.10 ; extra == 'd' + - ipython>=7.8.0 ; extra == 'jupyter' + - tokenize-rt>=3.2.0 ; extra == 'jupyter' + - uvloop>=0.15.2 ; extra == 'uvloop' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f3/b5/2bfc18330eddbcfb5aab8d2d720663cd410f51b2ed01375f5be3751595b0/black-25.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: black + version: 25.11.0 + sha256: 6cb2d54a39e0ef021d6c5eef442e10fd71fcb491be6413d083a320ee768329dd + requires_dist: + - click>=8.0.0 + - mypy-extensions>=0.4.3 + - packaging>=22.0 + - pathspec>=0.9.0 + - platformdirs>=2 + - pytokens>=0.3.0 - tomli>=1.1.0 ; python_full_version < '3.11' - typing-extensions>=4.0.1 ; python_full_version < '3.11' - colorama>=0.4.3 ; extra == 'colorama' @@ -1027,60 +1235,60 @@ packages: version: '2.6' sha256: 0b0049264e7340b3ec782b5cb99beb325f36c3782a32e36e876452fd49a09952 requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py312h2ec8cdc_3.conda - sha256: dc27c58dc717b456eee2d57d8bc71df3f562ee49368a2351103bc8f1b67da251 - md5: a32e0c069f6c3dcac635f7b0b0dac67e +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312h67db365_0.conda + sha256: 1acccd5464d81184ead80c017b4a7320c59c2774eb914f14d60ca8b4c55754e9 + md5: 7c9245551ebbe6b6068aeda04060afaa depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - - libstdcxx >=13 + - libgcc >=14 + - libstdcxx >=14 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 constrains: - - libbrotlicommon 1.1.0 hb9d3cd8_3 + - libbrotlicommon 1.2.0 h09219d5_0 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping - size: 351721 - timestamp: 1749230265727 -- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py313h46c70d0_3.conda - sha256: e510ad1db7ea882505712e815ff02514490560fd74b5ec3a45a6c7cf438f754d - md5: 2babfedd9588ad40c7113ddfe6a5ca82 + size: 367744 + timestamp: 1761592371750 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py313h09d1b84_0.conda + sha256: 93eeadb5ef4ae211edb01f4a4d837e4b5ceba8ddaefdd68a0c982503c8cc86d1 + md5: dfd94363b679c74937b3926731ee861a depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - - libstdcxx >=13 + - libgcc >=14 + - libstdcxx >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 constrains: - - libbrotlicommon 1.1.0 hb9d3cd8_3 + - libbrotlicommon 1.2.0 h09219d5_0 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping - size: 350295 - timestamp: 1749230225293 -- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda - sha256: 5ced96500d945fb286c9c838e54fa759aa04a7129c59800f0846b4335cee770d - md5: 62ee74e96c5ebb0af99386de58cf9553 + size: 367767 + timestamp: 1761592405814 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda + sha256: c30daba32ddebbb7ded490f0e371eae90f51e72db620554089103b4a6934b0d5 + md5: 51a19bba1b8ebfb60df25cde030b7ebc depends: - __glibc >=2.17,<3.0.a0 - - libgcc-ng >=12 + - libgcc >=14 license: bzip2-1.0.6 license_family: BSD purls: [] - size: 252783 - timestamp: 1720974456583 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.8.3-hbd8a1cb_0.conda - sha256: 837b795a2bb39b75694ba910c13c15fa4998d4bb2a622c214a6a5174b2ae53d1 - md5: 74784ee3d225fc3dca89edb635b4e5cc + size: 260341 + timestamp: 1757437258798 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda + sha256: b986ba796d42c9d3265602bc038f6f5264095702dd546c14bc684e60c385e773 + md5: f0991f0f84902f6b6009b4d2350a83aa depends: - __unix license: ISC purls: [] - size: 154402 - timestamp: 1754210968730 + size: 152432 + timestamp: 1762967197890 - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 noarch: python sha256: 561e6660f26c35d137ee150187d89767c988413c978e1b712d53f27ddf70ea17 @@ -1103,6 +1311,11 @@ packages: - pkg:pypi/cached-property?source=hash-mapping size: 11065 timestamp: 1615209567874 +- pypi: https://files.pythonhosted.org/packages/f1/6a/1766f8c163951a3c9aeb30a4e6f5de9b2eed8389e3906c4cf30fcb475be6/casefy-1.1.0-py3-none-any.whl + name: casefy + version: 1.1.0 + sha256: a3dfcb14d85902d90702db1e9835760237f6a73ec0ae3b7e991ad767513a3cbc + requires_python: '>=3.6' - conda: https://conda.anaconda.org/conda-forge/noarch/casefy-1.1.0-pyhd8ed1ab_0.conda sha256: 06560908eb00a11446980ad17ed469f505a031a1ffa793bf9c2a628f2634fcc9 md5: 32e3a03cc7f3e8761adf8e619118cfc3 @@ -1114,28 +1327,28 @@ packages: - pkg:pypi/casefy?source=hash-mapping size: 12036 timestamp: 1741451659659 -- pypi: https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl name: certifi - version: 2025.8.3 - sha256: f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5 + version: 2025.11.12 + sha256: 97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b requires_python: '>=3.7' -- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.8.3-pyhd8ed1ab_0.conda - sha256: a1ad5b0a2a242f439608f22a538d2175cac4444b7b3f4e2b8c090ac337aaea40 - md5: 11f59985f49df4620890f3e746ed7102 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.11.12-pyhd8ed1ab_0.conda + sha256: 083a2bdad892ccf02b352ecab38ee86c3e610ba9a4b11b073ea769d55a115d32 + md5: 96a02a5c1a65470a7e4eedb644c872fd depends: - - python >=3.9 + - python >=3.10 license: ISC purls: - pkg:pypi/certifi?source=compressed-mapping - size: 158692 - timestamp: 1754231530168 -- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.1-py312h06ac9bb_0.conda - sha256: cba6ea83c4b0b4f5b5dc59cb19830519b28f95d7ebef7c9c5cf1c14843621457 - md5: a861504bbea4161a9170b85d4d2be840 + size: 157131 + timestamp: 1762976260320 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h460c074_1.conda + sha256: 7dafe8173d5f94e46cf9cd597cc8ff476a8357fbbd4433a8b5697b2864845d9c + md5: 648ee28dcd4e07a1940a17da62eccd40 depends: - __glibc >=2.17,<3.0.a0 - - libffi >=3.4,<4.0a0 - - libgcc >=13 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 - pycparser - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 @@ -1143,52 +1356,64 @@ packages: license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping - size: 294403 - timestamp: 1725560714366 -- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.1-py313hfab6e84_0.conda - sha256: 73cd6199b143a8a6cbf733ce124ed57defc1b9a7eab9b10fd437448caf8eaa45 - md5: ce6386a5892ef686d6d680c345c40ad1 + size: 295716 + timestamp: 1761202958833 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py313hf46b229_1.conda + sha256: 2162a91819945c826c6ef5efe379e88b1df0fe9a387eeba23ddcf7ebeacd5bd6 + md5: d0616e7935acab407d1543b28c446f6f depends: - __glibc >=2.17,<3.0.a0 - - libffi >=3.4,<4.0a0 - - libgcc >=13 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 - pycparser - - python >=3.13.0rc1,<3.14.0a0 + - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - pkg:pypi/cffi?source=hash-mapping - size: 295514 - timestamp: 1725560706794 -- pypi: https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + size: 298357 + timestamp: 1761202966461 +- pypi: https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl + name: chardet + version: 5.2.0 + sha256: e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl name: charset-normalizer - version: 3.4.3 - sha256: 416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f + version: 3.4.4 + sha256: a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 requires_python: '>=3.7' -- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.3-pyhd8ed1ab_0.conda - sha256: 838d5a011f0e7422be6427becba3de743c78f3874ad2743c341accbba9bb2624 - md5: 7e7d5ef1b9ed630e4a1c358d6bc62284 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda + sha256: b32f8362e885f1b8417bac2b3da4db7323faa12d5db62b7fd6691c02d60d6f59 + md5: a22d1fd9bf98827e280a02875d9a007a depends: - - python >=3.9 + - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/charset-normalizer?source=hash-mapping - size: 51033 - timestamp: 1754767444665 -- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.2.1-pyh707e725_0.conda - sha256: 8aee789c82d8fdd997840c952a586db63c6890b00e88c4fb6e80a38edd5f51c0 - md5: 94b550b8d3a614dbd326af798c7dfb40 + size: 50965 + timestamp: 1760437331772 +- pypi: https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl + name: click + version: 8.3.0 + sha256: 9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc + requires_dist: + - colorama ; sys_platform == 'win32' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.0-pyh707e725_0.conda + sha256: c6567ebc27c4c071a353acaf93eb82bb6d9a6961e40692a359045a89a61d02c0 + md5: e76c4ba9e1837847679421b8d549b784 depends: - __unix - python >=3.10 license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/click?source=hash-mapping - size: 87749 - timestamp: 1747811451319 + - pkg:pypi/click?source=compressed-mapping + size: 91622 + timestamp: 1758270534287 - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 md5: 962b9857ee8e7018c22f2776ffa0b2d7 @@ -1216,31 +1441,31 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/comm?source=compressed-mapping + - pkg:pypi/comm?source=hash-mapping size: 14690 timestamp: 1753453984907 -- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.11-py312hd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.12-py312hd8ed1ab_1.conda noarch: generic - sha256: 7e7bc8e73a2f3736444a8564cbece7216464c00f0bc38e604b0c792ff60d621a - md5: e5279009e7a7f7edd3cd2880c502b3cc + sha256: b88c76a6d6b45378552ccfd9e88b2a073161fe83fd1294c8fa103ffd32f7934a + md5: 99d689ccc1a360639eec979fd7805be9 depends: - python >=3.12,<3.13.0a0 - python_abi * *_cp312 license: Python-2.0 purls: [] - size: 45852 - timestamp: 1749047748072 -- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.13.5-py313hd8ed1ab_102.conda + size: 45767 + timestamp: 1761175217281 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.13.9-py313hd8ed1ab_101.conda noarch: generic - sha256: 058c8156ff880b1180a36b94307baad91f9130d0e3019ad8c7ade035852016fb - md5: 0401f31e3c9e48cebf215472aa3e7104 + sha256: 31da683e8a15e2062adfb29c9fb23d4253550a0b3c9be1cd45530f88796b4644 + md5: 367133808e89325690562099851529c8 depends: - python >=3.13,<3.14.0a0 - python_abi * *_cp313 license: Python-2.0 purls: [] - size: 47560 - timestamp: 1750062514868 + size: 48397 + timestamp: 1761175097707 - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-43.0.3-py312hda17c39_0.conda sha256: ba9e5aced2e7dc0bbc48f60bf38f514839424a01975fb2aed30e9246c2f82c7c md5: 2abada8c216dd6e32514535a3fa245d4 @@ -1259,14 +1484,14 @@ packages: - pkg:pypi/cryptography?source=hash-mapping size: 1488388 timestamp: 1729286882127 -- conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-45.0.6-py313hafb0bba_0.conda - sha256: 51713a14ac32a7d9ac21ec1fb6e4522178387f63acb0d096bac0ff0f30e64ba4 - md5: 48c1b1c5e42c8df2e8fa0343b41fbb40 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-46.0.3-py313hafb0bba_0.conda + sha256: 975cea9e12c4afdb8e12373cab92569fe4062bb0b5b3c39ee7c077c9fdca4121 + md5: 524ddf173d159040f9a4e2de23e08085 depends: - __glibc >=2.17,<3.0.a0 - - cffi >=1.12 + - cffi >=1.14 - libgcc >=14 - - openssl >=3.5.2,<4.0a0 + - openssl >=3.5.4,<4.0a0 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 constrains: @@ -1275,25 +1500,36 @@ packages: license_family: BSD purls: - pkg:pypi/cryptography?source=hash-mapping - size: 1659554 - timestamp: 1754472862161 -- conda: https://conda.anaconda.org/conda-forge/noarch/cyclopts-3.23.0-pyhcf101f3_0.conda - sha256: f54ed7e6f0de7ad345bf7f8683d7209b1514ecf38e6b5597f81467db6abfddf5 - md5: 696790a6e79fae8990555c8d81597680 + size: 1718808 + timestamp: 1760605188769 +- conda: https://conda.anaconda.org/conda-forge/noarch/cuda-version-13.1-h2ff5cdb_3.conda + sha256: 176ac20fdb95611af8fb2bf0d3d16fee998019b1d0f12fc9ddd5fa0df4553992 + md5: d85448460c25ee43ff2f8346bb9ad52b + constrains: + - cudatoolkit 13.1|13.1.* + - __cuda >=13 + license: LicenseRef-NVIDIA-End-User-License-Agreement + purls: [] + size: 21511 + timestamp: 1757017115788 +- conda: https://conda.anaconda.org/conda-forge/noarch/cyclopts-4.2.1-pyhcf101f3_0.conda + sha256: cdb5ecdeff76b5bd5e6742a0f54b429e9b015b95db00134cdd83d91dfbe5a826 + md5: ec2c80f482f293e4c6f7402a43a8442d depends: - python >=3.10 - - typing_extensions >=4.8.0 - attrs >=23.1.0 - rich >=13.6.0 + - docstring_parser >=0.15,<4.0 - rich-rst >=1.3.1,<2.0.0 - - docstring_parser >=0.15 - - importlib-metadata >=4.4 + - typing_extensions >=4.8.0 + - tomli >=2.0.0 - python license: Apache-2.0 + license_family: APACHE purls: - pkg:pypi/cyclopts?source=hash-mapping - size: 80574 - timestamp: 1756238352596 + size: 148777 + timestamp: 1762014755586 - conda: https://conda.anaconda.org/conda-forge/linux-64/dart-sass-1.59.1-ha770c72_0.conda sha256: 5eae84d272c5706dd4a733a4a3912e6a1d9d02fcd53546b26c44d4f0f7f104bc md5: de2018928d25b2cf33d0634f908554ef @@ -1302,6 +1538,34 @@ packages: purls: [] size: 2970979 timestamp: 1747420497129 +- pypi: https://files.pythonhosted.org/packages/95/ef/0ed17459fe6076219fcd45f69a0bb4bd1cb041b39095ca2946808a9b5f04/datamodel_code_generator-0.35.0-py3-none-any.whl + name: datamodel-code-generator + version: 0.35.0 + sha256: c356d1e4a555f86667a4262db03d4598a30caeda8f51786555fd269c8abb806b + requires_dist: + - argcomplete>=2.10.1,<4 + - black>=19.10b0 + - genson>=1.2.1,<2 + - inflect>=4.1,<8 + - isort>=4.3.21,<7 + - jinja2>=2.10.1,<4 + - packaging + - pydantic>=1.5 + - pyyaml>=6.0.1 + - tomli>=2.2.1,<3 ; python_full_version < '3.12' + - graphql-core>=3.2.3 ; extra == 'all' + - httpx>=0.24.1 ; extra == 'all' + - openapi-spec-validator>=0.2.8,<0.7 ; extra == 'all' + - prance>=0.18.2 ; extra == 'all' + - pysnooper>=0.4.1,<2 ; extra == 'all' + - ruff>=0.9.10 ; extra == 'all' + - pysnooper>=0.4.1,<2 ; extra == 'debug' + - graphql-core>=3.2.3 ; extra == 'graphql' + - httpx>=0.24.1 ; extra == 'http' + - ruff>=0.9.10 ; extra == 'ruff' + - openapi-spec-validator>=0.2.8,<0.7 ; extra == 'validation' + - prance>=0.18.2 ; extra == 'validation' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-h3c4dab8_0.conda sha256: 3b988146a50e165f0fa4e839545c679af88e4782ec284cc7b6d07dd226d6a068 md5: 679616eb5ad4e521c83da4650860aba7 @@ -1318,37 +1582,37 @@ packages: purls: [] size: 437860 timestamp: 1747855126005 -- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.16-py312h8285ef7_0.conda - sha256: ad6193b4c2771a82a8df3408d9c6174016b487fd1f7501b1618fa034c5118534 - md5: 6205bf8723b4b79275dd52ef60cf6af1 +- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.17-py312h8285ef7_0.conda + sha256: c715221c434f7762dc2709239b32f61c0df5e3da94cc0d34f2d2be4acbb5099f + md5: 14938d17d7a91e2bf132330c7f2f61a2 depends: - python - - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - libstdcxx >=14 - libgcc >=14 + - __glibc >=2.17,<3.0.a0 - python_abi 3.12.* *_cp312 license: MIT license_family: MIT purls: - - pkg:pypi/debugpy?source=compressed-mapping - size: 2856116 - timestamp: 1754523420446 -- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.16-py313h5d5ffb9_0.conda - sha256: 26c56e7f93cde8be5b1b3ec3404f95d2874946f6fe0182f6720e5c3232e006ed - md5: c6286f4df7bec3d3712d617a358149b4 + - pkg:pypi/debugpy?source=hash-mapping + size: 2855535 + timestamp: 1758162043806 +- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.17-py313h5d5ffb9_0.conda + sha256: 4c12ca7541d488f64ee92d6368e9a0a418e919c0b8c51517ff329b4259b4aaf8 + md5: be318961d544421f4c8d8a91bff4f118 depends: - python - - __glibc >=2.17,<3.0.a0 + - libgcc >=14 - libstdcxx >=14 - libgcc >=14 + - __glibc >=2.17,<3.0.a0 - python_abi 3.13.* *_cp313 license: MIT license_family: MIT purls: - - pkg:pypi/debugpy?source=compressed-mapping - size: 2868365 - timestamp: 1754523414483 + - pkg:pypi/debugpy?source=hash-mapping + size: 2868018 + timestamp: 1758162048107 - pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl name: decorator version: 5.2.1 @@ -1365,6 +1629,40 @@ packages: - pkg:pypi/decorator?source=hash-mapping size: 14129 timestamp: 1740385067843 +- pypi: https://files.pythonhosted.org/packages/f7/e6/efe534ef0952b531b630780e19cabd416e2032697019d5295defc6ef9bd9/deepdiff-8.6.1-py3-none-any.whl + name: deepdiff + version: 8.6.1 + sha256: ee8708a7f7d37fb273a541fa24ad010ed484192cd0c4ffc0fa0ed5e2d4b9e78b + requires_dist: + - orderly-set>=5.4.1,<6 + - click~=8.1.0 ; extra == 'cli' + - pyyaml~=6.0.0 ; extra == 'cli' + - coverage~=7.6.0 ; extra == 'coverage' + - bump2version~=1.0.0 ; extra == 'dev' + - jsonpickle~=4.0.0 ; extra == 'dev' + - ipdb~=0.13.0 ; extra == 'dev' + - numpy~=2.2.0 ; python_full_version >= '3.10' and extra == 'dev' + - numpy~=2.0 ; python_full_version < '3.10' and extra == 'dev' + - python-dateutil~=2.9.0 ; extra == 'dev' + - orjson~=3.10.0 ; extra == 'dev' + - tomli~=2.2.0 ; extra == 'dev' + - tomli-w~=1.2.0 ; extra == 'dev' + - pandas~=2.2.0 ; extra == 'dev' + - polars~=1.21.0 ; extra == 'dev' + - nox==2025.5.1 ; extra == 'dev' + - uuid6==2025.0.1 ; extra == 'dev' + - sphinx~=6.2.0 ; extra == 'docs' + - sphinx-sitemap~=2.6.0 ; extra == 'docs' + - sphinxemoji~=0.3.0 ; extra == 'docs' + - orjson ; extra == 'optimize' + - flake8~=7.1.0 ; extra == 'static' + - flake8-pyproject~=1.2.3 ; extra == 'static' + - pydantic~=2.10.0 ; extra == 'static' + - pytest~=8.3.0 ; extra == 'test' + - pytest-benchmark~=5.1.0 ; extra == 'test' + - pytest-cov~=6.0.0 ; extra == 'test' + - python-dotenv~=1.0.0 ; extra == 'test' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 sha256: 9717a059677553562a8f38ff07f3b9f61727bd614f505658b0a5ecbcf8df89be md5: 961b3a227b437d82ad7054484cfa71b2 @@ -1376,19 +1674,20 @@ packages: - pkg:pypi/defusedxml?source=hash-mapping size: 24062 timestamp: 1615232388757 -- conda: https://conda.anaconda.org/conda-forge/linux-64/deno-1.46.3-hcab8b69_0.conda - sha256: 704bb88a744aacab35c159929d6aee8216e7731e920f7d28254a721059dde4b1 - md5: f8410ffda105ab8d380990bbdf9f266f +- conda: https://conda.anaconda.org/conda-forge/linux-64/deno-2.3.1-hbf66b88_0.conda + sha256: d41255dad26964453c4439cf8789adde9a1615eb7492a9129095ed0400eae3aa + md5: 5343c8d26e6a573e3d2330a24a9be753 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - __glibc >=2.28,<3.0.a0 + - libgcc >=12 + - libzlib >=1.3.1,<2.0a0 constrains: - __glibc >=2.17 license: MIT license_family: MIT purls: [] - size: 39585861 - timestamp: 1726025052074 + size: 72232593 + timestamp: 1746124623923 - conda: https://conda.anaconda.org/conda-forge/linux-64/deno-dom-0.1.41-h4768de7_0.conda sha256: 2726829e1a6117dc9555a2088a4ebaa05035218b8791106f036ba73f15b1b13e md5: 89e80615c6b1b1ae4f5267bfc5fc7f66 @@ -1402,6 +1701,13 @@ packages: purls: [] size: 433150 timestamp: 1736703310469 +- pypi: https://files.pythonhosted.org/packages/e9/87/0fc6e51f9db3a3b3de88fb0c9cf6414d4572d565f4ba4d166023cbd4354d/dirty_equals-0.10.0-py3-none-any.whl + name: dirty-equals + version: 0.10.0 + sha256: bbf4a4eaafd56e371dafe2edf2265315ebd71a441b142ed801511aa33e4c3438 + requires_dist: + - pydantic>=2.4.2 ; extra == 'pydantic' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda sha256: 6d977f0b2fc24fee21a9554389ab83070db341af6d6f09285360b2e09ef8b26e md5: 003b8ba0a94e2f1e117d0bd46aebc901 @@ -1435,16 +1741,16 @@ packages: - pkg:pypi/docstring-parser?source=hash-mapping size: 31742 timestamp: 1753195731224 -- conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.22-pyhd8ed1ab_0.conda - sha256: dd585e49f231ec414e6550783f2aff85027fa829e5d66004ad702e1cfa6324aa - md5: 140faac6cff4382f5ea077ca618b2931 +- conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.22.3-pyhd8ed1ab_0.conda + sha256: ab77ee201665dc654248e3a250bd6fe05db0a1892716a6feb8da4a3162518624 + md5: abbe8c85619c87c4f4f61b44173434af depends: - - python >=3.9 + - python >=3.10 license: CC-PDDC AND BSD-3-Clause AND BSD-2-Clause AND ZPL-2.1 purls: - pkg:pypi/docutils?source=hash-mapping - size: 436452 - timestamp: 1753875179563 + size: 436965 + timestamp: 1762425841874 - conda: https://conda.anaconda.org/conda-forge/noarch/editables-0.5-pyhd8ed1ab_1.conda sha256: 8d4f908e670be360617d418c328213bc46e7100154c3742db085148141712f60 md5: 2cf824fe702d88e641eec9f9f653e170 @@ -1456,14 +1762,13 @@ packages: - pkg:pypi/editables?source=hash-mapping size: 10828 timestamp: 1733208220327 -- conda: https://conda.anaconda.org/conda-forge/linux-64/esbuild-0.25.9-hfc2019e_0.conda - sha256: d8916248880b129734357f76dc51a0a595a72b6d0d22d691250fe90d8094967a - md5: 37dd55299d6c44d5ad79dce2386df011 +- conda: https://conda.anaconda.org/conda-forge/linux-64/esbuild-0.27.0-hfc2019e_0.conda + sha256: ed48a39e1d049db7286c097360e0ad8a8aedc966537c297e310952f3f3f9a2e7 + md5: fc6322bea72892590d4c975187575464 license: MIT - license_family: MIT purls: [] - size: 4320313 - timestamp: 1755057047619 + size: 4410264 + timestamp: 1762716479223 - pypi: https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl name: et-xmlfile version: 2.0.0 @@ -1480,10 +1785,10 @@ packages: - pkg:pypi/exceptiongroup?source=hash-mapping size: 21284 timestamp: 1746947398083 -- pypi: https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl name: executing - version: 2.2.0 - sha256: 11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa + version: 2.2.1 + sha256: 760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017 requires_dist: - asttokens>=2.1.0 ; extra == 'tests' - ipython ; extra == 'tests' @@ -1493,49 +1798,51 @@ packages: - littleutils ; extra == 'tests' - rich ; python_full_version >= '3.11' and extra == 'tests' requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.0-pyhd8ed1ab_0.conda - sha256: 7510dd93b9848c6257c43fdf9ad22adf62e7aa6da5f12a6a757aed83bcfedf05 - md5: 81d30c08f9a3e556e8ca9e124b044d14 +- conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + sha256: 210c8165a58fdbf16e626aac93cc4c14dbd551a01d1516be5ecad795d2422cad + md5: ff9efb7f7469aed3c4a8106ffa29593c depends: - - python >=3.9 + - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/executing?source=hash-mapping - size: 29652 - timestamp: 1745502200340 -- conda: https://conda.anaconda.org/conda-forge/noarch/fastmcp-2.10.6-pyhe01879c_0.conda - sha256: c4aaafc642f4f1f0187f5d136fd2fa709e9df59373ff119af573a864398e3feb - md5: 10c24592557c0d2fcaf26f7d32f05563 + size: 30753 + timestamp: 1756729456476 +- conda: https://conda.anaconda.org/conda-forge/noarch/fastmcp-2.12.5-pyhcf101f3_0.conda + sha256: 4f04024e619f36225fb7074db202e8a213490a924a5444ba13b2714add0d59fe + md5: a0bfcfe051363dea8dbcf84e0d3d0c3b depends: - python >=3.10,<4 - python-dotenv >=1.1.0 - exceptiongroup >=1.2.2 - httpx >=0.28.1 - - mcp >=1.10.0 + - mcp >=1.12.4,<1.17.0 - openapi-pydantic >=0.5.1 - rich >=13.9.4 - cyclopts >=3.0.0 - authlib >=1.5.2 - pydantic >=2.11.7 - pyperclip >=1.9.0 + - openapi-core >=0.19.5 + - openai >=1.95.1 - python license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/fastmcp?source=hash-mapping - size: 160491 - timestamp: 1753016245093 -- conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.19.1-pyhd8ed1ab_0.conda - sha256: 7a2497c775cc7da43b5e32fc5cf9f4e8301ca723f0eb7f808bbe01c6094a3693 - md5: 9c418d067409452b2e87e0016257da68 + size: 227432 + timestamp: 1760801401155 +- conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.20.0-pyhd8ed1ab_0.conda + sha256: 19025a4078ff3940d97eb0da29983d5e0deac9c3e09b0eabf897daeaf9d1114e + md5: 66b8b26023b8efdf8fcb23bac4b6325d depends: - - python >=3.9 + - python >=3.10 license: Unlicense purls: - - pkg:pypi/filelock?source=compressed-mapping - size: 18003 - timestamp: 1755216353218 + - pkg:pypi/filelock?source=hash-mapping + size: 17976 + timestamp: 1759948208140 - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda sha256: 2509992ec2fd38ab27c7cdb42cf6cadc566a1cc0d1021a2673475d9fa87c6276 md5: d3549fd50d450b6d9e7dddff25dd2110 @@ -1548,6 +1855,80 @@ packages: - pkg:pypi/fqdn?source=hash-mapping size: 16705 timestamp: 1733327494780 +- pypi: https://files.pythonhosted.org/packages/a9/7a/dac76d31584bb4f874ae860490c9465f5b59bd8c110f68fbbb07aba48845/frictionless-5.18.1-py3-none-any.whl + name: frictionless + version: 5.18.1 + sha256: 3f4c87469a89bdb88e9cc318088553a26f3d14839098f95c183ea01fc89628dd + requires_dist: + - attrs>=22.2.0 + - chardet>=3.0 + - humanize>=4.2 + - isodate>=0.6 + - jinja2>=3.0 + - jsonschema>=4.20 + - marko>=1.0 + - petl>=1.6 + - pydantic>=2.0 + - python-dateutil>=2.8 + - python-slugify>=1.2 + - pyyaml>=5.3 + - requests>=2.10 + - rfc3986>=1.4 + - simpleeval>=0.9.11 + - tabulate>=0.8.10 + - typer>=0.12 + - typing-extensions>=4.3 + - validators>=0.18 + - boto3>=1.9 ; extra == 'aws' + - google-api-python-client>=1.12.1 ; extra == 'bigquery' + - frictionless-ckan-mapper>=1.0 ; extra == 'ckan' + - datasette>=0.64.2 ; extra == 'datasette' + - hatch ; extra == 'dev' + - httpx ; extra == 'dev' + - ipython ; extra == 'dev' + - livemark ; extra == 'dev' + - moto ; extra == 'dev' + - neovim ; extra == 'dev' + - oauth2client ; extra == 'dev' + - pyright==1.1.317 ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - pytest-dotenv ; extra == 'dev' + - pytest-lazy-fixtures ; extra == 'dev' + - pytest-mock ; extra == 'dev' + - pytest-timeout ; extra == 'dev' + - pytest-vcr ; extra == 'dev' + - requests-mock ; extra == 'dev' + - ruff ; extra == 'dev' + - yattag ; extra == 'dev' + - duckdb-engine>=0.7 ; extra == 'duckdb' + - duckdb>=0.8 ; extra == 'duckdb' + - sqlalchemy>=1.4,<=2.0.35 ; extra == 'duckdb' + - openpyxl>=3.0 ; extra == 'excel' + - tableschema-to-template>=0.0 ; extra == 'excel' + - xlrd>=1.2 ; extra == 'excel' + - xlwt>=1.2 ; extra == 'excel' + - pygithub>=1.50 ; extra == 'github' + - pygsheets>=2.0 ; extra == 'gsheets' + - pyquery>=1.4 ; extra == 'html' + - ijson>=3.0 ; extra == 'json' + - jsonlines>=1.2 ; extra == 'json' + - pymysql>=1.0 ; extra == 'mysql' + - sqlalchemy>=1.4 ; extra == 'mysql' + - ezodf>=0.3 ; extra == 'ods' + - lxml>=4.0 ; extra == 'ods' + - pandas>=1.0 ; extra == 'pandas' + - pyarrow>=14.0 ; extra == 'pandas' + - fastparquet>=0.8 ; extra == 'parquet' + - psycopg2>=2.9 ; extra == 'postgresql' + - psycopg>=3.0 ; extra == 'postgresql' + - sqlalchemy>=1.4 ; extra == 'postgresql' + - savreaderwriter>=3.0 ; extra == 'spss' + - sqlalchemy>=1.4 ; extra == 'sql' + - visidata>=2.10 ; extra == 'visidata' + - tatsu>=5.8.3 ; extra == 'wkt' + - pyzenodo3>=1.0 ; extra == 'zenodo' + requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.7.0-py312h447239a_0.conda sha256: f4e0e6cd241bc24afb2d6d08e5d2ba170fad2475e522bdf297b7271bba268be6 md5: 63e20cf7b7460019b423fc06abb96c60 @@ -1563,17 +1944,17 @@ packages: - pkg:pypi/frozenlist?source=hash-mapping size: 55037 timestamp: 1752167383781 -- conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2025.7.0-pyhd8ed1ab_0.conda - sha256: f734d98cd046392fbd9872df89ac043d72ac15f6a2529f129d912e28ab44609c - md5: a31ce802cd0ebfce298f342c02757019 +- conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2025.10.0-pyhd8ed1ab_0.conda + sha256: df5cb57bb668cd5b2072d8bd66380ff7acb12e8c337f47dd4b9a75a6a6496a6d + md5: d18004c37182f83b9818b714825a7627 depends: - - python >=3.9 + - python >=3.10 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/fsspec?source=compressed-mapping - size: 145357 - timestamp: 1752608821935 + size: 146592 + timestamp: 1761840236679 - conda: https://conda.anaconda.org/conda-forge/noarch/fuzy-jon-0.1.0-pyhd8ed1ab_0.conda sha256: e2d3a33ff870effc96f03d25912884fc5177b0b2e18fc198fd781a30de6b10d0 md5: 1c7a40a765baa74b07b5bc202d950be4 @@ -1591,6 +1972,10 @@ packages: version: 0.4.0 sha256: b7adcdd5adbebf1adf17378da5ba3f543684dbec47b1cda1f3997e573cd542c4 requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' +- pypi: https://files.pythonhosted.org/packages/f8/5c/e226de133afd8bb267ec27eead9ae3d784b95b39a287ed404caab39a5f50/genson-1.3.0-py3-none-any.whl + name: genson + version: 1.3.0 + sha256: 468feccd00274cc7e4c09e84b08704270ba8d95232aa280f65b986139cec67f7 - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhd8ed1ab_0.conda sha256: f64b68148c478c3bfc8f8d519541de7d2616bf59d44485a5271041d40c061887 md5: 4b69232755285701bc86a5afe4d9933a @@ -1612,6 +1997,7 @@ packages: - hpack >=4.1,<5 - python license: MIT + license_family: MIT purls: - pkg:pypi/h2?source=compressed-mapping size: 95967 @@ -1662,25 +2048,25 @@ packages: - pkg:pypi/hatchling?source=hash-mapping size: 56598 timestamp: 1734311718682 -- conda: https://conda.anaconda.org/conda-forge/linux-64/hf-xet-1.1.8-py39h598437d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/hf-xet-1.2.0-py310hb823017_0.conda noarch: python - sha256: 3d219dcd015308c37201a45b710811d16b81a4b79d7c5fa8bb38efd93f323d86 - md5: a5b6e561de75ba61f5adc0d702defb4b + sha256: c134796866f5d2a6851512f1598399df157ff02db81eb7bbac2964681d9ee96b + md5: 77edbfd5f562cb044ef73ac185581df9 depends: - python - - __glibc >=2.17,<3.0.a0 - libgcc >=14 + - __glibc >=2.17,<3.0.a0 - _python_abi3_support 1.* - - cpython >=3.9 - - openssl >=3.5.2,<4.0a0 + - cpython >=3.10 + - openssl >=3.5.4,<4.0a0 constrains: - __glibc >=2.17 license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/hf-xet?source=compressed-mapping - size: 2599548 - timestamp: 1755587744407 + - pkg:pypi/hf-xet?source=hash-mapping + size: 2703061 + timestamp: 1761341459458 - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba md5: 0a802cb9888dd14eeefc611f05c40b6e @@ -1724,38 +2110,50 @@ packages: - pkg:pypi/httpx?source=hash-mapping size: 63082 timestamp: 1733663449209 -- conda: https://conda.anaconda.org/conda-forge/noarch/httpx-sse-0.4.1-pyhd8ed1ab_0.conda - sha256: b19ece3b0d085a193710044f5ce4f207b60433897476f2132e68c3b8d916e537 - md5: 11186f5dd073e7d06e711eb3abdb6252 +- conda: https://conda.anaconda.org/conda-forge/noarch/httpx-sse-0.4.3-pyhd8ed1ab_0.conda + sha256: afe03faa3d227869d2d645cce2b902b9f76c297207bf5db1670cab56a4b09834 + md5: d884b0fc71e824093baf8f437d585461 depends: - httpx - - python >=3.9 + - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/httpx-sse?source=hash-mapping - size: 13816 - timestamp: 1750777567553 -- conda: https://conda.anaconda.org/conda-forge/noarch/huggingface_hub-0.34.4-pyhd8ed1ab_0.conda - sha256: 8b88d24987e7fe1ad65ff8304799af5a1029bc73dbf30c8a641830c17c21d61f - md5: 222c7a91b0cb1e54e169d1be00b805a3 + size: 14711 + timestamp: 1760142772011 +- conda: https://conda.anaconda.org/conda-forge/noarch/huggingface_hub-1.1.2-pyhd8ed1ab_0.conda + sha256: e67b17bef274d4655ddcc481a9492b1cb1ce1937fe84ea3ea35ad30b39d58df8 + md5: 8243752658148716c03bd193ebb9760d depends: - filelock - fsspec >=2023.5.0 - - hf-xet >=1.1.3,<2.0.0 + - hf-xet >=1.2.0,<2.0.0 + - httpx >=0.23.0,<1 - packaging >=20.9 - - python >=3.9 + - python >=3.10 - pyyaml >=5.1 - requests + - shellingham - tqdm >=4.42.1 + - typer-slim - typing-extensions >=3.7.4.3 - typing_extensions >=3.7.4.3 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/huggingface-hub?source=hash-mapping - size: 334085 - timestamp: 1754700574257 + size: 320779 + timestamp: 1762428834983 +- pypi: https://files.pythonhosted.org/packages/c3/5b/9512c5fb6c8218332b530f13500c6ff5f3ce3342f35e0dd7be9ac3856fd3/humanize-4.14.0-py3-none-any.whl + name: humanize + version: 4.14.0 + sha256: d57701248d040ad456092820e6fde56c930f17749956ac47f4f655c0c547bfff + requires_dist: + - freezegun ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + requires_python: '>=3.10' - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 md5: 8e6923fc12f1fe8f8c4e5c9f343256ac @@ -1780,27 +2178,39 @@ packages: - pkg:pypi/hyperlink?source=hash-mapping size: 74751 timestamp: 1733319972207 -- pypi: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda + sha256: 71e750d509f5fa3421087ba88ef9a7b9be11c53174af3aa4d06aff4c18b38e8e + md5: 8b189310083baabfb622af68fd9d3ae3 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: MIT + license_family: MIT + purls: [] + size: 12129203 + timestamp: 1720853576813 +- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl name: idna - version: '3.10' - sha256: 946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 + version: '3.11' + sha256: 771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea requires_dist: - ruff>=0.6.2 ; extra == 'all' - mypy>=1.11.2 ; extra == 'all' - pytest>=8.3.2 ; extra == 'all' - flake8>=7.1.1 ; extra == 'all' - requires_python: '>=3.6' -- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.10-pyhd8ed1ab_1.conda - sha256: d7a472c9fd479e2e8dcb83fb8d433fce971ea369d704ece380e876f9c3494e87 - md5: 39a4f67be3286c86d696df570b1201b7 + requires_python: '>=3.8' +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0 + md5: 53abe63df7e10a6ba605dc5f9f961d36 depends: - - python >=3.9 + - python >=3.10 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/idna?source=hash-mapping - size: 49765 - timestamp: 1733211921194 + size: 50721 + timestamp: 1760286526795 - pypi: https://files.pythonhosted.org/packages/0f/a4/25df835a9b9b372a4a869a8a1ac30a32199f2b3f581ad0e249f7e3d19eed/immutables-0.21-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: immutables version: '0.21' @@ -1848,22 +2258,46 @@ packages: - pkg:pypi/importlib-resources?source=hash-mapping size: 33781 timestamp: 1736252433366 -- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda - sha256: 0ec8f4d02053cd03b0f3e63168316530949484f80e16f5e2fb199a1d117a89ca - md5: 6837f3eff7dcea42ecd714ce1ac2b108 +- pypi: https://files.pythonhosted.org/packages/8a/eb/427ed2b20a38a4ee29f24dbe4ae2dafab198674fe9a85e3d6adf9e5f5f41/inflect-7.5.0-py3-none-any.whl + name: inflect + version: 7.5.0 + sha256: 2aea70e5e70c35d8350b8097396ec155ffd68def678c7ff97f51aa69c1d92344 + requires_dist: + - more-itertools>=8.5.0 + - typeguard>=4.0.1 + - typing-extensions ; python_full_version < '3.9' + - pytest>=6,!=8.1.* ; extra == 'test' + - pygments ; extra == 'test' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - pytest-checkdocs>=2.4 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - pytest-enabler>=2.2 ; extra == 'enabler' + - pytest-mypy ; extra == 'type' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda + sha256: e1a9e3b1c8fe62dc3932a616c284b5d8cbe3124bbfbedcf4ce5c828cb166ee19 + md5: 9614359868482abba1bd15ce465e3c42 depends: - - python >=3.9 + - python >=3.10 license: MIT license_family: MIT purls: - - pkg:pypi/iniconfig?source=hash-mapping - size: 11474 - timestamp: 1733223232820 + - pkg:pypi/iniconfig?source=compressed-mapping + size: 13387 + timestamp: 1760831448842 - pypi: ./ name: ipyautoui - version: 0.7.27.dev5+g1a777b20d - sha256: 80bde0b5ca0219044e916ad31bec9ca7ee48399399b7c67b5725a04d7b08af8f + version: 0.7.27.dev57+ge3983b8bb.d20251112 + sha256: 6c7821934fedd45a563e97c4e8173aa2122eaa4d9c5a8a32e41e0f2c4b72e51b requires_dist: + - datamodel-code-generator>=0.28.5 + - deepdiff - immutables - ipydatagrid==1.3.2 - ipyfilechooser @@ -1881,6 +2315,8 @@ packages: - pyyaml - requests - wcmatch + - xlsxdatagrid>=0.3.2,<0.4 + requires_python: '>=3.8,<3.14' editable: true - pypi: https://files.pythonhosted.org/packages/40/36/de3566f8a2140d403e66cd2d96dbbd6b425157473166a7ab295a0d217764/ipydatagrid-1.3.2-py3-none-any.whl name: ipydatagrid @@ -1901,10 +2337,11 @@ packages: sha256: 4555c24b30b819c91dc0ae5e6f7e4cf8f90e5cca531a9209a1fe4deee288d5c5 requires_dist: - ipywidgets -- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-6.30.1-pyh82676e8_0.conda - sha256: cfc2c4e31dfedbb3d124d0055f55fda4694538fb790d52cd1b37af5312833e36 - md5: b0cc25825ce9212b8bee37829abad4d6 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.1.0-pyha191276_0.conda + sha256: a9d6b74115dbd62e19017ff8fa4885b07b5164427f262cc15b5307e5aaf3ee73 + md5: c6f63cfe66adaa5650788e3106b6683a depends: + - python - __linux - comm >=0.1.1 - debugpy >=1.6.5 @@ -1915,30 +2352,33 @@ packages: - nest-asyncio >=1.4 - packaging >=22 - psutil >=5.7 - - python >=3.9 + - python >=3.10 - pyzmq >=25 - tornado >=6.2 - traitlets >=5.4.0 + - python + constrains: + - appnope >=0.1.2 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/ipykernel?source=hash-mapping - size: 121367 - timestamp: 1754352984703 -- pypi: https://files.pythonhosted.org/packages/63/f8/0031ee2b906a15a33d6bfc12dd09c3dfa966b3cb5b284ecfb7549e6ac3c4/ipython-9.4.0-py3-none-any.whl + size: 133820 + timestamp: 1761567932044 +- pypi: https://files.pythonhosted.org/packages/05/aa/62893d6a591d337aa59dcc4c6f6c842f1fe20cd72c8c5c1f980255243252/ipython-9.7.0-py3-none-any.whl name: ipython - version: 9.4.0 - sha256: 25850f025a446d9b359e8d296ba175a36aedd32e83ca9b5060430fe16801f066 + version: 9.7.0 + sha256: bce8ac85eb9521adc94e1845b4c03d88365fd6ac2f4908ec4ed1eb1b0a065f9f requires_dist: - - colorama ; sys_platform == 'win32' - - decorator - - ipython-pygments-lexers - - jedi>=0.16 - - matplotlib-inline + - colorama>=0.4.4 ; sys_platform == 'win32' + - decorator>=4.3.2 + - ipython-pygments-lexers>=1.0.0 + - jedi>=0.18.1 + - matplotlib-inline>=0.1.5 - pexpect>4.3 ; sys_platform != 'emscripten' and sys_platform != 'win32' - prompt-toolkit>=3.0.41,<3.1.0 - - pygments>=2.4.0 - - stack-data + - pygments>=2.11.0 + - stack-data>=0.6.0 - traitlets>=5.13.0 - typing-extensions>=4.6 ; python_full_version < '3.12' - black ; extra == 'black' @@ -1946,46 +2386,44 @@ packages: - exceptiongroup ; extra == 'doc' - intersphinx-registry ; extra == 'doc' - ipykernel ; extra == 'doc' - - ipython[test] ; extra == 'doc' - - matplotlib ; extra == 'doc' - - setuptools>=18.5 ; extra == 'doc' + - ipython[matplotlib,test] ; extra == 'doc' + - setuptools>=70.0 ; extra == 'doc' - sphinx-toml==0.0.4 ; extra == 'doc' - - sphinx-rtd-theme ; extra == 'doc' - - sphinx>=1.3 ; extra == 'doc' + - sphinx-rtd-theme>=0.1.8 ; extra == 'doc' + - sphinx>=8.0 ; extra == 'doc' - typing-extensions ; extra == 'doc' - - pytest ; extra == 'test' - - pytest-asyncio<0.22 ; extra == 'test' - - testpath ; extra == 'test' - - packaging ; extra == 'test' + - pytest>=7.0.0 ; extra == 'test' + - pytest-asyncio>=1.0.0 ; extra == 'test' + - testpath>=0.2 ; extra == 'test' + - packaging>=20.1.0 ; extra == 'test' + - setuptools>=61.2 ; extra == 'test' - ipython[test] ; extra == 'test-extra' - curio ; extra == 'test-extra' - jupyter-ai ; extra == 'test-extra' - - matplotlib!=3.2.0 ; extra == 'test-extra' + - ipython[matplotlib] ; extra == 'test-extra' - nbformat ; extra == 'test-extra' - nbclient ; extra == 'test-extra' - - ipykernel ; extra == 'test-extra' - - numpy>=1.23 ; extra == 'test-extra' - - pandas ; extra == 'test-extra' - - trio ; extra == 'test-extra' - - matplotlib ; extra == 'matplotlib' + - ipykernel>6.30 ; extra == 'test-extra' + - numpy>=1.27 ; extra == 'test-extra' + - pandas>2.1 ; extra == 'test-extra' + - trio>=0.1.0 ; extra == 'test-extra' + - matplotlib>3.9 ; extra == 'matplotlib' - ipython[doc,matplotlib,test,test-extra] ; extra == 'all' requires_python: '>=3.11' -- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.4.0-pyhfa0c392_0.conda - sha256: ff5138bf6071ca01d84e1329f6baa96f0723df6fe183cfa1ab3ebc96240e6d8f - md5: cb7706b10f35e7507917cefa0978a66d +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.7.0-pyh53cf698_0.conda + sha256: b27fb08b14d82e896f35fe5ce889665aabb075bd540f9761c838d1d09a3d9704 + md5: 2d6b86a2e11b8cb2f20a432158ef10b9 depends: - __unix - pexpect >4.3 - - decorator - - exceptiongroup - - ipython_pygments_lexers - - jedi >=0.16 - - matplotlib-inline - - pickleshare + - decorator >=4.3.2 + - ipython_pygments_lexers >=1.0.0 + - jedi >=0.18.1 + - matplotlib-inline >=0.1.5 - prompt-toolkit >=3.0.41,<3.1.0 - - pygments >=2.4.0 + - pygments >=2.11.0 - python >=3.11 - - stack_data + - stack_data >=0.6.0 - traitlets >=5.13.0 - typing_extensions >=4.6 - python @@ -1993,8 +2431,8 @@ packages: license_family: BSD purls: - pkg:pypi/ipython?source=hash-mapping - size: 628259 - timestamp: 1751465044469 + size: 643036 + timestamp: 1762350942197 - pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl name: ipython-pygments-lexers version: 1.1.1 @@ -2014,10 +2452,10 @@ packages: - pkg:pypi/ipython-pygments-lexers?source=hash-mapping size: 13993 timestamp: 1737123723464 -- pypi: https://files.pythonhosted.org/packages/0a/c5/226ff8aaf6248edf16246498d7885805e2c8b122631ac133130b0612b1ad/ipyvue-1.11.2-py2.py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/48/f4/93c187f69bbd58669d315f5463124ef62484a24335bc6702d19c83d1311e/ipyvue-1.11.3-py2.py3-none-any.whl name: ipyvue - version: 1.11.2 - sha256: e009efa97ec223c4833a6c8ef3a473385d767ff69518ff94f107400517333353 + version: 1.11.3 + sha256: f6f4680a8b61c190dd56a461b5c595d05d84699dde2f7dd5c43f5db7520c6028 requires_dist: - ipywidgets>=7.0.0 - pre-commit ; extra == 'dev' @@ -2043,10 +2481,10 @@ packages: - sphinx-design ; extra == 'doc' - sphinx-rtd-theme ; extra == 'doc' requires_python: '>=3.6' -- pypi: https://files.pythonhosted.org/packages/58/6a/9166369a2f092bd286d24e6307de555d63616e8ddb373ebad2b5635ca4cd/ipywidgets-8.1.7-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl name: ipywidgets - version: 8.1.7 - sha256: 764f2602d25471c213919b8a1997df04bef869251db4ca8efba1b76b1bd9f7bb + version: 8.1.8 + sha256: ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e requires_dist: - comm>=0.1.3 - ipython>=6.1.0 @@ -2059,6 +2497,22 @@ packages: - pytest-cov ; extra == 'test' - pytz ; extra == 'test' requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl + name: isodate + version: 0.7.2 + sha256: 28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15 + requires_python: '>=3.7' +- conda: https://conda.anaconda.org/conda-forge/noarch/isodate-0.7.2-pyhd8ed1ab_1.conda + sha256: 845fc87dfaf3f96245ad6ad69c5e5b31b084979f64f9e32157888ee0a08f39ba + md5: 14c42a6334f38c412449f5a5e4043a5a + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/isodate?source=hash-mapping + size: 23778 + timestamp: 1733230826126 - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda sha256: 08e838d29c134a7684bca0468401d26840f41c92267c4126d7b43a6b533b0aed md5: 0b0154421989637d424ccf0f104be51a @@ -2071,6 +2525,15 @@ packages: - pkg:pypi/isoduration?source=hash-mapping size: 19832 timestamp: 1733493720346 +- pypi: https://files.pythonhosted.org/packages/7f/cc/9b681a170efab4868a032631dea1e8446d8ec718a7f657b94d49d1a12643/isort-6.1.0-py3-none-any.whl + name: isort + version: 6.1.0 + sha256: 58d8927ecce74e5087aef019f778d4081a3b6c98f15a80ba35782ca8a2097784 + requires_dist: + - importlib-metadata>=4.6.0 ; python_full_version < '3.10' + - colorama ; extra == 'colors' + - setuptools ; extra == 'plugins' + requires_python: '>=3.9.0' - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.classes-3.4.0-pyhd8ed1ab_2.conda sha256: 3d16a0fa55a29fe723c918a979b2ee927eb0bf9616381cdfd26fa9ea2b649546 md5: ade6b25a6136661dadd1a43e4350b10b @@ -2169,6 +2632,14 @@ packages: - pkg:pypi/jeepney?source=hash-mapping size: 40015 timestamp: 1740828380668 +- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + name: jinja2 + version: 3.1.6 + sha256: 85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 + requires_dist: + - markupsafe>=2.0 + - babel>=2.7 ; extra == 'i18n' + requires_python: '>=3.7' - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhd8ed1ab_0.conda sha256: f1ac18b11637ddadc05642e8185a851c7fab5998c6f5470d716812fae943b2af md5: 446bd6c8cb26050d528881df495ce646 @@ -2181,22 +2652,21 @@ packages: - pkg:pypi/jinja2?source=hash-mapping size: 112714 timestamp: 1741263433881 -- conda: https://conda.anaconda.org/conda-forge/linux-64/jiter-0.10.0-py312h12e396e_0.conda - sha256: 2d08c42c347fe32b4ec03c5c803a641812d65711b43a32a820cd13d9d1984d86 - md5: a3f7a6978a83ba7ae8d68bbd336e731b +- conda: https://conda.anaconda.org/conda-forge/linux-64/jiter-0.12.0-py312h0ccc70a_1.conda + sha256: 1378a84955f5138d2d11cc7d4aa94bf2ed1911e580cf2e5c456137f86b64e28b + md5: ccf459efc6b440de02a8443321505364 depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 constrains: - __glibc >=2.17 license: MIT - license_family: MIT purls: - pkg:pypi/jiter?source=hash-mapping - size: 309543 - timestamp: 1747609999738 + size: 310877 + timestamp: 1763006795569 - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.12.1-pyhd8ed1ab_0.conda sha256: 4e08ccf9fa1103b617a4167a270768de736a36be795c6cd34c2761100d332f74 md5: 0fc93f473c31a2f85c0bde213e7c63ca @@ -2208,9 +2678,9 @@ packages: - pkg:pypi/json5?source=hash-mapping size: 34191 timestamp: 1755034963991 -- conda: https://conda.anaconda.org/conda-forge/linux-64/jsonpointer-3.0.0-py312h7900ff3_1.conda - sha256: 76ccb7bffc7761d1d3133ffbe1f7f1710a0f0d9aaa9f7ea522652e799f3601f4 - md5: 6b51f7459ea4073eeb5057207e2e1e3d +- conda: https://conda.anaconda.org/conda-forge/linux-64/jsonpointer-3.0.0-py312h7900ff3_2.conda + sha256: 39c77cd86d9f544e3ce11fdbab1047181d08dd14a72461d06d957b5fcfc78615 + md5: eeaf37c3dc2d1660668bd102c841f783 depends: - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 @@ -2218,25 +2688,52 @@ packages: license_family: BSD purls: - pkg:pypi/jsonpointer?source=hash-mapping - size: 17277 - timestamp: 1725303032027 -- conda: https://conda.anaconda.org/conda-forge/linux-64/jsonpointer-3.0.0-py313h78bf25f_1.conda - sha256: 18d412dc91ee7560f0f94c19bb1c3c23f413b9a7f55948e2bb3ce44340439a58 - md5: 668d64b50e7ce7984cfe09ed7045b9fa + size: 17957 + timestamp: 1756754245172 +- conda: https://conda.anaconda.org/conda-forge/linux-64/jsonpointer-3.0.0-py313h78bf25f_2.conda + sha256: 9174f5209f835cc8918acddc279be919674d874179197e025181fe2a71cb0bce + md5: c1375f38e5f3ee38a9ee0e405a601c35 depends: - - python >=3.13.0rc1,<3.14.0a0 + - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jsonpointer?source=hash-mapping - size: 17568 - timestamp: 1725303033801 + size: 18143 + timestamp: 1756754243113 - pypi: https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl name: jsonref version: 1.1.0 sha256: 590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9 requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl + name: jsonschema + version: 4.25.1 + sha256: 3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63 + requires_dist: + - attrs>=22.2.0 + - jsonschema-specifications>=2023.3.6 + - referencing>=0.28.4 + - rpds-py>=0.7.1 + - fqdn ; extra == 'format' + - idna ; extra == 'format' + - isoduration ; extra == 'format' + - jsonpointer>1.13 ; extra == 'format' + - rfc3339-validator ; extra == 'format' + - rfc3987 ; extra == 'format' + - uri-template ; extra == 'format' + - webcolors>=1.11 ; extra == 'format' + - fqdn ; extra == 'format-nongpl' + - idna ; extra == 'format-nongpl' + - isoduration ; extra == 'format-nongpl' + - jsonpointer>1.13 ; extra == 'format-nongpl' + - rfc3339-validator ; extra == 'format-nongpl' + - rfc3986-validator>0.1.0 ; extra == 'format-nongpl' + - rfc3987-syntax>=1.1.0 ; extra == 'format-nongpl' + - uri-template ; extra == 'format-nongpl' + - webcolors>=24.6.0 ; extra == 'format-nongpl' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.25.1-pyhe01879c_0.conda sha256: ac377ef7762e49cb9c4f985f1281eeff471e9adc3402526eea78e6ac6589cf1d md5: 341fd940c242cf33e832c0402face56f @@ -2250,22 +2747,45 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/jsonschema?source=compressed-mapping + - pkg:pypi/jsonschema?source=hash-mapping size: 81688 timestamp: 1755595646123 -- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.4.1-pyh29332c3_0.conda - sha256: 66fbad7480f163509deec8bd028cd3ea68e58022982c838683586829f63f3efa - md5: 41ff526b1083fde51fbdc93f29282e0e +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-path-0.3.4-pyh29332c3_0.conda + sha256: 54ae9b11f76c2cf962f07b9711865a6ca482e7f23109cca447160aec51256fda + md5: 2db827e73306cbf15c69ee52b250d68b depends: + - pathable >=0.4.1,<0.5.0 - python >=3.9 + - pyyaml >=5.1 + - referencing <0.37.0 + - requests >=2.31.0,<3.0.0 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/jsonschema-path?source=hash-mapping + size: 22714 + timestamp: 1737837054101 +- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + name: jsonschema-specifications + version: 2025.9.1 + sha256: 98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe + requires_dist: + - referencing>=0.31.0 + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 + md5: 439cd0f567d697b20a8f45cb70a1005a + depends: + - python >=3.10 - referencing >=0.31.0 - python license: MIT license_family: MIT purls: - pkg:pypi/jsonschema-specifications?source=hash-mapping - size: 19168 - timestamp: 1745424244298 + size: 19236 + timestamp: 1757335715225 - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.25.1-he01879c_0.conda sha256: aef6705fe1335e6472e1b6365fcdb586356b18dceff72d8d6a315fc90e900ccf md5: 13e31c573c884962318a738405ca3487 @@ -2285,20 +2805,20 @@ packages: purls: [] size: 4744 timestamp: 1755595646123 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.2.6-pyhe01879c_0.conda - sha256: 6f2d6c5983e013af68e7e1d7082cc46b11f55e28147bd0a72a44488972ed90a3 - md5: 7129ed52335cc7164baf4d6508a3f233 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.0-pyhcf101f3_0.conda + sha256: 897ad2e2c2335ef3c2826d7805e16002a1fd0d509b4ae0bc66617f0e0ff07bc2 + md5: 62b7c96c6cd77f8173cc5cada6a9acaa depends: - importlib-metadata >=4.8.3 - jupyter_server >=1.1.2 - - python >=3.9 + - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jupyter-lsp?source=compressed-mapping - size: 58416 - timestamp: 1752935193718 + - pkg:pypi/jupyter-lsp?source=hash-mapping + size: 60377 + timestamp: 1756388269267 - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.6.3-pyhd8ed1ab_1.conda sha256: 19d8bd5bb2fde910ec59e081eeb59529491995ce0d653a5209366611023a0b3a md5: 4ebae00eae9705b0c3d6d1018a81d047 @@ -2316,20 +2836,24 @@ packages: - pkg:pypi/jupyter-client?source=hash-mapping size: 106342 timestamp: 1733441040958 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.8.1-pyh31011fe_0.conda - sha256: 56a7a7e907f15cca8c4f9b0c99488276d4cb10821d2d15df9245662184872e81 - md5: b7d89d860ebcda28a5303526cdee68ab +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + sha256: 1d34b80e5bfcd5323f104dbf99a2aafc0e5d823019d626d0dce5d3d356a2a52a + md5: b38fe4e78ee75def7e599843ef4c1ab0 depends: - __unix + - python - platformdirs >=2.5 - - python >=3.8 + - python >=3.10 - traitlets >=5.3 + - python + constrains: + - pywin32 >=300 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/jupyter-core?source=hash-mapping - size: 59562 - timestamp: 1748333186063 + size: 65503 + timestamp: 1760643864586 - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.0-pyh29332c3_0.conda sha256: 37e6ac3ccf7afcc730c3b93cb91a13b9ae827fd306f35dd28f958a74a14878b5 md5: f56000b36f09ab7533877e695e4e8cb0 @@ -2377,7 +2901,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jupyter-server?source=compressed-mapping + - pkg:pypi/jupyter-server?source=hash-mapping size: 347094 timestamp: 1755870522134 - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.3-pyhd8ed1ab_1.conda @@ -2392,9 +2916,9 @@ packages: - pkg:pypi/jupyter-server-terminals?source=hash-mapping size: 19711 timestamp: 1733428049134 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.4.6-pyhd8ed1ab_0.conda - sha256: c3558f1c2a5977799ce425f1f7c8d8d1cae3408da41ec4f5c3771a21e673d465 - md5: 70cb2903114eafc6ed5d70ca91ba6545 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.4.10-pyhd8ed1ab_0.conda + sha256: 1ce33112e545bcfc41f92747f4f8b0f36310937339334bfaabe2496a65b3f5b2 + md5: 0fc7cfcd261709ef5591c1ea3415e8a7 depends: - async-lru >=1.0.0 - httpx >=0.25.0,<1 @@ -2407,7 +2931,7 @@ packages: - jupyterlab_server >=2.27.1,<3 - notebook-shim >=0.2 - packaging - - python >=3.9 + - python >=3.10 - setuptools >=41.1.0 - tomli >=1.2.2 - tornado >=6.2.0 @@ -2416,17 +2940,17 @@ packages: license_family: BSD purls: - pkg:pypi/jupyterlab?source=compressed-mapping - size: 8408461 - timestamp: 1755263247917 + size: 8034306 + timestamp: 1761146412485 - pypi: https://files.pythonhosted.org/packages/7e/6b/a3c4d85f8f609c78336e76b78733d5cdd0871b79fcce1fa66533849aab0c/jupyterlab_quarto-0.3.5-py3-none-any.whl name: jupyterlab-quarto version: 0.3.5 sha256: 114165409aaad2e68202374ab3d02b08015ed3898427d81bdb3fe9f995e151b9 requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/43/6a/ca128561b22b60bd5a0c4ea26649e68c8556b82bc70a0c396eebc977fe86/jupyterlab_widgets-3.0.15-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl name: jupyterlab-widgets - version: 3.0.15 - sha256: d59023d7d7ef71400d51e6fee9a88867f6e65e10a4201605d2d7f3e8f012a31c + version: 3.0.16 + sha256: 45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8 requires_python: '>=3.7' - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda sha256: dc24b900742fdaf1e077d9a3458fd865711de80bca95fe3c6d46610c532c6ef0 @@ -2442,44 +2966,42 @@ packages: - pkg:pypi/jupyterlab-pygments?source=hash-mapping size: 18711 timestamp: 1733328194037 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.27.3-pyhd8ed1ab_1.conda - sha256: d03d0b7e23fa56d322993bc9786b3a43b88ccc26e58b77c756619a921ab30e86 - md5: 9dc4b2b0f41f0de41d27f3293e319357 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + sha256: 381d2d6a259a3be5f38a69463e0f6c5dcf1844ae113058007b51c3bef13a7cee + md5: a63877cb23de826b1620d3adfccc4014 depends: - babel >=2.10 - - importlib-metadata >=4.8.3 - jinja2 >=3.0.3 - json5 >=0.9.0 - jsonschema >=4.18 - jupyter_server >=1.21,<3 - packaging >=21.3 - - python >=3.9 + - python >=3.10 - requests >=2.31 - constrains: - - openapi-core >=0.18.0,<0.19.0 + - python license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jupyterlab-server?source=hash-mapping - size: 49449 - timestamp: 1733599666357 -- conda: https://conda.anaconda.org/conda-forge/noarch/jupytext-1.17.2-pyh80e38bb_0.conda - sha256: 48986a9c01f17d1d5a598af33814a877fd67a6a3287625718d76617a7d17f51d - md5: 6d0652a97ef103de0c77b9c610d0c20d + - pkg:pypi/jupyterlab-server?source=compressed-mapping + size: 51621 + timestamp: 1761145478692 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupytext-1.18.1-pyh80e38bb_0.conda + sha256: 07063dad3019455d786dc3b5174731eb0ef53eb699df25e21571c2b7cdcf0fd0 + md5: 3c85f79f1debe2d2c82ac08f1c1126e1 depends: - markdown-it-py >=1.0 - mdit-py-plugins - nbformat - packaging - - python >=3.9 + - python >=3.10 - pyyaml - tomli license: MIT license_family: MIT purls: - pkg:pypi/jupytext?source=hash-mapping - size: 108159 - timestamp: 1748846779024 + size: 111205 + timestamp: 1760888130421 - conda: https://conda.anaconda.org/conda-forge/noarch/keyring-25.6.0-pyha804496_0.conda sha256: b6f57c17cf098022c32fe64e85e9615d427a611c48a5947cdfc357490210a124 md5: cdd58ab99c214b55d56099108a914282 @@ -2524,29 +3046,42 @@ packages: purls: [] size: 1370023 timestamp: 1719463201255 -- conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.2.2-pyhd8ed1ab_1.conda - sha256: 637a9c32e15a4333f1f9c91e0a506dbab4a6dab7ee83e126951159c916c81c99 - md5: 3a8063b25e603999188ed4bbf3485404 +- conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + sha256: 49570840fb15f5df5d4b4464db8ee43a6d643031a2bc70ef52120a52e3809699 + md5: 9b965c999135d43a3d0f7bd7d024e26a depends: - - python >=3.9 + - python >=3.10 license: MIT license_family: MIT purls: - - pkg:pypi/lark?source=hash-mapping - size: 92093 - timestamp: 1734709450256 -- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1423503_1.conda - sha256: 1a620f27d79217c1295049ba214c2f80372062fd251b569e9873d4a953d27554 - md5: 0be7c6e070c19105f966d3758448d018 + - pkg:pypi/lark?source=compressed-mapping + size: 94312 + timestamp: 1761596921009 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lazy-object-proxy-1.12.0-py312h4c3975b_1.conda + sha256: b00991414f2bb05c7d959e1c76554f6e9077c149d094cbbf204a42960d37c749 + md5: 2c5f5418b4611a2e7376b37a17ac6b45 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-2-Clause + purls: + - pkg:pypi/lazy-object-proxy?source=hash-mapping + size: 40599 + timestamp: 1762506759868 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1aa0949_5.conda + sha256: dab1fbf65abb05d3f2ee49dff90d60eeb2e02039fcb561343c7cea5dea523585 + md5: 511ed8935448c1875776b60ad3daf3a1 depends: - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 constrains: - binutils_impl_linux-64 2.44 license: GPL-3.0-only - license_family: GPL purls: [] - size: 676044 - timestamp: 1752032747103 + size: 741516 + timestamp: 1762674665675 - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 md5: c277e0a4d549b03ac1e9d6cbbe3d017b @@ -2573,67 +3108,67 @@ packages: purls: [] size: 74811 timestamp: 1752719572741 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda - sha256: 764432d32db45466e87f10621db5b74363a9f847d2b8b1f9743746cd160f06ab - md5: ede4673863426c0883c0063d853bbd85 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda + sha256: 25cbdfa65580cfab1b8d15ee90b4c9f1e0d72128f1661449c9a999d341377d54 + md5: 35f29eec58405aaf55e01cb470d8c26a depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 license: MIT license_family: MIT purls: [] - size: 57433 - timestamp: 1743434498161 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.1.0-h767d61c_4.conda - sha256: 144e35c1c2840f2dc202f6915fc41879c19eddbb8fa524e3ca4aa0d14018b26f - md5: f406dcbb2e7bef90d793e50e79a2882b + size: 57821 + timestamp: 1760295480630 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda + sha256: 08f9b87578ab981c7713e4e6a7d935e40766e10691732bba376d4964562bcb45 + md5: c0374badb3a5d4b1372db28d19462c53 depends: - __glibc >=2.17,<3.0.a0 - _openmp_mutex >=4.5 constrains: - - libgcc-ng ==15.1.0=*_4 - - libgomp 15.1.0 h767d61c_4 + - libgomp 15.2.0 h767d61c_7 + - libgcc-ng ==15.2.0=*_7 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 824153 - timestamp: 1753903866511 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_4.conda - sha256: 76ceac93ed98f208363d6e9c75011b0ff7b97b20f003f06461a619557e726637 - md5: 28771437ffcd9f3417c66012dc49a3be + size: 822552 + timestamp: 1759968052178 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_7.conda + sha256: 2045066dd8e6e58aaf5ae2b722fb6dfdbb57c862b5f34ac7bfb58c40ef39b6ad + md5: 280ea6eee9e2ddefde25ff799c4f0363 depends: - - libgcc 15.1.0 h767d61c_4 + - libgcc 15.2.0 h767d61c_7 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 29249 - timestamp: 1753903872571 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.84.3-hf39c6af_0.conda - sha256: e1ad3d9ddaa18f95ff5d244587fd1a37aca6401707f85a37f7d9b5002fcf16d0 - md5: 467f23819b1ea2b89c3fc94d65082301 + size: 29313 + timestamp: 1759968065504 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.1-h32235b2_2.conda + sha256: fc82277d0d6340743732c48dcbac3f4e9ee36902649a7d9a02622b0713ce3666 + md5: 986dcf488a1aced411da84753d93d078 depends: - __glibc >=2.17,<3.0.a0 - - libffi >=3.4.6,<3.5.0a0 + - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 - libiconv >=1.18,<2.0a0 - libzlib >=1.3.1,<2.0a0 - - pcre2 >=10.45,<10.46.0a0 + - pcre2 >=10.46,<10.47.0a0 constrains: - - glib 2.84.3 *_0 + - glib 2.86.1 *_2 license: LGPL-2.1-or-later purls: [] - size: 3961899 - timestamp: 1754315006443 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.1.0-h767d61c_4.conda - sha256: e0487a8fec78802ac04da0ac1139c3510992bc58a58cde66619dde3b363c2933 - md5: 3baf8976c96134738bba224e9ef6b1e5 + size: 3933707 + timestamp: 1762787455198 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda + sha256: e9fb1c258c8e66ee278397b5822692527c5f5786d372fe7a869b900853f3f5ca + md5: f7b4d76975aac7e5d9e6ad13845f92fe depends: - __glibc >=2.17,<3.0.a0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 447289 - timestamp: 1753903801049 + size: 447919 + timestamp: 1759967942498 - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f md5: 915f5995e94f60e9a4826e0b0920ee88 @@ -2687,48 +3222,63 @@ packages: purls: [] size: 205978 timestamp: 1716828628198 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda - sha256: 6d9c32fc369af5a84875725f7ddfbfc2ace795c28f246dc70055a79f9b2003da - md5: 0b367fad34931cb79e0d6b7e5c06bb1c +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.0-hee844dc_0.conda + sha256: 4c992dcd0e34b68f843e75406f7f303b1b97c248d18f3c7c330bdc0bc26ae0b3 + md5: 729a572a3ebb8c43933b30edcc628ceb depends: - __glibc >=2.17,<3.0.a0 + - icu >=75.1,<76.0a0 - libgcc >=14 - libzlib >=1.3.1,<2.0a0 license: blessing purls: [] - size: 932581 - timestamp: 1753948484112 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_4.conda - sha256: b5b239e5fca53ff90669af1686c86282c970dd8204ebf477cf679872eb6d48ac - md5: 3c376af8888c386b9d3d1c2701e2f3ab + size: 945576 + timestamp: 1762299687230 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda + sha256: 1b981647d9775e1cdeb2fab0a4dd9cd75a6b0de2963f6c3953dbd712f78334b3 + md5: 5b767048b1b3ee9a954b06f4084f93dc depends: - __glibc >=2.17,<3.0.a0 - - libgcc 15.1.0 h767d61c_4 + - libgcc 15.2.0 h767d61c_7 + constrains: + - libstdcxx-ng ==15.2.0=*_7 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 3903453 - timestamp: 1753903894186 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_4.conda - sha256: 81c841c1cf4c0d06414aaa38a249f9fdd390554943065c3a0b18a9fb7e8cc495 - md5: 2d34729cbc1da0ec988e57b13b712067 + size: 3898269 + timestamp: 1759968103436 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-h4852527_7.conda + sha256: 024fd46ac3ea8032a5ec3ea7b91c4c235701a8bf0e6520fe5e6539992a6bd05f + md5: f627678cf829bd70bccf141a19c3ad3e depends: - - libstdcxx 15.1.0 h8f9b012_4 + - libstdcxx 15.2.0 h8f9b012_7 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 29317 - timestamp: 1753903924491 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda - sha256: 787eb542f055a2b3de553614b25f09eefb0a0931b0c87dbcce6efdfd92f04f18 - md5: 40b61aab5c7ba9ff276c41cfffe6b80b + size: 29343 + timestamp: 1759968157195 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda + sha256: e5ec6d2ad7eef538ddcb9ea62ad4346fde70a4736342c4ad87bd713641eb9808 + md5: 80c07c68d2f6870250959dcc95b209d1 depends: - - libgcc-ng >=12 + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 license: BSD-3-Clause license_family: BSD purls: [] - size: 33601 - timestamp: 1680112270483 + size: 37135 + timestamp: 1758626800002 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda + sha256: c180f4124a889ac343fc59d15558e93667d894a966ec6fdb61da1604481be26b + md5: 0f03292cc56bf91a077a134ea8747118 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 895108 + timestamp: 1753948278280 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa md5: 92ed62436b625154323d40d5f2f11dd7 @@ -2805,12 +3355,11 @@ packages: - pkg:pypi/litellm?source=hash-mapping size: 6394494 timestamp: 1751152584221 -- pypi: https://files.pythonhosted.org/packages/96/2b/34cc11786bc00d0f04d0f5fdc3a2b1ae0b6239eef72d3d345805f9ad92a1/markdown-3.8.2-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl name: markdown - version: 3.8.2 - sha256: 5c83764dbd4e00bdd94d85a19b8d55ccca20fe35b2e678a1422b380324dd5f24 + version: '3.10' + sha256: b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c requires_dist: - - importlib-metadata>=4.4 ; python_full_version < '3.10' - coverage ; extra == 'testing' - pyyaml ; extra == 'testing' - mkdocs>=1.6 ; extra == 'docs' @@ -2820,7 +3369,40 @@ packages: - mkdocs-gen-files ; extra == 'docs' - mkdocs-section-index ; extra == 'docs' - mkdocs-literate-nav ; extra == 'docs' - requires_python: '>=3.9' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + name: markdown-it-py + version: 4.0.0 + sha256: 87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147 + requires_dist: + - mdurl~=0.1 + - psutil ; extra == 'benchmarking' + - pytest ; extra == 'benchmarking' + - pytest-benchmark ; extra == 'benchmarking' + - commonmark~=0.9 ; extra == 'compare' + - markdown~=3.4 ; extra == 'compare' + - mistletoe~=1.0 ; extra == 'compare' + - mistune~=3.0 ; extra == 'compare' + - panflute~=2.3 ; extra == 'compare' + - markdown-it-pyrs ; extra == 'compare' + - linkify-it-py>=1,<3 ; extra == 'linkify' + - mdit-py-plugins>=0.5.0 ; extra == 'plugins' + - gprof2dot ; extra == 'profiling' + - mdit-py-plugins>=0.5.0 ; extra == 'rtd' + - myst-parser ; extra == 'rtd' + - pyyaml ; extra == 'rtd' + - sphinx ; extra == 'rtd' + - sphinx-copybutton ; extra == 'rtd' + - sphinx-design ; extra == 'rtd' + - sphinx-book-theme~=1.0 ; extra == 'rtd' + - jupyter-sphinx ; extra == 'rtd' + - ipykernel ; extra == 'rtd' + - coverage ; extra == 'testing' + - pytest ; extra == 'testing' + - pytest-cov ; extra == 'testing' + - pytest-regressions ; extra == 'testing' + - requests ; extra == 'testing' + requires_python: '>=3.10' - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda sha256: 7b1da4b5c40385791dbc3cc85ceea9fad5da680a27d5d3cb8bfaa185e304a89e md5: 5b5203189eb668f042ac2b0826244964 @@ -2830,15 +3412,29 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/markdown-it-py?source=compressed-mapping + - pkg:pypi/markdown-it-py?source=hash-mapping size: 64736 timestamp: 1754951288511 -- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.2-py312h178313f_1.conda - sha256: 4a6bf68d2a2b669fecc9a4a009abd1cf8e72c2289522ff00d81b5a6e51ae78f5 - md5: eb227c3e0bf58f5bd69c0532b157975b +- pypi: https://files.pythonhosted.org/packages/73/de/65dfc670e50c9db92b750db1d7c87292b8f3ba9be2c1154594d1a7d1afb4/marko-2.2.1-py3-none-any.whl + name: marko + version: 2.2.1 + sha256: 31e9a18b35c113e506ace5594716fa3df2872f8955908e279bc551f3eb1f0db8 + requires_dist: + - python-slugify ; extra == 'toc' + - pygments ; extra == 'codehilite' + - objprint ; extra == 'repr' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: markupsafe + version: 3.0.3 + sha256: ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_0.conda + sha256: f77f9f1a4da45cbc8792d16b41b6f169f649651a68afdc10b2da9da12b9aa42b + md5: f775a43412f7f3d7ed218113ad233869 depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 constrains: @@ -2847,14 +3443,14 @@ packages: license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping - size: 24604 - timestamp: 1733219911494 -- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.2-py313h8060acc_1.conda - sha256: d812caf52efcea7c9fd0eafb21d45dadfd0516812f667b928bee50e87634fae5 - md5: 21b62c55924f01b6eef6827167b46acb + size: 25321 + timestamp: 1759055268795 +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py313h3dea7bd_0.conda + sha256: a530a411bdaaf0b1e4de8869dfaca46cb07407bc7dc0702a9e231b0e5ce7ca85 + md5: c14389156310b8ed3520d84f854be1ee depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 constrains: @@ -2863,27 +3459,32 @@ packages: license_family: BSD purls: - pkg:pypi/markupsafe?source=hash-mapping - size: 24856 - timestamp: 1733219782830 -- pypi: https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl + size: 25909 + timestamp: 1759055357045 +- pypi: https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl name: matplotlib-inline - version: 0.1.7 - sha256: df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca + version: 0.2.1 + sha256: d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76 requires_dist: - traitlets - requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.1.7-pyhd8ed1ab_1.conda - sha256: 69b7dc7131703d3d60da9b0faa6dd8acbf6f6c396224cf6aef3e855b8c0c41c6 - md5: af6ab708897df59bd6e7283ceab1b56b + - flake8 ; extra == 'test' + - nbdime ; extra == 'test' + - nbval ; extra == 'test' + - notebook ; extra == 'test' + - pytest ; extra == 'test' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + sha256: 9d690334de0cd1d22c51bc28420663f4277cfa60d34fa5cad1ce284a13f1d603 + md5: 00e120ce3e40bad7bfc78861ce3c4a25 depends: - - python >=3.9 + - python >=3.10 - traitlets license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/matplotlib-inline?source=hash-mapping - size: 14467 - timestamp: 1733417051523 + - pkg:pypi/matplotlib-inline?source=compressed-mapping + size: 15175 + timestamp: 1761214578417 - conda: https://conda.anaconda.org/conda-forge/noarch/mcp-1.12.4-pyhd8ed1ab_0.conda sha256: 092020382b8d97b5451821af59247e71021761ff05566d3b4d7283c68bd8ca91 md5: 54f2625826d6241d8beee9407644a676 @@ -2923,6 +3524,11 @@ packages: - pkg:pypi/mdit-py-plugins?source=hash-mapping size: 43805 timestamp: 1754946862113 +- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + name: mdurl + version: 0.1.2 + sha256: 84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 + requires_python: '>=3.7' - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 md5: 592132998493b3ff25fd7479396e8351 @@ -2934,30 +3540,35 @@ packages: - pkg:pypi/mdurl?source=hash-mapping size: 14465 timestamp: 1733255681319 -- conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.1.3-pyh29332c3_0.conda - sha256: a67484d7dd11e815a81786580f18b6e4aa2392f292f29183631a6eccc8dc37b3 - md5: 7ec6576e328bc128f4982cd646eeba85 +- conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.1.4-pyhcf101f3_0.conda + sha256: 609ea628ace5c6cdbdce772704e6cb159ead26969bb2f386ca1757632b0f74c6 + md5: f5a4d548d1d3bdd517260409fc21e205 depends: - - python >=3.9 + - python >=3.10 - typing_extensions - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/mistune?source=hash-mapping - size: 72749 - timestamp: 1742402716323 -- conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.7.0-pyhd8ed1ab_0.conda - sha256: d0c2253dcb1da6c235797b57d29de688dabc2e48cc49645b1cff2b52b7907428 - md5: 7c65a443d58beb0518c35b26c70e201d + size: 72996 + timestamp: 1756495311698 +- pypi: https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl + name: more-itertools + version: 10.8.0 + sha256: 52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.8.0-pyhd8ed1ab_0.conda + sha256: fabe81c8f8f3e1d0ef227fc1306526c76189b3f1175f12302c707e0972dd707c + md5: d7620a15dc400b448e1c88a981b23ddd depends: - - python >=3.9 + - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/more-itertools?source=hash-mapping - size: 61359 - timestamp: 1745349566387 + size: 65129 + timestamp: 1756855971031 - conda: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.6.3-py312h178313f_0.conda sha256: c703d148a85ffb4f11001d31b7c4c686a46ad554eeeaa02c69da59fbf0e00dbb md5: f4e246ec4ccdf73e50eefb0fa359a64e @@ -2992,20 +3603,20 @@ packages: - pkg:pypi/nbclient?source=hash-mapping size: 28045 timestamp: 1734628936013 -- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.6-hb482800_0.conda - sha256: 5480b7e05bf3079fcb7357a5a15a96c3a1649cc1371d0c468c806898a7e53088 - md5: aa90ea40c80d4bd3da35cb17ed668f22 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.6-hc388f54_1.conda + sha256: e151c45e9ad2b0368fe64f51b6c857873681df27da3c408a811e85551e129d0e + md5: 0b26dff819ba9cfb0f6ff9c8b6a53c19 depends: - - nbconvert-core ==7.16.6 pyh29332c3_0 - - nbconvert-pandoc ==7.16.6 hed9df3c_0 + - nbconvert-core ==7.16.6 pyhcf101f3_1 + - nbconvert-pandoc ==7.16.6 h7d6f222_1 license: BSD-3-Clause license_family: BSD purls: [] - size: 5241 - timestamp: 1738067871725 -- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyh29332c3_0.conda - sha256: dcccb07c5a1acb7dc8be94330e62d54754c0e9c9cb2bb6865c8e3cfe44cf5a58 - md5: d24beda1d30748afcc87c429454ece1b + size: 5259 + timestamp: 1760797634451 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyhcf101f3_1.conda + sha256: 8f575e5c042b17f4677179a6ba474bdbe76573936d3d3e2aeb42b511b9cb1f3f + md5: cfc86ccc3b1de35d36ccaae4c50391f5 depends: - beautifulsoup4 - bleach-with-css !=5.0.0 @@ -3021,29 +3632,29 @@ packages: - packaging - pandocfilters >=1.4.1 - pygments >=2.4.1 - - python >=3.9 + - python >=3.10 - traitlets >=5.1 - python constrains: - pandoc >=2.9.2,<4.0.0 - - nbconvert ==7.16.6 *_0 + - nbconvert ==7.16.6 *_1 license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/nbconvert?source=hash-mapping - size: 200601 - timestamp: 1738067871724 -- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.6-hed9df3c_0.conda - sha256: 1e8923f1557c2ddb7bba915033cfaf8b8c1b7462c745172458102c11caee1002 - md5: 5b0afb6c52e74a7eca2cf809a874acf4 + - pkg:pypi/nbconvert?source=compressed-mapping + size: 199273 + timestamp: 1760797634443 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.6-h7d6f222_1.conda + sha256: 1eaf769838863544a0f2d2fb05acba1211a764b64234b53b2da836015d661150 + md5: 32b4a67e7fde3b22287b65838c8ad01b depends: - - nbconvert-core ==7.16.6 pyh29332c3_0 + - nbconvert-core ==7.16.6 pyhcf101f3_1 - pandoc license: BSD-3-Clause license_family: BSD purls: [] - size: 5722 - timestamp: 1738067871725 + size: 5726 + timestamp: 1760797634451 - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda sha256: 7a5bd30a2e7ddd7b85031a5e2e14f290898098dc85bea5b3a5bf147c25122838 md5: bbe1963f1e47f594070ffe87cdf612ea @@ -3080,6 +3691,22 @@ packages: - pkg:pypi/nest-asyncio?source=hash-mapping size: 11543 timestamp: 1733325673691 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-22.19.0-heeeca48_0.conda + sha256: 44e2da00f569ea882ad7fc303873bd6443e25f85a41d6634b0bdbe7950690e1d + md5: a04691868ba5ff2a1977d127b0090d77 + depends: + - __glibc >=2.28,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + - icu >=75.1,<76.0a0 + - openssl >=3.5.3,<4.0a0 + - libuv >=1.51.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + purls: [] + size: 24443145 + timestamp: 1758398535072 - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda sha256: 7b920e46b9f7a2d2aa6434222e5c8d739021dbc5cc75f32d124a8191d86f9056 md5: e7f89ea5f7ea9401642758ff50a2d9c1 @@ -3092,9 +3719,9 @@ packages: - pkg:pypi/notebook-shim?source=hash-mapping size: 16817 timestamp: 1733408419340 -- conda: https://conda.anaconda.org/conda-forge/noarch/notebook_intelligence-2.3.2-pyhd8ed1ab_0.conda - sha256: a290501325a193d61be7c134f7782275abc61e1797c9de5d0b6e2449dbb7c398 - md5: a84056d32f552023a7039364d4ff2934 +- conda: https://conda.anaconda.org/conda-forge/noarch/notebook_intelligence-2.6.0-pyhd8ed1ab_0.conda + sha256: f652d1b4662bb59fc232df50412269ee9ba2769d042279d5a77ca4a1656d989a + md5: 6851832d9bfe5b727fd6ea42f1572b45 depends: - cryptography - fastmcp @@ -3111,37 +3738,36 @@ packages: - sseclient-py - tiktoken license: GPL-3.0-or-later - license_family: GPL purls: - pkg:pypi/notebook-intelligence?source=hash-mapping - size: 4042636 - timestamp: 1756186734265 -- pypi: https://files.pythonhosted.org/packages/1d/0f/571b2c7a3833ae419fe69ff7b479a78d313581785203cc70a8db90121b9a/numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + size: 4045604 + timestamp: 1762567599638 +- pypi: https://files.pythonhosted.org/packages/9e/7e/7d306ff7cb143e6d975cfa7eb98a93e73495c4deabb7d1b5ecf09ea0fd69/numpy-2.3.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl name: numpy - version: 2.3.2 - sha256: 938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f + version: 2.3.4 + sha256: fc8a63918b04b8571789688b2780ab2b4a33ab44bfe8ccea36d3eba51228c953 requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/59/ef/f96536f1df42c668cbacb727a8c6da7afc9c05ece6d558927fb1722693e1/numpy-2.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/f9/58/30a85127bfee6f108282107caf8e06a1f0cc997cb6b52cdee699276fcce4/numpy-2.3.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl name: numpy - version: 2.3.2 - sha256: 8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73 + version: 2.3.4 + sha256: 4121c5beb58a7f9e6dfdee612cb24f4df5cd4db6e8261d7f4d7450a997a65d6a requires_python: '>=3.11' -- conda: https://conda.anaconda.org/conda-forge/linux-64/ollama-0.11.7-cpu_hba3e463_0.conda - sha256: f9440a7e72dff6179db9bb808d83b6617f6f785c878bedf03cf4dfa354cee3f1 - md5: 67de87ca68f109e46f26b8f97e66e7df +- conda: https://conda.anaconda.org/conda-forge/linux-64/ollama-0.12.10-cuda_130h9684303_0.conda + sha256: 2ad520ab4eec60535881e668864b29da960883d3aad4c4c1ad861b53129d1314 + md5: e54214e31a06e63a326553d028cf74ae depends: + - cuda-version >=13.0,<14 + - __glibc >=2.28,<3.0.a0 - libstdcxx >=14 - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - __glibc >=2.17 license: MIT - license_family: MIT purls: [] - size: 11827207 - timestamp: 1756164966288 -- conda: https://conda.anaconda.org/conda-forge/noarch/ollama-python-0.5.3-pyhd8ed1ab_0.conda - sha256: 7a22c8e1a9527bc500bb5667290339d8decf586d899c7374700d8a66016c8231 - md5: d753ac78b8d083343b5f3422c5a3513e + size: 516615800 + timestamp: 1762487188766 +- conda: https://conda.anaconda.org/conda-forge/noarch/ollama-python-0.6.0-pyhd8ed1ab_0.conda + sha256: 7c01798b2f9b0e1d25cadf30cad2d3f6087e052dc8bf16b744b927d1a8995977 + md5: 0cea78ef241c20cd08b05cf07074a7a1 depends: - httpx >=0.27 - pydantic >=2.9.0 @@ -3150,8 +3776,8 @@ packages: license_family: MIT purls: - pkg:pypi/ollama?source=hash-mapping - size: 18870 - timestamp: 1754680952708 + size: 19339 + timestamp: 1758769592561 - conda: https://conda.anaconda.org/conda-forge/noarch/openai-1.99.9-pyhd8ed1ab_0.conda sha256: 99a8a346e72c8492f73bf1843ef3533aacd41dfc5546b90ac6a74914ed7a1925 md5: 63c6ba955c8f7bd6a57697b78d4fa31b @@ -3172,6 +3798,27 @@ packages: - pkg:pypi/openai?source=hash-mapping size: 310163 timestamp: 1755034335796 +- conda: https://conda.anaconda.org/conda-forge/noarch/openapi-core-0.19.5-pyh29332c3_0.conda + sha256: bce5fa89688f012339ce565cba7c94030f792cb20244d3e1e088f71b49cc2970 + md5: 1f1e2a9772ed3a9e0573dc5d479d262e + depends: + - isodate + - jsonschema >=4.18.0,<5.0.0 + - jsonschema-path >=0.3.1,<0.4.0 + - more-itertools + - openapi-schema-validator >=0.6.0,<0.7.0 + - openapi-spec-validator >=0.7.1,<0.8.0 + - parse + - python >=3.9 + - typing_extensions >=4.8.0,<5.0.0 + - werkzeug <3.1.2 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/openapi-core?source=hash-mapping + size: 111755 + timestamp: 1742503825212 - conda: https://conda.anaconda.org/conda-forge/noarch/openapi-pydantic-0.5.1-pyh3cfb1c2_0.conda sha256: 441e1f8902fae6c2ff881dd57e2f9612b361d7ca540733b62391d846af1e8c8f md5: 177fcc79ec5146bbbf6d6e15ea231013 @@ -3184,6 +3831,37 @@ packages: - pkg:pypi/openapi-pydantic?source=hash-mapping size: 47050 timestamp: 1736451905669 +- conda: https://conda.anaconda.org/conda-forge/noarch/openapi-schema-validator-0.6.3-pyhd8ed1ab_0.conda + sha256: 586d9cbb78825a5b1bbff76358dddead8595ddb10362397d64c0b9f04fd25356 + md5: d99b3bb08a0d8c7116e15469ee0bed86 + depends: + - jsonschema >=4.19.1,<5.0.0a0 + - jsonschema-specifications >=2023.5.2 + - python >=3.9 + - rfc3339-validator + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/openapi-schema-validator?source=hash-mapping + size: 17588 + timestamp: 1736695233725 +- conda: https://conda.anaconda.org/conda-forge/noarch/openapi-spec-validator-0.7.2-pyhe01879c_0.conda + sha256: 6a11dd75d24197f9fef0b51cb8918213c091d2dbda7f3abfafbbff2b35cf933e + md5: 2541181696d89a4225d7e39bd5e8c200 + depends: + - importlib_resources >=5.8,<7.0 + - jsonschema >=4.18.0,<5.0.0 + - jsonschema-path >=0.3.1,<0.4.0 + - lazy-object-proxy >=1.7.1,<2.0.0 + - openapi-schema-validator >=0.6.0,<0.7.0 + - python >=3.9 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/openapi-spec-validator?source=hash-mapping + size: 49597 + timestamp: 1749392782112 - pypi: https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl name: openpyxl version: 3.1.5 @@ -3191,9 +3869,9 @@ packages: requires_dist: - et-xmlfile requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.2-h26f9b46_0.conda - sha256: c9f54d4e8212f313be7b02eb962d0cb13a8dae015683a403d3accd4add3e520e - md5: ffffb341206dd0dab0c36053c048d621 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda + sha256: a47271202f4518a484956968335b2521409c8173e123ab381e775c358c67fe6d + md5: 9ee58d5c534af06558933af3c845a780 depends: - __glibc >=2.17,<3.0.a0 - ca-certificates @@ -3201,8 +3879,24 @@ packages: license: Apache-2.0 license_family: Apache purls: [] - size: 3128847 - timestamp: 1754465526100 + size: 3165399 + timestamp: 1762839186699 +- pypi: https://files.pythonhosted.org/packages/12/27/fb8d7338b4d551900fa3e580acbe7a0cf655d940e164cb5c00ec31961094/orderly_set-5.5.0-py3-none-any.whl + name: orderly-set + version: 5.5.0 + sha256: 46f0b801948e98f427b412fcabb831677194c05c3b699b80de260374baa0b1e7 + requires_dist: + - coverage~=7.6.0 ; extra == 'coverage' + - bump2version~=1.0.0 ; extra == 'dev' + - ipdb~=0.13.0 ; extra == 'dev' + - orjson ; extra == 'optimize' + - flake8~=7.1.0 ; extra == 'static' + - flake8-pyproject~=1.2.3 ; extra == 'static' + - pytest~=8.3.0 ; extra == 'test' + - pytest-benchmark~=5.1.0 ; extra == 'test' + - pytest-cov~=6.0.0 ; extra == 'test' + - python-dotenv~=1.0.0 ; extra == 'test' + requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda sha256: 1840bd90d25d4930d60f57b4f38d4e0ae3f5b8db2819638709c36098c6ba770c md5: e51f1e4089cad105b6cac64bd8166587 @@ -3215,6 +3909,11 @@ packages: - pkg:pypi/overrides?source=hash-mapping size: 30139 timestamp: 1734587755455 +- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl + name: packaging + version: '25.0' + sha256: 29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 + requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda sha256: 289861ed0c13a15d7bbb408796af4de72c2fe67e2bcb0de98f4c3fce259d7991 md5: 58335b26c38bf4a20f399384c33cbcf9 @@ -3227,10 +3926,15 @@ packages: - pkg:pypi/packaging?source=hash-mapping size: 62477 timestamp: 1745345660407 -- pypi: https://files.pythonhosted.org/packages/8f/52/0634adaace9be2d8cac9ef78f05c47f3a675882e068438b9d7ec7ef0c13f/pandas-2.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/cf/f7/3367feadd4ab56783b0971c9b7edfbdd68e0c70ce877949a5dd2117ed4a0/palettable-3.3.3-py2.py3-none-any.whl + name: palettable + version: 3.3.3 + sha256: 74e9e7d7fe5a9be065e02397558ed1777b2df0b793a6f4ce1a5ee74f74fb0caa + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl name: pandas - version: 2.3.2 - sha256: 4ac8c320bded4718b298281339c1a50fb00a6ba78cb2a63521c39bec95b0209b + version: 2.3.3 + sha256: 318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac requires_dist: - numpy>=1.22.4 ; python_full_version < '3.11' - numpy>=1.23.2 ; python_full_version == '3.11.*' @@ -3318,10 +4022,10 @@ packages: - xlsxwriter>=3.0.5 ; extra == 'all' - zstandard>=0.19.0 ; extra == 'all' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/d3/a4/f7edcfa47e0a88cda0be8b068a5bae710bf264f867edfdf7b71584ace362/pandas-2.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/e5/63/cd7d615331b328e287d8233ba9fdf191a9c2d11b6af0c7a59cfcec23de68/pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl name: pandas - version: 2.3.2 - sha256: 96d31a6b4354e3b9b8a2c848af75d31da390657e3ac6f30c05c82068b9ed79b9 + version: 2.3.3 + sha256: b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89 requires_dist: - numpy>=1.22.4 ; python_full_version < '3.11' - numpy>=1.23.2 ; python_full_version == '3.11.*' @@ -3428,6 +4132,17 @@ packages: - pkg:pypi/pandocfilters?source=hash-mapping size: 11627 timestamp: 1631603397334 +- conda: https://conda.anaconda.org/conda-forge/noarch/parse-1.20.2-pyhd8ed1ab_1.conda + sha256: 3196db12a2f29586a2f7bbae9422ffb1d91ea483b9d52904897f86f73a8fba29 + md5: 880b839b4d809c5be9da9b27a77eba37 + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/parse?source=hash-mapping + size: 23771 + timestamp: 1733259910335 - pypi: https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl name: parso version: 0.8.5 @@ -3451,6 +4166,22 @@ packages: - pkg:pypi/parso?source=hash-mapping size: 81562 timestamp: 1755974222274 +- conda: https://conda.anaconda.org/conda-forge/noarch/pathable-0.4.4-pyhd8ed1ab_0.conda + sha256: d1ab9496d20fd68e1a853f6a8e0f63c79626e00badf75af8a9a8dcd379302e23 + md5: 7177a7cde05e5b0b3635e13f07b13733 + depends: + - python >=3.9 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/pathable?source=hash-mapping + size: 17124 + timestamp: 1736621777997 +- pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + name: pathspec + version: 0.12.1 + sha256: a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 + requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_1.conda sha256: 9f64009cdf5b8e529995f18e03665b03f5d07c0b17445b8badef45bde76249ee md5: 617f15191456cc6a13db418a275435e5 @@ -3462,19 +4193,44 @@ packages: - pkg:pypi/pathspec?source=hash-mapping size: 41075 timestamp: 1733233471940 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.45-hc749103_0.conda - sha256: 27c4014f616326240dcce17b5f3baca3953b6bc5f245ceb49c3fa1e6320571eb - md5: b90bece58b4c2bf25969b70f3be42d25 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.46-h1321c63_0.conda + sha256: 5c7380c8fd3ad5fc0f8039069a45586aa452cf165264bc5a437ad80397b32934 + md5: 7fa07cb0fb1b625a089ccc01218ee5b1 depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 - - libgcc >=13 + - libgcc >=14 - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD purls: [] - size: 1197308 - timestamp: 1745955064657 + size: 1209177 + timestamp: 1756742976157 +- pypi: https://files.pythonhosted.org/packages/9f/5c/ea831abc18dd3268046d7d9a0119f1f8ddc69642e0a5245f839602b8114d/petl-1.7.17-py3-none-any.whl + name: petl + version: 1.7.17 + sha256: 53785128bcdf46eb4472638ad572acc6d87cc83f80b567fed06ee4a947eea5d1 + requires_dist: + - fastavro>=0.24.0 ; extra == 'avro' + - bcolz>=1.2.1 ; extra == 'bcolz' + - sqlalchemy>=1.3.6,<2.0 ; extra == 'db' + - cython>=0.29.13 ; extra == 'hdf5' + - numpy>=1.16.4 ; extra == 'hdf5' + - numexpr>=2.6.9 ; extra == 'hdf5' + - tables>=3.5.2 ; extra == 'hdf5' + - aiohttp>=3.6.2 ; extra == 'http' + - requests ; extra == 'http' + - intervaltree>=3.0.2 ; extra == 'interval' + - numpy>=1.16.4 ; extra == 'numpy' + - pandas>=0.24.2 ; extra == 'pandas' + - fsspec>=0.7.4 ; extra == 'remote' + - smbprotocol>=1.0.1 ; extra == 'smb' + - xlrd>=2.0.1 ; extra == 'xls' + - xlwt>=1.3.0 ; extra == 'xls' + - openpyxl>=2.6.2 ; extra == 'xlsx' + - lxml>=4.4.0 ; extra == 'xpath' + - whoosh ; extra == 'whoosh' + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' - pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl name: pexpect version: 4.9.0 @@ -3492,28 +4248,34 @@ packages: - pkg:pypi/pexpect?source=hash-mapping size: 53561 timestamp: 1733302019362 -- conda: https://conda.anaconda.org/conda-forge/noarch/pickleshare-0.7.5-pyhd8ed1ab_1004.conda - sha256: e2ac3d66c367dada209fc6da43e645672364b9fd5f9d28b9f016e24b81af475b - md5: 11a9d1d09a3615fc07c3faf79bc0b943 - depends: - - python >=3.9 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pickleshare?source=hash-mapping - size: 11748 - timestamp: 1733327448200 -- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.4.0-pyhcf101f3_0.conda - sha256: dfe0fa6e351d2b0cef95ac1a1533d4f960d3992f9e0f82aeb5ec3623a699896b - md5: cc9d9a3929503785403dbfad9f707145 +- pypi: https://files.pythonhosted.org/packages/73/cb/ac7874b3e5d58441674fb70742e6c374b28b0c7cb988d37d991cde47166c/platformdirs-4.5.0-py3-none-any.whl + name: platformdirs + version: 4.5.0 + sha256: e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3 + requires_dist: + - furo>=2025.9.25 ; extra == 'docs' + - proselint>=0.14 ; extra == 'docs' + - sphinx-autodoc-typehints>=3.2 ; extra == 'docs' + - sphinx>=8.2.3 ; extra == 'docs' + - appdirs==1.4.4 ; extra == 'test' + - covdefaults>=2.3 ; extra == 'test' + - pytest-cov>=7 ; extra == 'test' + - pytest-mock>=3.15.1 ; extra == 'test' + - pytest>=8.4.2 ; extra == 'test' + - mypy>=1.18.2 ; extra == 'type' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.0-pyhcf101f3_0.conda + sha256: 7efd51b48d908de2d75cbb3c4a2e80dd9454e1c5bb8191b261af3136f7fa5888 + md5: 5c7a868f8241e64e1cf5fdf4962f23e2 depends: - python >=3.10 - python license: MIT + license_family: MIT purls: - - pkg:pypi/platformdirs?source=compressed-mapping - size: 23653 - timestamp: 1756227402815 + - pkg:pypi/platformdirs?source=hash-mapping + size: 23625 + timestamp: 1759953252315 - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda sha256: a8eb555eef5063bbb7ba06a379fa7ea714f57d9741fe0efdb9442dbbc2cccbcc md5: 7da7ccd349dbf6487a7778579d2bb971 @@ -3525,17 +4287,17 @@ packages: - pkg:pypi/pluggy?source=hash-mapping size: 24246 timestamp: 1747339794916 -- conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.22.1-pyhd8ed1ab_0.conda - sha256: 454e2c0ef14accc888dd2cd2e8adb8c6a3a607d2d3c2f93962698b5718e6176d - md5: c64b77ccab10b822722904d889fa83b5 +- conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.23.1-pyhd8ed1ab_0.conda + sha256: 13dc67de68db151ff909f2c1d2486fa7e2d51355b25cee08d26ede1b62d48d40 + md5: a1e91db2d17fd258c64921cb38e6745a depends: - - python >=3.9 + - python >=3.10 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/prometheus-client?source=hash-mapping - size: 52641 - timestamp: 1748896836631 + size: 54592 + timestamp: 1758278323953 - pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl name: prompt-toolkit version: 3.0.52 @@ -3552,6 +4314,7 @@ packages: constrains: - prompt_toolkit 3.0.52 license: BSD-3-Clause + license_family: BSD purls: - pkg:pypi/prompt-toolkit?source=hash-mapping size: 273927 @@ -3570,34 +4333,34 @@ packages: - pkg:pypi/propcache?source=hash-mapping size: 54233 timestamp: 1744525107433 -- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.0.0-py312h4c3975b_1.conda - sha256: 87fa638e19db9c9c5a1e9169d12a4b90ea32c72b47e8da328b36d233ba72cc79 - md5: ebc6080d32b9608710a0d651e581d9f4 +- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.1.3-py312h5253ce2_0.conda + sha256: 1b679202ebccf47be64509a4fc2a438a66229403257630621651b2886b882597 + md5: 82ce56c5a4a55165aed95e04923ab363 depends: - - __glibc >=2.17,<3.0.a0 + - python - libgcc >=14 - - python >=3.12,<3.13.0a0 + - __glibc >=2.17,<3.0.a0 - python_abi 3.12.* *_cp312 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=hash-mapping - size: 467818 - timestamp: 1755851390449 -- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.0.0-py313h07c4f96_1.conda - sha256: 9182273778a10b2a82343c5c1c8b57f4551dd07d9a639585d468f4a7fe5ff1e8 - md5: 5a7c24c9dc49128731ae565cf598cde4 + size: 495011 + timestamp: 1762092914381 +- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.1.3-py313h54dd161_0.conda + sha256: 26cf5a69d04ef66f03516b8a8211a43bb23d5225faacd7d36e5c987b0d66af0a + md5: 1d719fc61f91ab2644a2eeb35fcab360 depends: - - __glibc >=2.17,<3.0.a0 + - python - libgcc >=14 - - python >=3.13,<3.14.0a0 + - __glibc >=2.17,<3.0.a0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=hash-mapping - size: 474571 - timestamp: 1755851494108 + size: 501735 + timestamp: 1762092897061 - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 md5: b3c17d95b5a10c6e64a21fa17573e70e @@ -3649,6 +4412,16 @@ packages: - pytest ; extra == 'testing' - flake8 ; extra == 'testing' requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/13/95/aec81f781c75cd10554dc17a25849c720d54feafb6f7847690478dcf5ef8/pyarrow-22.0.0-cp312-cp312-manylinux_2_28_x86_64.whl + name: pyarrow + version: 22.0.0 + sha256: c6c791b09c57ed76a18b03f2631753a4960eefbbca80f846da8baefc6491fcfe + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/1b/8b/5362443737a5307a7b67c1017c42cd104213189b4970bf607e05faf9c525/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_x86_64.whl + name: pyarrow + version: 22.0.0 + sha256: e0a15757fccb38c410947df156f9749ae4a3c89b2393741a50521f39a8cf202a + requires_python: '>=3.10' - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda sha256: 79db7928d13fab2d892592223d7570f5061c192f27b9febd1a418427b719acc6 md5: 12c566707c80111f9799308d9e265aef @@ -3661,65 +4434,65 @@ packages: - pkg:pypi/pycparser?source=hash-mapping size: 110100 timestamp: 1733195786147 -- pypi: https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl name: pydantic - version: 2.11.7 - sha256: dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b + version: 2.12.4 + sha256: 92d3d202a745d46f9be6df459ac5a064fdaa3c1c4cd8adcfa332ccf3c05f871e requires_dist: - annotated-types>=0.6.0 - - pydantic-core==2.33.2 - - typing-extensions>=4.12.2 - - typing-inspection>=0.4.0 + - pydantic-core==2.41.5 + - typing-extensions>=4.14.1 + - typing-inspection>=0.4.2 - email-validator>=2.0.0 ; extra == 'email' - tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone' requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.11.7-pyh3cfb1c2_0.conda - sha256: ee7823e8bc227f804307169870905ce062531d36c1dcf3d431acd65c6e0bd674 - md5: 1b337e3d378cde62889bb735c024b7a2 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.4-pyh3cfb1c2_0.conda + sha256: c51297f0f6ef13776cc5b61c37d00c0d45faaed34f81d196e64bebc989f3e497 + md5: bf6ce72315b6759453d8c90a894e9e4c depends: - annotated-types >=0.6.0 - - pydantic-core 2.33.2 - - python >=3.9 + - pydantic-core 2.41.5 + - python >=3.10 - typing-extensions >=4.6.1 - - typing-inspection >=0.4.0 - - typing_extensions >=4.12.2 + - typing-inspection >=0.4.2 + - typing_extensions >=4.14.1 license: MIT license_family: MIT purls: - pkg:pypi/pydantic?source=hash-mapping - size: 307333 - timestamp: 1749927245525 -- pypi: https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + size: 320446 + timestamp: 1762379584494 +- pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: pydantic-core - version: 2.33.2 - sha256: 9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d + version: 2.41.5 + sha256: 406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586 requires_dist: - - typing-extensions>=4.6.0,!=4.7.0 + - typing-extensions>=4.14.1 requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.33.2-py312h680f630_0.conda - sha256: 4d14d7634c8f351ff1e63d733f6bb15cba9a0ec77e468b0de9102014a4ddc103 - md5: cfbd96e5a0182dfb4110fc42dda63e57 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py312h868fb18_1.conda + sha256: 07f899d035e06598682d3904d55f1529fac71b15e12b61d44d6a5fbf8521b0fe + md5: 56a776330a7d21db63a7c9d6c3711a04 depends: - python - typing-extensions >=4.6.0,!=4.7.0 + - libgcc >=14 - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - python_abi 3.12.* *_cp312 constrains: - __glibc >=2.17 license: MIT - license_family: MIT purls: - - pkg:pypi/pydantic-core?source=hash-mapping - size: 1890081 - timestamp: 1746625309715 -- pypi: https://files.pythonhosted.org/packages/70/1a/5f4fd9e7285f10c44095a4f9fe17d0f358d1702a7c74a9278c794e8a7537/pydantic_extra_types-2.10.5-py3-none-any.whl + - pkg:pypi/pydantic-core?source=compressed-mapping + size: 1935221 + timestamp: 1762989004359 +- pypi: https://files.pythonhosted.org/packages/93/04/5c918669096da8d1c9ec7bb716bd72e755526103a61bc5e76a3e4fb23b53/pydantic_extra_types-2.10.6-py3-none-any.whl name: pydantic-extra-types - version: 2.10.5 - sha256: b60c4e23d573a69a4f1a16dd92888ecc0ef34fb0e655b4f305530377fa70e7a8 + version: 2.10.6 + sha256: 6106c448316d30abf721b5b9fecc65e983ef2614399a24142d689c7546cc246a requires_dist: - pydantic>=2.5.2 - typing-extensions + - cron-converter>=1.2.2 ; extra == 'all' - pendulum>=3.0.0,<4.0.0 ; extra == 'all' - phonenumbers>=8,<10 ; extra == 'all' - pycountry>=23 ; extra == 'all' @@ -3730,6 +4503,7 @@ packages: - semver>=3.0.2 ; extra == 'all' - semver~=3.0.2 ; extra == 'all' - tzdata>=2024.1 ; extra == 'all' + - cron-converter>=1.2.2 ; extra == 'cron' - pendulum>=3.0.0,<4.0.0 ; extra == 'pendulum' - phonenumbers>=8,<10 ; extra == 'phonenumbers' - pycountry>=23 ; extra == 'pycountry' @@ -3737,10 +4511,10 @@ packages: - python-ulid>=1,<4 ; python_full_version >= '3.9' and extra == 'python-ulid' - semver>=3.0.2 ; extra == 'semver' requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl name: pydantic-settings - version: 2.10.1 - sha256: a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796 + version: 2.12.0 + sha256: fddb9fd99a5b18da837b29710391e945b1e30c135477f484084ee513adb93809 requires_dist: - pydantic>=2.7.0 - python-dotenv>=0.21.0 @@ -3752,21 +4526,20 @@ packages: - google-cloud-secret-manager>=2.23.1 ; extra == 'gcp-secret-manager' - tomli>=2.0.1 ; extra == 'toml' - pyyaml>=6.0.1 ; extra == 'yaml' - requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-settings-2.10.1-pyh3cfb1c2_0.conda - sha256: e56b9a0320e3cab58b88f62ccdcd4bf7cd89ec348c878e1843d4d22315bfced1 - md5: a5f9c3e867917c62d796c20dba792cbd + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-settings-2.12.0-pyh3cfb1c2_0.conda + sha256: 17d552dd19501909d626ff50cd23753d56e03ab670ce9096f1c4068e1eb90f2a + md5: 0a3042ce18b785982c64a8567cc3e512 depends: - pydantic >=2.7.0 - - python >=3.9 + - python >=3.10 - python-dotenv >=0.21.0 - typing-inspection >=0.4.0 license: MIT - license_family: MIT purls: - pkg:pypi/pydantic-settings?source=hash-mapping - size: 38816 - timestamp: 1750801673349 + size: 43752 + timestamp: 1762786342653 - pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl name: pygments version: 2.19.2 @@ -3785,20 +4558,20 @@ packages: - pkg:pypi/pygments?source=hash-mapping size: 889287 timestamp: 1750615908735 -- conda: https://conda.anaconda.org/conda-forge/noarch/pyperclip-1.9.0-pyha804496_3.conda - sha256: 3c5ad439174e1644817f673501062862b0e5e396e4ce45fbc368007fbbff8f67 - md5: e901f0e3e1ee1262e20f9b65e1419696 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyperclip-1.11.0-pyha804496_0.conda + sha256: 977fa57882322d2ed29ad54bc0084d79c27fde57f150be39923f2c0824fc3205 + md5: 2054f5088a57280a8ea79df3d5341728 depends: - __linux - - python >=3.9 + - python >=3.10 - xclip - xsel license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/pyperclip?source=hash-mapping - size: 16430 - timestamp: 1733932714090 + size: 16983 + timestamp: 1758906797105 - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 md5: 461219d1a5bd61342293efa2c0c90eac @@ -3811,26 +4584,26 @@ packages: - pkg:pypi/pysocks?source=hash-mapping size: 21085 timestamp: 1733217331982 -- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.1-pyhd8ed1ab_0.conda - sha256: 93e267e4ec35353e81df707938a6527d5eb55c97bf54c3b87229b69523afb59d - md5: a49c2283f24696a7b30367b7346a0144 +- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.0.0-pyhcf101f3_0.conda + sha256: afd413cd919bd3cca1d45062b9822be8935e1f61ce6d6b2642364e8c19e2873d + md5: 499e8e2df95ad3d263bee8d41cc3d475 depends: - - colorama >=0.4 - - exceptiongroup >=1 - - iniconfig >=1 - - packaging >=20 - - pluggy >=1.5,<2 - pygments >=2.7.2 - - python >=3.9 + - python >=3.10 + - iniconfig >=1.0.1 + - packaging >=22 + - pluggy >=1.5,<2 - tomli >=1 + - colorama >=0.4 + - exceptiongroup >=1 + - python constrains: - pytest-faulthandler >=2 license: MIT - license_family: MIT purls: - pkg:pypi/pytest?source=hash-mapping - size: 276562 - timestamp: 1750239526127 + size: 298822 + timestamp: 1762632428892 - pypi: https://files.pythonhosted.org/packages/09/52/7bbfb6e987d9a8a945f22941a8da63e3529465f1b106ef0e26f5df7c780d/pytest_examples-0.0.18-py3-none-any.whl name: pytest-examples version: 0.0.18 @@ -3840,24 +4613,25 @@ packages: - pytest>=7 - ruff>=0.5.0 requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.11-h9e4cc4f_0_cpython.conda - sha256: 6cca004806ceceea9585d4d655059e951152fc774a471593d4f5138e6a54c81d - md5: 94206474a5608243a10c92cefbe0908f +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.12-hd63d673_1_cpython.conda + build_number: 1 + sha256: 39898d24769a848c057ab861052e50bdc266310a7509efa3514b840e85a2ae98 + md5: 5c00c8cea14ee8d02941cab9121dce41 depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 - ld_impl_linux-64 >=2.36.1 - - libexpat >=2.7.0,<3.0a0 - - libffi >=3.4.6,<3.5.0a0 - - libgcc >=13 + - libexpat >=2.7.1,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 - liblzma >=5.8.1,<6.0a0 - libnsl >=2.0.1,<2.1.0a0 - - libsqlite >=3.50.0,<4.0a0 - - libuuid >=2.38.1,<3.0a0 + - libsqlite >=3.50.4,<4.0a0 + - libuuid >=2.41.2,<3.0a0 - libxcrypt >=4.4.36 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - - openssl >=3.5.0,<4.0a0 + - openssl >=3.5.4,<4.0a0 - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata @@ -3865,35 +4639,45 @@ packages: - python_abi 3.12.* *_cp312 license: Python-2.0 purls: [] - size: 31445023 - timestamp: 1749050216615 -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.5-hec9711d_102_cp313.conda - build_number: 102 - sha256: c2cdcc98ea3cbf78240624e4077e164dc9d5588eefb044b4097c3df54d24d504 - md5: 89e07d92cf50743886f41638d58c4328 + size: 31537229 + timestamp: 1761176876216 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-hc97d973_101_cp313.conda + build_number: 101 + sha256: e89da062abd0d3e76c8d3b35d3cafc5f0d05914339dcb238f9e3675f2a58d883 + md5: 4780fe896e961722d0623fa91d0d3378 depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 - ld_impl_linux-64 >=2.36.1 - - libexpat >=2.7.0,<3.0a0 - - libffi >=3.4.6,<3.5.0a0 - - libgcc >=13 + - libexpat >=2.7.1,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 - liblzma >=5.8.1,<6.0a0 - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.50.1,<4.0a0 - - libuuid >=2.38.1,<3.0a0 + - libsqlite >=3.50.4,<4.0a0 + - libuuid >=2.41.2,<3.0a0 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - - openssl >=3.5.0,<4.0a0 + - openssl >=3.5.4,<4.0a0 - python_abi 3.13.* *_cp313 - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata license: Python-2.0 purls: [] - size: 33273132 - timestamp: 1750064035176 + size: 37174029 + timestamp: 1761178179147 python_site_packages_path: lib/python3.13/site-packages +- pypi: https://files.pythonhosted.org/packages/43/4f/a5f167a95ef57c3e37fe8ae0a41745061442f44e4c0c4395d70c8740e453/python_calamine-0.5.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: python-calamine + version: 0.5.4 + sha256: f8304fc19322f05dc0af78851ca47255a088a9c0cc3874648b42038e7f27ff2f + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/98/f5/aec030f567ee14c60b6fc9028a78767687f484071cb080f7cfa328d6496e/python_calamine-0.5.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: python-calamine + version: 0.5.4 + sha256: b8f882e092ab23f72ea07e2e48f5f2efb1885c1836fb949f22fd4540ae11742e + requires_python: '>=3.10' - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl name: python-dateutil version: 2.9.0.post0 @@ -3914,25 +4698,25 @@ packages: - pkg:pypi/python-dateutil?source=hash-mapping size: 233310 timestamp: 1751104122689 -- pypi: https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl name: python-dotenv - version: 1.1.1 - sha256: 31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc + version: 1.2.1 + sha256: b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 requires_dist: - click>=5.0 ; extra == 'cli' requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.1.1-pyhe01879c_0.conda - sha256: 9a90570085bedf4c6514bcd575456652c47918ff3d7b383349e26192a4805cc8 - md5: a245b3c04afa11e2e52a0db91550da7c +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.1-pyhcf101f3_0.conda + sha256: aa98e0b1f5472161318f93224f1cfec1355ff69d2f79f896c0b9e033e4a6caf9 + md5: 083725d6cd3dc007f06d04bcf1e613a2 depends: - - python >=3.9 + - python >=3.10 - python license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/python-dotenv?source=hash-mapping - size: 26031 - timestamp: 1750789290754 + size: 26922 + timestamp: 1761503229008 - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda sha256: df9aa74e9e28e8d1309274648aac08ec447a92512c33f61a8de0afa9ce32ebe8 md5: 23029aae904a2ba587daba708208012f @@ -3945,26 +4729,26 @@ packages: - pkg:pypi/fastjsonschema?source=hash-mapping size: 244628 timestamp: 1755304154927 -- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.11-hd8ed1ab_0.conda - sha256: b8afeaefe409d61fa4b68513b25a66bb17f3ca430d67cfea51083c7bfbe098ef - md5: 859c6bec94cd74119f12b961aba965a8 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.12-hd8ed1ab_1.conda + sha256: 59f17182813f8b23709b7d4cfda82c33b72dd007cb729efa0033c609fbd92122 + md5: c20172b4c59fbe288fa50cdc1b693d73 depends: - - cpython 3.12.11.* + - cpython 3.12.12.* - python_abi * *_cp312 license: Python-2.0 purls: [] - size: 45836 - timestamp: 1749047798827 -- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.13.5-h4df99d1_102.conda - sha256: ac6cf618100c2e0cad1cabfe2c44bf4a944aa07bb1dc43abff73373351a7d079 - md5: 2eabcede0db21acee23c181db58b4128 + size: 45888 + timestamp: 1761175248278 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.13.9-h4df99d1_101.conda + sha256: 7535b9cb2414e34c73ed4a97a90bcadcc76b9d47d0bb8ef5002c592d85fe022d + md5: f41e3c1125e292e6bfcea8392a3de3d8 depends: - - cpython 3.13.5.* + - cpython 3.13.9.* - python_abi * *_cp313 license: Python-2.0 purls: [] - size: 47572 - timestamp: 1750062593102 + size: 48385 + timestamp: 1761175154112 - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda sha256: 4790787fe1f4e8da616edca4acf6a4f8ed4e7c6967aa31b920208fc8f95efcca md5: a61bf9ec79426938ff785eb69dbb1960 @@ -3987,6 +4771,25 @@ packages: - pkg:pypi/python-multipart?source=hash-mapping size: 27683 timestamp: 1732988029649 +- pypi: https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl + name: python-slugify + version: 8.0.4 + sha256: 276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8 + requires_dist: + - text-unidecode>=1.3 + - unidecode>=1.1.1 ; extra == 'unidecode' + requires_python: '>=3.7' +- conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.2-pyhd8ed1ab_0.conda + sha256: e8392a8044d56ad017c08fec2b0eb10ae3d1235ac967d0aab8bd7b41c4a5eaf0 + md5: 88476ae6ebd24f39261e0854ac244f33 + depends: + - python >=3.9 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/tzdata?source=hash-mapping + size: 144160 + timestamp: 1742745254292 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda build_number: 8 sha256: 80677180dd3c22deb7426ca89d6203f1c7f1f256f2d5a94dc210f6e758229809 @@ -4009,6 +4812,21 @@ packages: purls: [] size: 7002 timestamp: 1752805902938 +- pypi: https://files.pythonhosted.org/packages/84/25/d9db8be44e205a124f6c98bc0324b2bb149b7431c53877fc6d1038dddaf5/pytokens-0.3.0-py3-none-any.whl + name: pytokens + version: 0.3.0 + sha256: 95b2b5eaf832e469d141a378872480ede3f251a5a5041b8ec6e581d3ac71bbf3 + requires_dist: + - black ; extra == 'dev' + - build ; extra == 'dev' + - mypy ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - setuptools ; extra == 'dev' + - tox ; extra == 'dev' + - twine ; extra == 'dev' + - wheel ; extra == 'dev' + requires_python: '>=3.8' - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl name: pytz version: '2025.2' @@ -4035,17 +4853,17 @@ packages: purls: [] size: 4856 timestamp: 1646866525560 -- pypi: https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl name: pyyaml - version: 6.0.2 - sha256: 70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 + version: 6.0.3 + sha256: 0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 requires_python: '>=3.8' -- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.2-py312h178313f_2.conda - sha256: 159cba13a93b3fe084a1eb9bda0a07afc9148147647f0d437c3c3da60980503b - md5: cf2485f39740de96e2a7f2bb18ed2fee +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_0.conda + sha256: 1b3dc4c25c83093fff08b86a3574bc6b94ba355c8eba1f35d805c5e256455fc7 + md5: fba10c2007c8b06f77c5a23ce3a635ad depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 - yaml >=0.2.5,<0.3.0a0 @@ -4053,27 +4871,27 @@ packages: license_family: MIT purls: - pkg:pypi/pyyaml?source=hash-mapping - size: 206903 - timestamp: 1737454910324 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.2-py313h8060acc_2.conda - sha256: 6826217690cfe92d6d49cdeedb6d63ab32f51107105d6a459d30052a467037a0 - md5: 50992ba61a8a1f8c2d346168ae1c86df + size: 204539 + timestamp: 1758892248166 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py313h3dea7bd_0.conda + sha256: 40dcd6718dce5fbee8aabdd0519f23d456d8feb2e15ac352eaa88bbfd3a881af + md5: 4794ea0adaebd9f844414e594b142cb2 depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT purls: - - pkg:pypi/pyyaml?source=hash-mapping - size: 205919 - timestamp: 1737454783637 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.0.2-py312hfb55c3c_2.conda + - pkg:pypi/pyyaml?source=compressed-mapping + size: 207109 + timestamp: 1758892173548 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hfb55c3c_0.conda noarch: python - sha256: dcf749dcf86feac506c32dc8469f0b8201f5c5077026ade7fe01bf3b90f74ecd - md5: ba7305f9723cc16cf79288e0bb7b34b2 + sha256: a00a41b66c12d9c60e66b391e9a4832b7e28743348cf4b48b410b91927cd7819 + md5: 3399d43f564c905250c1aea268ebb935 depends: - python - __glibc >=2.17,<3.0.a0 @@ -4085,24 +4903,25 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/pyzmq?source=compressed-mapping - size: 211840 - timestamp: 1756136260634 -- conda: https://conda.anaconda.org/conda-forge/linux-64/quarto-1.7.33-ha770c72_0.conda - sha256: 86385aab764b05099f0ea8959510fb70a804cbe5c0294a6777d19f3b9c6aef2d - md5: 0a7ad8dc3e969fb49e38074c93d3b5b8 + - pkg:pypi/pyzmq?source=hash-mapping + size: 212218 + timestamp: 1757387023399 +- conda: https://conda.anaconda.org/conda-forge/linux-64/quarto-1.8.25-hbf95b10_0.conda + sha256: e5ed23a12276e358eb88714ff49a71406f0fbca636326f02c8147870f19fc54c + md5: e1d21422a23c39b3dbe493222f6ad6d7 depends: - dart-sass - - deno >=1.46.3,<1.46.4.0a0 + - deno >=2.3.1,<2.3.2.0a0 - deno-dom >=0.1.41,<0.1.42.0a0 - esbuild + - nodejs >=22.19.0,<23.0a0 - pandoc 3.6.3 - typst 0.13.0 license: MIT license_family: MIT purls: [] - size: 16561225 - timestamp: 1754537016289 + size: 22728666 + timestamp: 1759247033437 - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda sha256: 2d6d0c026902561ed77cd646b5021aef2d4db22e57a5b0178dfc669231e06d2c md5: 283b96675859b20a825f8fa30f311446 @@ -4114,6 +4933,15 @@ packages: purls: [] size: 282480 timestamp: 1740379431762 +- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + name: referencing + version: 0.37.0 + sha256: 381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 + requires_dist: + - attrs>=22.2.0 + - rpds-py>=0.7.0 + - typing-extensions>=4.4.0 ; python_full_version < '3.13' + requires_python: '>=3.10' - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.36.2-pyh29332c3_0.conda sha256: e20909f474a6cece176dfc0dc1addac265deb5fa92ea90e975fbca48085b20c3 md5: 9140f1c09dd5489549c6a33931b943c7 @@ -4129,20 +4957,35 @@ packages: - pkg:pypi/referencing?source=hash-mapping size: 51668 timestamp: 1737836872415 -- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2025.7.34-py312h4c3975b_0.conda - sha256: 603e3208d9f0cb01708c7acc3521e460acfda2d01a182bc06e98beed219a825f - md5: 3f7a1b14a111a4bc196f8e286ac29e65 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 + md5: 870293df500ca7e18bedefa5838a22ab + depends: + - attrs >=22.2.0 + - python >=3.10 + - rpds-py >=0.7.0 + - typing_extensions >=4.4.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/referencing?source=hash-mapping + size: 51788 + timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2025.11.3-py312h4c3975b_1.conda + sha256: 5c5b1959c32a25300f04d1976a3768fc4056e76b4be15cbe9f35837561a61e92 + md5: 667039d7f72bb171f499c7dbea13d76a depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 - license: Python-2.0 + license: Apache-2.0 AND CNRI-Python license_family: PSF purls: - pkg:pypi/regex?source=hash-mapping - size: 407782 - timestamp: 1753984175334 + size: 409564 + timestamp: 1762507059752 - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl name: requests version: 2.32.5 @@ -4169,7 +5012,7 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/requests?source=compressed-mapping + - pkg:pypi/requests?source=hash-mapping size: 59263 timestamp: 1755614348400 - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda @@ -4184,6 +5027,13 @@ packages: - pkg:pypi/rfc3339-validator?source=hash-mapping size: 10209 timestamp: 1733600040800 +- pypi: https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl + name: rfc3986 + version: 2.0.0 + sha256: 50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd + requires_dist: + - idna ; extra == 'idna2008' + requires_python: '>=3.7' - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 sha256: 2a5b495a1de0f60f24d8a74578ebc23b24aa53279b1ad583755f223097c41c37 md5: 912a71cc01012ee38e6b90ddd561e36f @@ -4208,52 +5058,66 @@ packages: - pkg:pypi/rfc3987-syntax?source=hash-mapping size: 22913 timestamp: 1752876729969 -- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.1.0-pyhe01879c_0.conda - sha256: 3bda3cd6aa2ca8f266aeb8db1ec63683b4a7252d7832e8ec95788fb176d0e434 - md5: c41e49bd1f1479bed6c6300038c5466e +- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl + name: rich + version: 14.2.0 + sha256: 76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd + requires_dist: + - ipywidgets>=7.5.1,<9 ; extra == 'jupyter' + - markdown-it-py>=2.2.0 + - pygments>=2.13.0,<3.0.0 + requires_python: '>=3.8.0' +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.2.0-pyhcf101f3_0.conda + sha256: edfb44d0b6468a8dfced728534c755101f06f1a9870a7ad329ec51389f16b086 + md5: a247579d8a59931091b16a1e932bbed6 depends: - markdown-it-py >=2.2.0 - pygments >=2.13.0,<3.0.0 - - python >=3.9 + - python >=3.10 - typing_extensions >=4.0.0,<5.0.0 - python license: MIT license_family: MIT purls: - pkg:pypi/rich?source=compressed-mapping - size: 201098 - timestamp: 1753436991345 -- conda: https://conda.anaconda.org/conda-forge/noarch/rich-rst-1.3.1-pyhd8ed1ab_1.conda - sha256: cbfda01e7903347f1f56494f18768069bbc34c36a3a49a3264cc90ca1fd9e964 - md5: 645849c287d21f6b8d1c54ff454b6db6 + size: 200840 + timestamp: 1760026188268 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-rst-1.3.2-pyhd8ed1ab_0.conda + sha256: 202e90d6624abc924e185166f6fcfdd29c6749ec26d60480a0a34c898c0b67fd + md5: cbd84dbdb3f5a7d762b5fb2b0d49e7cd depends: - docutils - - python >=3.9 + - python >=3.10 - rich >=12.0.0 license: MIT license_family: MIT purls: - pkg:pypi/rich-rst?source=hash-mapping - size: 17117 - timestamp: 1735200283902 -- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.27.1-py312h868fb18_0.conda - sha256: d9ace02196f551cbe608fd9d64628239a2101815a96a8a095e7a426b19956176 - md5: 2c5c390ddeffeb6eecc79df2416783d0 + size: 18299 + timestamp: 1760519277784 +- pypi: https://files.pythonhosted.org/packages/ca/ee/a324d3198da151820a326c1f988caaa4f37fc27955148a76fff7a2d787a9/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: rpds-py + version: 0.28.0 + sha256: b8e1e9be4fa6305a16be628959188e4fd5cd6f1b0e724d63c6d8b2a8adf74ea6 + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.28.0-py312h868fb18_2.conda + sha256: ae6b9ecf6e13009d44163058360811284a3174c8094421eab3520fd77f5ade77 + md5: b21792d3803edb7ae5467442513c264e depends: - python - - __glibc >=2.17,<3.0.a0 - libgcc >=14 + - __glibc >=2.17,<3.0.a0 - python_abi 3.12.* *_cp312 constrains: - __glibc >=2.17 license: MIT purls: - - pkg:pypi/rpds-py?source=hash-mapping - size: 389613 - timestamp: 1756315744748 -- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.27.1-py313h843e2db_0.conda - sha256: 64e5748673d41f055ff4ca5e7a720e9a0a6122f7b2954d21d427f247b9d3e2b8 - md5: f713aec06900657c138e60dc61889557 + - pkg:pypi/rpds-py?source=compressed-mapping + size: 379937 + timestamp: 1762984724704 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.28.0-py313h843e2db_2.conda + sha256: a324240a742bd109fa97661916823e6c2d45b4c6f58957225c914a06cf863794 + md5: 60c24f26f922abfc661967b0ef609935 depends: - python - __glibc >=2.17,<3.0.a0 @@ -4264,18 +5128,18 @@ packages: license: MIT purls: - pkg:pypi/rpds-py?source=hash-mapping - size: 389201 - timestamp: 1756315722486 -- pypi: https://files.pythonhosted.org/packages/c0/1d/b4207ec35e7babaee62c462769e77457e26eb853fbdc877af29417033333/ruff-0.12.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + size: 379483 + timestamp: 1762984685444 +- pypi: https://files.pythonhosted.org/packages/ee/79/6ad4dda2cfd55e41ac9ed6d73ef9ab9475b1eef69f3a85957210c74ba12c/ruff-0.14.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: ruff - version: 0.12.10 - sha256: 1f68433c4fbc63efbfa3ba5db31727db229fa4e61000f452c540474b03de52a9 + version: 0.14.4 + sha256: 456daa2fa1021bc86ca857f43fe29d5d8b3f0e55e9f90c58c317c1dcc2afc7b5 requires_python: '>=3.7' -- conda: https://conda.anaconda.org/conda-forge/linux-64/secretstorage-3.3.3-py312h7900ff3_3.conda - sha256: c6d5d0bc7fb6cbfa3b8be8f2399a3c1308b3392a4e20bd1a0f29a828fda5ab20 - md5: 4840da9db2808db946a0d979603c6de4 +- conda: https://conda.anaconda.org/conda-forge/linux-64/secretstorage-3.4.0-py312h7900ff3_0.conda + sha256: 5c2ba91cf23f7928fd8d906d17cb4aacc46afc2b2ad8b8c6a2013814cf2ee846 + md5: 17ac9aa340fe2e83b67886e11a1ea48d depends: - - cryptography + - cryptography >=2.0 - dbus - jeepney >=0.6 - python >=3.12,<3.13.0a0 @@ -4283,24 +5147,24 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/secretstorage?source=hash-mapping - size: 31601 - timestamp: 1725915741329 -- conda: https://conda.anaconda.org/conda-forge/linux-64/secretstorage-3.3.3-py313h78bf25f_3.conda - sha256: 7f548e147e14ce743a796aa5f26aba11f82c14ab53ab25b48f35974ca48f6ac7 - md5: 813e01c086f6c4e134e13ef25b02df8c + - pkg:pypi/secretstorage?source=compressed-mapping + size: 32448 + timestamp: 1757606914831 +- conda: https://conda.anaconda.org/conda-forge/linux-64/secretstorage-3.4.0-py313h78bf25f_0.conda + sha256: 6b4a6093963291fd0703eca97078107fc3024d744d3bf175aa6fc2af99a1eae1 + md5: 97dc269920a6ad86fe3e460d3b6663e3 depends: - - cryptography + - cryptography >=2.0 - dbus - jeepney >=0.6 - - python >=3.13.0rc1,<3.14.0a0 + - python >=3.13,<3.14.0a0 - python_abi 3.13.* *_cp313 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/secretstorage?source=hash-mapping - size: 32074 - timestamp: 1725915738039 + size: 32835 + timestamp: 1757606804014 - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-1.8.3-pyh0d859eb_1.conda sha256: 00926652bbb8924e265caefdb1db100f86a479e8f1066efe395d5552dde54d02 md5: 938c8de6b9de091997145b3bf25cdbf9 @@ -4324,17 +5188,26 @@ packages: - pkg:pypi/setuptools?source=hash-mapping size: 748788 timestamp: 1748804951958 -- conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_1.conda - sha256: 0557c090913aa63cdbe821dbdfa038a321b488e22bc80196c4b3b1aace4914ef - md5: 7c3c2a0f3ebdea2bbc35538d162b43bf +- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl + name: shellingham + version: 1.5.4 + sha256: 7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 + requires_python: '>=3.7' +- conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda + sha256: 1d6534df8e7924d9087bd388fbac5bd868c5bf8971c36885f9f016da0657d22b + md5: 83ea3a2ddb7a75c1b09cea582aa4f106 depends: - - python >=3.9 + - python >=3.10 license: MIT - license_family: MIT purls: - - pkg:pypi/shellingham?source=hash-mapping - size: 14462 - timestamp: 1733301007770 + - pkg:pypi/shellingham?source=compressed-mapping + size: 15018 + timestamp: 1762858315311 +- pypi: https://files.pythonhosted.org/packages/a0/e9/e58082fbb8cecbb6fb4133033c40cc50c248b1a331582be3a0f39138d65b/simpleeval-1.0.3-py3-none-any.whl + name: simpleeval + version: 1.0.3 + sha256: e3bdbb8c82c26297c9a153902d0fd1858a6c3774bf53ff4f134788c3f2035c38 + requires_python: '>=3.9' - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl name: six version: 1.17.0 @@ -4349,43 +5222,44 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/six?source=compressed-mapping + - pkg:pypi/six?source=hash-mapping size: 18455 timestamp: 1753199211006 -- conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_1.conda - sha256: c2248418c310bdd1719b186796ae50a8a77ce555228b6acd32768e2543a15012 - md5: bf7a226e58dfb8346c70df36065d86c9 +- conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + sha256: dce518f45e24cd03f401cb0616917773159a210c19d601c5f2d4e0e5879d30ad + md5: 03fe290994c5e4ec17293cfb6bdce520 depends: - - python >=3.9 + - python >=3.10 license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/sniffio?source=hash-mapping - size: 15019 - timestamp: 1733244175724 + - pkg:pypi/sniffio?source=compressed-mapping + size: 15698 + timestamp: 1762941572482 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8-pyhd8ed1ab_0.conda sha256: c978576cf9366ba576349b93be1cfd9311c00537622a2f9e14ba2b90c97cae9c md5: 18c019ccf43769d211f2cf78e9ad46c2 depends: - python >=3.10 license: MIT + license_family: MIT purls: - pkg:pypi/soupsieve?source=hash-mapping size: 37803 timestamp: 1756330614547 -- conda: https://conda.anaconda.org/conda-forge/noarch/sse-starlette-3.0.2-pyhd8ed1ab_0.conda - sha256: 225bcbcacbea67a4608cf479f408a4f310aca40eace6b86865629589e5728e51 - md5: a2a0c0d9f04be0a9aeaca213137e2b3a +- conda: https://conda.anaconda.org/conda-forge/noarch/sse-starlette-3.0.3-pyhd8ed1ab_0.conda + sha256: e96f603ddc9979ae20c42dfb02e3c0c67e8e1bfd938b9a0e9d66f21d0acf14f9 + md5: dceec34e1e7394d50a7b67f09962ab44 depends: - anyio >=4.7.0 - - python >=3.9 + - python >=3.10 - starlette >=0.41.3 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/sse-starlette?source=hash-mapping - size: 16857 - timestamp: 1753611797829 + size: 17374 + timestamp: 1761854658607 - conda: https://conda.anaconda.org/conda-forge/noarch/sseclient-py-1.8.0-pyhd8ed1ab_1.conda sha256: b9f39919cfa3951465893faa945cd57ac286d1534823f6c0899dadeba5002ddc md5: e97159ac18916ba0e6aab45eef73aeaa @@ -4424,9 +5298,9 @@ packages: - pkg:pypi/stack-data?source=hash-mapping size: 26988 timestamp: 1733569565672 -- conda: https://conda.anaconda.org/conda-forge/noarch/starlette-0.47.3-pyhfdc7a7d_0.conda - sha256: 12f1e9361138d23c787b321ee0a621a7a04b3918d790e13cef29e5e57f479506 - md5: 7839e6127ef19c0a07fe798d9d1c436b +- conda: https://conda.anaconda.org/conda-forge/noarch/starlette-0.50.0-pyhfdc7a7d_0.conda + sha256: ab9ab67faa3cf12f45f5ced316e2c50dc72b4046cd275612fae756fe9d4cf82c + md5: 68bcb398c375177cf117cf608c274f9d depends: - anyio >=3.6.2,<5 - python >=3.10 @@ -4436,8 +5310,15 @@ packages: license_family: BSD purls: - pkg:pypi/starlette?source=hash-mapping - size: 63403 - timestamp: 1756076609765 + size: 64760 + timestamp: 1762016292582 +- pypi: https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl + name: tabulate + version: 0.9.0 + sha256: 024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f + requires_dist: + - wcwidth ; extra == 'widechars' + requires_python: '>=3.7' - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh0d859eb_0.conda sha256: b300557c0382478cf661ddb520263508e4b3b5871b471410450ef2846e8c352c md5: efba281bbdae5f6b0a1d53c6d4a97c93 @@ -4452,13 +5333,17 @@ packages: - pkg:pypi/terminado?source=hash-mapping size: 22452 timestamp: 1710262728753 -- conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.9.0-py312h14ff09d_0.conda - sha256: aba3affdd0f87e198185ddc0986aa59cb067832dc88ffa6dedbe127da4f8d7bf - md5: 0f116f56298be1450a9db6b45bd2d9a1 +- pypi: https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl + name: text-unidecode + version: '1.3' + sha256: 1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py312hd04cf1f_2.conda + sha256: d572b1e15249dd4d69d64aac3c4cfe911f417ccb5d569012bdb212ce24114107 + md5: 40dce7aa88aa05b0e3b81733962e87c3 depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - - libstdcxx >=13 + - libgcc >=14 + - libstdcxx >=14 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 - regex >=2022.1.18 @@ -4466,11 +5351,10 @@ packages: constrains: - __glibc >=2.17 license: MIT - license_family: MIT purls: - pkg:pypi/tiktoken?source=hash-mapping - size: 968542 - timestamp: 1739550580537 + size: 932770 + timestamp: 1762966101457 - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda sha256: cad582d6f978276522f84bd209a5ddac824742fe2d452af6acf900f8650a73a2 md5: f1acf5fdefa8300de697982bcb1761c9 @@ -4495,15 +5379,15 @@ packages: purls: [] size: 3285204 timestamp: 1748387766691 -- conda: https://conda.anaconda.org/conda-forge/linux-64/tokenizers-0.21.4-py312h6be956c_0.conda - sha256: e40270d073e8159d37ab54d651e7209b867463828bbdb05ef30a7d501ccc2532 - md5: 2141c351576ed7bf2c5b334085a60bb4 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tokenizers-0.22.1-py312h6be956c_1.conda + sha256: 1d138119c30d2ab2e2247993e9830692c5755554cc61d81388ec6150cac068db + md5: e71230073e73c5e9bf05c26e6d07860f depends: - __glibc >=2.17,<3.0.a0 - - huggingface_hub >=0.16.4,<1.0 + - huggingface_hub >=0.16.4,<2.0 - libgcc >=14 - libstdcxx >=14 - - openssl >=3.5.1,<4.0a0 + - openssl >=3.6.0,<4.0a0 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 constrains: @@ -4512,20 +5396,20 @@ packages: license_family: APACHE purls: - pkg:pypi/tokenizers?source=hash-mapping - size: 2366555 - timestamp: 1753768279362 -- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.2.1-pyhe01879c_2.conda - sha256: 040a5a05c487647c089ad5e05ad5aff5942830db2a4e656f1e300d73436436f1 - md5: 30a0a26c8abccf4b7991d590fe17c699 + size: 2470825 + timestamp: 1762916818943 +- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda + sha256: cb77c660b646c00a48ef942a9e1721ee46e90230c7c570cdeb5a893b5cce9bff + md5: d2732eb636c264dc9aa4cbee404b1a53 depends: - - python >=3.9 + - python >=3.10 - python license: MIT license_family: MIT purls: - pkg:pypi/tomli?source=compressed-mapping - size: 21238 - timestamp: 1753796677376 + size: 20973 + timestamp: 1760014679845 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-w-1.2.0-pyhd8ed1ab_0.conda sha256: 304834f2438017921d69f05b3f5a6394b42dc89a90a6128a46acbf8160d377f6 md5: 32e37e8fe9ef45c637ee38ad51377769 @@ -4548,9 +5432,9 @@ packages: - pkg:pypi/tomlkit?source=hash-mapping size: 38777 timestamp: 1749127286558 -- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.2-py312h4c3975b_0.conda - sha256: 891965f8e495ad5cef399db03a13df48df7add06ae131f4b77a88749c74b2060 - md5: 82dacd4832dcde0c2b7888248a3b3d7c +- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.2-py312h4c3975b_2.conda + sha256: aecc1ec07a13693922b0b7db52486298ab1cbfdbf1e20043941d660f868d7881 + md5: 2f03dbd34c9706d67b7c9ee815cc89ef depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 @@ -4559,12 +5443,12 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/tornado?source=compressed-mapping - size: 850503 - timestamp: 1754732194289 -- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.2-py313h07c4f96_0.conda - sha256: bc4df522f933ea8829334d79732d828880bb976ed03a1f68f0826b91eaaee0b1 - md5: 01082edc358a2285f6480b918e35e1af + - pkg:pypi/tornado?source=hash-mapping + size: 851236 + timestamp: 1762506907752 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.2-py313h07c4f96_2.conda + sha256: 8ef12814ebf787553b351c919d40a599e2331aefec639aef5ce6117cbcfc6a28 + md5: 7824f18e343d1f846dcde7b23c9bf31a depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 @@ -4574,8 +5458,8 @@ packages: license_family: Apache purls: - pkg:pypi/tornado?source=hash-mapping - size: 878421 - timestamp: 1754732125966 + size: 871569 + timestamp: 1762506888003 - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.1-pyhd8ed1ab_1.conda sha256: 11e2c85468ae9902d24a27137b6b39b4a78099806e551d390e394a8c34b48e40 md5: 9efbfdc37242619130ea42b1cc4ed861 @@ -4613,80 +5497,85 @@ packages: - pkg:pypi/traitlets?source=hash-mapping size: 110051 timestamp: 1733367480074 -- pypi: https://files.pythonhosted.org/packages/9c/d1/8d5bd662703cc1764d986f6908a608777305946fa634d34c470cd4a1e729/traittypes-0.2.1-py2.py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/8d/c0/fdf9d3ee103ce66a55f0532835ad5e154226c5222423c6636ba049dc42fc/traittypes-0.2.3-py2.py3-none-any.whl name: traittypes - version: 0.2.1 - sha256: 1340af133810b6eee1a2eb2e988f862b0d12b6c2d16f282aaf3207b782134c2e + version: 0.2.3 + sha256: 49016082ce740d6556d9bb4672ee2d899cd14f9365f17cbb79d5d96b47096d4e requires_dist: - traitlets>=4.2.2 - numpy ; extra == 'test' - pandas ; extra == 'test' - xarray ; extra == 'test' - pytest ; extra == 'test' -- conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2025.8.26.11-pyhd8ed1ab_0.conda - sha256: c851abb1c9551ff189f392ca526fde04d2e33cc38b829718bc4560ce8ce73efe - md5: 7e40fb5d7eceaaf74900b3929dddfb06 +- conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2025.9.11.17-pyhd8ed1ab_0.conda + sha256: 74807fa88e811aeaf3d2acd6221665efd9469caf8c57b4ee370b61f0528ff0ae + md5: fc3b129397a910cfe1350075a7ad7432 depends: - python >=3.10 license: Apache-2.0 license_family: Apache purls: - pkg:pypi/trove-classifiers?source=hash-mapping - size: 19483 - timestamp: 1756214076961 -- conda: https://conda.anaconda.org/conda-forge/noarch/typer-0.16.1-pyhc167863_0.conda - sha256: 9b86ae360cb0ee5d3aed5eaa3003d946f868b1b0f72afb2db297e97991f2cd12 - md5: d1a93f6a8a848176099d3605c4101f31 + size: 19575 + timestamp: 1757677773672 +- pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl + name: typeguard + version: 4.4.4 + sha256: b5f562281b6bfa1f5492470464730ef001646128b180769880468bd84b68b09e + requires_dist: + - importlib-metadata>=3.6 ; python_full_version < '3.10' + - typing-extensions>=4.14.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl + name: typer + version: 0.20.0 + sha256: 5b463df6793ec1dca6213a3cf4c0f03bc6e322ac5e16e13ddd622a889489784a + requires_dist: + - click>=8.0.0 + - typing-extensions>=3.7.4.3 + - shellingham>=1.3.0 + - rich>=10.11.0 + requires_python: '>=3.8' +- conda: https://conda.anaconda.org/conda-forge/noarch/typer-0.20.0-pyhefaf540_1.conda + sha256: 17a1e572939af33d709248170871d4da74f7e32b48f2e9b5abca613e201c6e64 + md5: 23a53fdefc45ba3f4e075cc0997fd13b depends: - - typer-slim-standard ==0.16.1 h810d63d_0 - - python >=3.9 + - typer-slim-standard ==0.20.0 h4daf872_1 + - python >=3.10 - python license: MIT - license_family: MIT purls: - pkg:pypi/typer?source=compressed-mapping - size: 77346 - timestamp: 1755547637982 -- conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-0.16.1-pyhe01879c_0.conda - sha256: 4c7cf1427a03d67bbdb2b09aa2fad352dc7cede01fddd510828281064a9accbc - md5: 24db73f88ea930dc00234434f6aeddc6 + size: 79829 + timestamp: 1762984042927 +- conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-0.20.0-pyhcf101f3_1.conda + sha256: 4b5ded929080b91367f128e7299619f6116f08bc77d9924a2f8766e2a1b18161 + md5: 4b02a515f3e882dcfe9cfbf0a1f5cd3a depends: - - python >=3.9 + - python >=3.10 - click >=8.0.0 - typing_extensions >=3.7.4.3 - python constrains: - - typer 0.16.1.* + - typer 0.20.0.* - rich >=10.11.0 - shellingham >=1.3.0 license: MIT - license_family: MIT purls: - pkg:pypi/typer-slim?source=compressed-mapping - size: 46871 - timestamp: 1755547637982 -- conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-standard-0.16.1-h810d63d_0.conda - sha256: 3ffef676f99f9943f5a8c045c7ba9260966321cd6c9a7aba0114ca33c5995747 - md5: a17c34ff6b5095b9366270064be17102 + size: 47951 + timestamp: 1762984042920 +- conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-standard-0.20.0-h4daf872_1.conda + sha256: 5027768bc9a580c8ffbf25872bb2208c058cbb79ae959b1cf2cc54b5d32c0377 + md5: 37b26aafb15a6687b31a3d8d7a1f04e7 depends: - - typer-slim ==0.16.1 pyhe01879c_0 + - typer-slim ==0.20.0 pyhcf101f3_1 - rich - shellingham license: MIT - license_family: MIT purls: [] - size: 5291 - timestamp: 1755547637982 -- conda: https://conda.anaconda.org/conda-forge/noarch/types-python-dateutil-2.9.0.20250822-pyhd8ed1ab_0.conda - sha256: dfdf6e3dea87c873a86cfa47f7cba6ffb500bad576d083b3de6ad1b17e1a59c3 - md5: 5e9220c892fe069da8de2b9c63663319 - depends: - - python >=3.10 - license: Apache-2.0 AND MIT - purls: - - pkg:pypi/types-python-dateutil?source=hash-mapping - size: 24939 - timestamp: 1755865615651 + size: 5322 + timestamp: 1762984042927 - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl name: typing-extensions version: 4.15.0 @@ -4702,25 +5591,25 @@ packages: purls: [] size: 91383 timestamp: 1756220668932 -- pypi: https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl name: typing-inspection - version: 0.4.1 - sha256: 389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51 + version: 0.4.2 + sha256: 4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7 requires_dist: - typing-extensions>=4.12.0 requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.1-pyhd8ed1ab_0.conda - sha256: 4259a7502aea516c762ca8f3b8291b0d4114e094bdb3baae3171ccc0900e722f - md5: e0c3cd765dc15751ee2f0b03cd015712 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_0.conda + sha256: 8aaf69b828c2b94d0784f18f70f11aa032950d304e57e88467120b45c18c24fd + md5: 399701494e731ce73fdd86c185a3d1b4 depends: - - python >=3.9 + - python >=3.10 - typing_extensions >=4.12.0 license: MIT license_family: MIT purls: - - pkg:pypi/typing-inspection?source=hash-mapping - size: 18809 - timestamp: 1747870776989 + - pkg:pypi/typing-inspection?source=compressed-mapping + size: 18799 + timestamp: 1759301271883 - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 md5: 0caa1af407ecff61170c9437a808404d @@ -4730,7 +5619,7 @@ packages: license: PSF-2.0 license_family: PSF purls: - - pkg:pypi/typing-extensions?source=compressed-mapping + - pkg:pypi/typing-extensions?source=hash-mapping size: 51692 timestamp: 1756220668932 - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda @@ -4819,9 +5708,9 @@ packages: - pkg:pypi/userpath?source=hash-mapping size: 14292 timestamp: 1735925027874 -- conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.8.13-heb9285d_0.conda - sha256: 176d6d9cf2e847ef88238fc06ef9ee5c84fc00f77c80b4d9bf273f176708da85 - md5: 7faf18206f2225fbe9e9ed35eaf265a9 +- conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.9.9-h76e24b7_0.conda + sha256: 2e20f8c6e69374688cf8177a280b199c9c92161bf22465071f81832a3074f003 + md5: bc71e01e6f7abacff84011d596cb58d3 depends: - libgcc >=14 - libstdcxx >=14 @@ -4831,8 +5720,8 @@ packages: - __glibc >=2.17 license: Apache-2.0 OR MIT purls: [] - size: 15002992 - timestamp: 1755845004831 + size: 16822208 + timestamp: 1762997132411 - conda: https://conda.anaconda.org/conda-forge/linux-64/uvicorn-0.29.0-py312h7900ff3_0.conda sha256: e1f0c882f3b17b6d13f31b214ab87657f53d15cd7b221301104e293044986d8c md5: 5abb5cedead2c9a8d616a1b8e5503be8 @@ -4847,21 +5736,28 @@ packages: - pkg:pypi/uvicorn?source=hash-mapping size: 126964 timestamp: 1710932152563 -- conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.34.0-pyhd8ed1ab_0.conda - sha256: 398f40090e80ec5084483bb798555d0c5be3d1bb30f8bb5e4702cd67cdb595ee - md5: 2bd6c0c96cfc4dbe9bde604a122e3e55 +- pypi: https://files.pythonhosted.org/packages/fa/6e/3e955517e22cbdd565f2f8b2e73d52528b14b8bcfdb04f62466b071de847/validators-0.35.0-py3-none-any.whl + name: validators + version: 0.35.0 + sha256: e8c947097eae7892cb3d26868d637f79f47b4a0554bc6b80065dfe5aac3705dd + requires_dist: + - eth-hash[pycryptodome]>=0.7.0 ; extra == 'crypto-eth-addresses' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.35.4-pyhd8ed1ab_0.conda + sha256: 77193c99c6626c58446168d3700f9643d8c0dab1f6deb6b9dd039e6872781bfb + md5: cfccfd4e8d9de82ed75c8e2c91cab375 depends: - distlib >=0.3.7,<1 - filelock >=3.12.2,<4 - platformdirs >=3.9.1,<5 - - python >=3.9 + - python >=3.10 - typing_extensions >=4.13.2 license: MIT license_family: MIT purls: - pkg:pypi/virtualenv?source=compressed-mapping - size: 4381624 - timestamp: 1755111905876 + size: 4401341 + timestamp: 1761726489722 - conda: https://conda.anaconda.org/conda-forge/noarch/voila-0.5.11-pyhd8ed1ab_1.conda sha256: 9766b970d848d9902a94e4a7b904d9331eb60658f427d73c8493501ad5c894f9 md5: 2a1de13cdf50ded5f8046f8f007b8bf1 @@ -4890,34 +5786,33 @@ packages: requires_dist: - bracex>=2.1.1 requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl name: wcwidth - version: 0.2.13 - sha256: 3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 - requires_dist: - - backports-functools-lru-cache>=1.2.1 ; python_full_version < '3.2' -- conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.13-pyhd8ed1ab_1.conda - sha256: f21e63e8f7346f9074fd00ca3b079bd3d2fa4d71f1f89d5b6934bf31446dc2a5 - md5: b68980f2495d096e71c7fd9d7ccf63e6 + version: 0.2.14 + sha256: a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1 + requires_python: '>=3.6' +- conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.14-pyhd8ed1ab_0.conda + sha256: e311b64e46c6739e2a35ab8582c20fa30eb608da130625ed379f4467219d4813 + md5: 7e1e5ff31239f9cd5855714df8a3783d depends: - - python >=3.9 + - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/wcwidth?source=hash-mapping - size: 32581 - timestamp: 1733231433877 -- conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-24.11.1-pyhd8ed1ab_0.conda - sha256: 08315dc2e61766a39219b2d82685fc25a56b2817acf84d5b390176080eaacf99 - md5: b49f7b291e15494aafb0a7d74806f337 + size: 33670 + timestamp: 1758622418893 +- conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + sha256: 21f6c8a20fe050d09bfda3fb0a9c3493936ce7d6e1b3b5f8b01319ee46d6c6f6 + md5: 6639b6b0d8b5a284f027a2003669aa65 depends: - - python >=3.9 + - python >=3.10 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/webcolors?source=hash-mapping - size: 18431 - timestamp: 1733359823938 + size: 18987 + timestamp: 1761899393153 - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda sha256: 19ff205e138bb056a46f9e3839935a2e60bd1cf01c8241a5e172a422fed4f9c6 md5: 2841eb5bfc75ce15e9a0054b98dcd64d @@ -4929,35 +5824,47 @@ packages: - pkg:pypi/webencodings?source=hash-mapping size: 15496 timestamp: 1733236131358 -- conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.8.0-pyhd8ed1ab_1.conda - sha256: 1dd84764424ffc82030c19ad70607e6f9e3b9cb8e633970766d697185652053e - md5: 84f8f77f0a9c6ef401ee96611745da8f +- conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + sha256: 42a2b61e393e61cdf75ced1f5f324a64af25f347d16c60b14117393a98656397 + md5: 2f1ed718fcd829c184a6d4f0f2e07409 depends: - - python >=3.9 + - python >=3.10 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/websocket-client?source=hash-mapping - size: 46718 - timestamp: 1733157432924 -- conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-15.0.1-py312h66e93f0_0.conda - sha256: d55c82992553720a4c2f49d383ce8260a4ce1fa39df0125edb71f78ff2ee3682 - md5: b986da7551224417af6b7da4021d8050 + size: 61391 + timestamp: 1759928175142 +- conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-15.0.1-py312h5253ce2_2.conda + sha256: 550e082eb189cf1a6dea57e544259152704759524f373ba2bd773cb8214a0c23 + md5: 3fed1ea2c74091df72ad4e893e55c905 depends: + - python - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - - python >=3.12,<3.13.0a0 + - libgcc >=14 - python_abi 3.12.* *_cp312 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/websockets?source=hash-mapping - size: 265549 - timestamp: 1741285580597 -- pypi: https://files.pythonhosted.org/packages/ca/51/5447876806d1088a0f8f71e16542bf350918128d0a69437df26047c8e46f/widgetsnbextension-4.0.14-py3-none-any.whl + size: 356215 + timestamp: 1756476348289 +- conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.1-pyhd8ed1ab_0.conda + sha256: 8de7b1b2e5f8a4300088e406cf4ebdac86f76d9986424af5277fb6eaccf384b3 + md5: 1180d2cfd2aefc04fca2f127fa76d983 + depends: + - markupsafe >=2.1.1 + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/werkzeug?source=hash-mapping + size: 242626 + timestamp: 1730494409132 +- pypi: https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl name: widgetsnbextension - version: 4.0.14 - sha256: 4875a9eaf72fbf5079dc372a51a9f268fc38d46f767cbf85c43a36da5cb9b575 + version: 4.0.15 + sha256: 8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366 requires_python: '>=3.7' - conda: https://conda.anaconda.org/conda-forge/linux-64/xclip-0.13-hb9d3cd8_4.conda sha256: 7795c9b28a643a7279e6008dfe625cda3c8ee8fa6e178d390d7e213fe4291a5d @@ -4972,6 +5879,28 @@ packages: purls: [] size: 23536 timestamp: 1731320447881 +- pypi: https://files.pythonhosted.org/packages/23/66/d0ce2f2e05a04c1d020f7cad5c7d211810a904772ca2178488d47c7ef3e4/xlsxdatagrid-0.3.2-py3-none-any.whl + name: xlsxdatagrid + version: 0.3.2 + sha256: 066ffb0ce934dacb234f4f524b37d661c9a47d0d87e6ff9349d59ecb5cc6ea63 + requires_dist: + - casefy + - datamodel-code-generator>=0.28.5 + - dirty-equals + - frictionless + - frictionless[pandas] + - jsonref + - palettable + - pydantic-extra-types + - pydantic>2 + - python-calamine + - xlsxwriter>=3.2.1 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/3a/0c/3662f4a66880196a590b202f0db82d919dd2f89e99a27fadef91c4a33d41/xlsxwriter-3.2.9-py3-none-any.whl + name: xlsxwriter + version: 3.2.9 + sha256: 9a5db42bc5dff014806c58a20b9eae7322a134abb6fce3c92c181bfb275ec5b3 + requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda sha256: c12396aabb21244c212e488bbdc4abcdef0b7404b15761d9329f5a4a39113c4b md5: fb901ff28063514abb6046c9ec2c4a45 @@ -5008,28 +5937,28 @@ packages: purls: [] size: 835896 timestamp: 1741901112627 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb9d3cd8_0.conda - sha256: ed10c9283974d311855ae08a16dfd7e56241fac632aec3b92e3cfe73cff31038 - md5: f6ebe2cb3f82ba6c057dde5d9debe4f7 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda + sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b + md5: b2895afaf55bf96a8c8282a2e47a5de0 depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 license: MIT license_family: MIT purls: [] - size: 14780 - timestamp: 1734229004433 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb9d3cd8_0.conda - sha256: 6b250f3e59db07c2514057944a3ea2044d6a8cdde8a47b6497c254520fade1ee - md5: 8035c64cb77ed555e3f150b7b3972480 + size: 15321 + timestamp: 1762976464266 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda + sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 + md5: 1dafce8548e38671bea82e3f5c6ce22f depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 license: MIT license_family: MIT purls: [] - size: 19901 - timestamp: 1727794976192 + size: 20591 + timestamp: 1762976546182 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.6-hb9d3cd8_0.conda sha256: da5dc921c017c05f38a38bd75245017463104457b63a1ce633ed41f214159c14 md5: febbab7d15033c913d53c7a2c102309d @@ -5093,13 +6022,13 @@ packages: purls: [] size: 85189 timestamp: 1753484064210 -- conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.20.1-py312h178313f_0.conda - sha256: f5c2c572423fac9ea74512f96a7c002c81fd2eb260608cfa1edfaeda4d81582e - md5: 3b3fa80c71d6a8d0380e9e790f5a4a8a +- conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.22.0-py312h8a5da7c_0.conda + sha256: 6e3f2db09387fc982b5400b842745084825cd2d4621e8278e4af8fb0dc2b55d8 + md5: 6a3fd177315aaafd4366930d440e4430 depends: - __glibc >=2.17,<3.0.a0 - idna >=2.0 - - libgcc >=13 + - libgcc >=14 - multidict >=4.0 - propcache >=0.2.1 - python >=3.12,<3.13.0a0 @@ -5108,22 +6037,23 @@ packages: license_family: Apache purls: - pkg:pypi/yarl?source=hash-mapping - size: 149496 - timestamp: 1749555225039 -- conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h3b0a872_7.conda - sha256: a4dc72c96848f764bb5a5176aa93dd1e9b9e52804137b99daeebba277b31ea10 - md5: 3947a35e916fcc6b9825449affbf4214 + size: 151549 + timestamp: 1761337128623 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h387f397_9.conda + sha256: 47cfe31255b91b4a6fa0e9dbaf26baa60ac97e033402dbc8b90ba5fee5ffe184 + md5: 8035e5b54c08429354d5d64027041cad depends: + - libstdcxx >=14 + - libgcc >=14 - __glibc >=2.17,<3.0.a0 - - krb5 >=1.21.3,<1.22.0a0 - - libgcc >=13 + - libgcc >=14 - libsodium >=1.0.20,<1.0.21.0a0 - - libstdcxx >=13 + - krb5 >=1.21.3,<1.22.0a0 license: MPL-2.0 license_family: MOZILLA purls: [] - size: 335400 - timestamp: 1731585026517 + size: 310648 + timestamp: 1757370847287 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda sha256: 7560d21e1b021fd40b65bfb72f67945a3fcb83d78ad7ccf37b8b3165ec3b68ad md5: df5e78d904988eb55042c0c97446079f @@ -5135,33 +6065,48 @@ packages: - pkg:pypi/zipp?source=hash-mapping size: 22963 timestamp: 1749421737203 -- conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py312h4c3975b_3.conda - sha256: 40c76563f3a398f27b4036e468881a1f909a8c66d100a16a28c1379a0940a59c - md5: 7a2c6e25a4fabf9fab62ee1977beabe5 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py312h5253ce2_1.conda + sha256: c2bcb8aa930d6ea3c9c7a64fc4fab58ad7bcac483a9a45de294f67d2f447f413 + md5: 02738ff9855946075cbd1b5274399a41 depends: - - __glibc >=2.17,<3.0.a0 + - python - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 - libgcc >=14 - - python >=3.12,<3.13.0a0 + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 - python_abi 3.12.* *_cp312 license: BSD-3-Clause - license_family: BSD purls: - - pkg:pypi/zstandard?source=hash-mapping - size: 488806 - timestamp: 1756075707087 -- conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py313h07c4f96_3.conda - sha256: a2e3a0f646bc2f33fd87de332f73b88b7c3efb7b693e06a920f6aaa0d2f49231 - md5: 0720da5e63f3c93647350cc217fdf2bc + - pkg:pypi/zstandard?source=compressed-mapping + size: 467133 + timestamp: 1762512686069 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py313h54dd161_1.conda + sha256: e6921de3669e1bbd5d050a3b771b46a887e7f4ffeb1ddd5e4d9fb01062a2f6e9 + md5: 710d4663806d0f72b2fb414e936223b5 depends: - - __glibc >=2.17,<3.0.a0 + - python - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 - libgcc >=14 - - python >=3.13,<3.14.0a0 + - __glibc >=2.17,<3.0.a0 - python_abi 3.13.* *_cp313 + - zstd >=1.5.7,<1.6.0a0 license: BSD-3-Clause - license_family: BSD purls: - pkg:pypi/zstandard?source=hash-mapping - size: 492832 - timestamp: 1756075709448 + size: 471496 + timestamp: 1762512679097 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda + sha256: a4166e3d8ff4e35932510aaff7aa90772f84b4d07e9f6f83c614cba7ceefe0eb + md5: 6432cb5d4ac0046c3ac0a8a0f95842f9 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 567578 + timestamp: 1742433379869 diff --git a/pyproject.toml b/pyproject.toml index 4830eadf..f204c526 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,7 @@ requires = ["hatchling", "hatch-vcs"] name = "ipyautoui" dynamic = ["version"] license = "BSD-3-Clause" +requires-python = ">=3.8,<3.14" license-files = ["licenses/BSD-3-Clause.txt"] description = "wrapper that sits on top of ipywidgets and other ipy widget libraries to template / automate the creation of widget forms. Uses pydantic to create defined data-container and serialisation to JSON. Includes example patterns for adding new custom widgets." readme = "README.md" @@ -40,7 +41,10 @@ dependencies = [ "pydantic-settings", "pydantic-extra-types", "PyYAML", - "wcmatch", + "wcmatch", + "deepdiff", + "datamodel-code-generator>=0.28.5", + "xlsxdatagrid>=0.3.2,<0.4", ] [project.urls] diff --git a/src/ipyautoui/automapschema.py b/src/ipyautoui/automapschema.py index 50cc9f5a..f02ff81d 100644 --- a/src/ipyautoui/automapschema.py +++ b/src/ipyautoui/automapschema.py @@ -12,14 +12,61 @@ from ipyautoui.custom.filechooser import FileChooser from ipyautoui.custom.date_string import DatePickerString, NaiveDatetimePickerString from ipyautoui.autobox import AutoBox +from tempfile import TemporaryDirectory +import pathlib +from datamodel_code_generator import DataModelType, InputFileType, generate +import json +import importlib.util +import sys import logging logger = logging.getLogger(__name__) +def pydantic_model_file_from_json_schema(json_schema, fpth): + return generate( + json.dumps(json_schema, ensure_ascii=False), + input_file_type=InputFileType.JsonSchema, + input_filename="example.json", + output=fpth, + output_model_type=DataModelType.PydanticV2BaseModel, + capitalise_enum_members=True, + ) + +def pydantic_model_from_json_schema(json_schema: dict) -> ty.Type[BaseModel]: + load = json_schema["title"].replace(" ", "") if "title" in json_schema else "Model" + + with TemporaryDirectory() as temporary_directory_name: + temporary_directory = pathlib.Path(temporary_directory_name) + file_path = "model.py" + module_name = file_path.split(".")[0] + output = pathlib.Path(temporary_directory / file_path) + + pydantic_model_file_from_json_schema(json_schema, output) + + #HACK refer to https://github.com/koxudaxi/datamodel-code-generator/issues/2534 for official fix, then remove the PATCH LOGIC once that is resolved + # --- NEW PATCH LOGIC --- + if json_schema.get("title") == "Project Building Area": + text = output.read_text() + + # Replace Enum → IntEnum in TargetYear only + text = text.replace("class TargetYear(Enum):", "class TargetYear(IntEnum):") + + # Ensure IntEnum is imported + if "from enum import IntEnum" not in text: + text = text.replace("from enum import Enum", "from enum import Enum, IntEnum") + + output.write_text(text) + # --- END PATCH LOGIC --- + + spec = importlib.util.spec_from_file_location(module_name, output) + module = importlib.util.module_from_spec(spec) + sys.modules[module_name] = module + spec.loader.exec_module(module) + return getattr(module, load) def _init_model_schema( - schema=None, by_alias=False + schema=None, by_alias=False, generate_pydantic_model_from_json_schema = True ) -> tuple[ty.Optional[ty.Type[BaseModel]], dict]: if schema is None: return None, { @@ -28,7 +75,10 @@ def _init_model_schema( "items": {"properties": {}}, } if isinstance(schema, dict): - model = None # jsonschema_to_pydantic(schema) + if generate_pydantic_model_from_json_schema: + model = pydantic_model_from_json_schema(schema) + else: + model = None # IDEA: Possible implementations -@jovyan at 8/24/2022, 12:05:02 PM # jsonschema_to_pydantic # https://koxudaxi.github.io/datamodel-code-generator/using_as_module/ diff --git a/src/ipyautoui/custom/__init__.py b/src/ipyautoui/custom/__init__.py index 47ae1378..2f4593cd 100644 --- a/src/ipyautoui/custom/__init__.py +++ b/src/ipyautoui/custom/__init__.py @@ -6,7 +6,7 @@ from ipyautoui.custom.fileupload import FileUploadToDir, FilesUploadToDir from ipyautoui.custom.executetasks import ExecuteTasks, SelectAndExecute from ipyautoui.custom.svgspinner import SvgSpinner -from ipyautoui.custom.filedownload import FileDownload, FilesDownload, SelectAndDownload +from ipyautoui.custom.filedownload import FileDownload, FilesDownload, SelectAndDownload, MakeFileAndDownload from ipyautoui.custom.maplist import MapList from ipyautoui.custom.jsonable_dict import JsonableDict @@ -23,6 +23,7 @@ "SelectAndExecute", "SvgSpinner", "FileDownload", + "MakeFileAndDownload", "FilesDownload", "SelectAndDownload", "MapList", diff --git a/src/ipyautoui/custom/autogrid.py b/src/ipyautoui/custom/autogrid.py index 7b03fe25..f6b75ec1 100644 --- a/src/ipyautoui/custom/autogrid.py +++ b/src/ipyautoui/custom/autogrid.py @@ -516,6 +516,7 @@ def update_from_schema( by_alias: bool = False, by_title: bool = True, order: ty.Optional[tuple] = None, + generate_pydantic_model_from_json_schema: bool = False, **kwargs, ): self.__init__( @@ -524,6 +525,7 @@ def update_from_schema( by_alias=by_alias, by_title=by_title, order=order, + generate_pydantic_model_from_json_schema=generate_pydantic_model_from_json_schema, **kwargs, ) @@ -606,6 +608,7 @@ def __init__( by_alias: bool = False, by_title: bool = True, order: ty.Optional[tuple] = None, + generate_pydantic_model_from_json_schema: bool = False, **kwargs, ): # accept schema or pydantic schema @@ -614,7 +617,7 @@ def __init__( ) self.by_title = by_title self.selection_mode = MAP_TRANSPOSED_SELECTION_MODE[self.transposed] - self.model, self.schema = asch._init_model_schema(schema, by_alias=by_alias) + self.model, self.schema = asch._init_model_schema(schema, by_alias=by_alias, generate_pydantic_model_from_json_schema=generate_pydantic_model_from_json_schema) # ^ generates gridschema self.gridschema.get_traits = self.datagrid_trait_names _data = self._init_data(data) diff --git a/src/ipyautoui/custom/buttonbars.py b/src/ipyautoui/custom/buttonbars.py index 0a12da90..65354e76 100644 --- a/src/ipyautoui/custom/buttonbars.py +++ b/src/ipyautoui/custom/buttonbars.py @@ -240,6 +240,8 @@ def _observe_tgl_unsaved_changes(self, onchange): if __name__ == "__main__": sb.unsaved_changes = True +IO_BUTTON_KWARGS = {'tooltip': 'import/export', 'style': {}, 'layout': {'width': '44px'}, 'icon': 'arrows-alt-v'} + # + class CrudOptions(ty.TypedDict): @@ -254,7 +256,9 @@ class CrudView(ty.TypedDict): edit: CrudOptions copy: CrudOptions delete: CrudOptions + io: CrudOptions reload: CrudOptions + support: CrudOptions DEFAULT_BUTTONBAR_CONFIG = CrudView( @@ -294,6 +298,14 @@ class CrudView(ty.TypedDict): message="🗑️ Deleting Value", ) ), + io=CrudOptions( + **dict(IO_BUTTON_KWARGS) + | dict( + tooltip="import/export", + tooltip_clicked="Go back to table", + message="🔄 Import / Export", + ) + ), reload=CrudOptions( **dict(RELOAD_BUTTON_KWARGS) | dict( @@ -324,7 +336,7 @@ def display_ui_tooltips(uiobj: w.DOMWidget) -> w.VBox: if v.tooltip is not None: li.append(v) except Exception as err: - logging.warning(err) + logging.info(err) replace_newlines = lambda x: x.replace("\n", "
") return w.VBox( [w.HBox([l, w.HTML(f"{replace_newlines(l.tooltip)}")]) for l in li] @@ -340,9 +352,18 @@ class CrudButtonBar(w.VBox): fn_delete = tr.Callable(default_value=lambda: print("delete")) fn_backward = tr.Callable(default_value=lambda: print("backward")) fn_support = tr.Callable(default_value=lambda: print("support")) + fn_io = tr.Callable(default_value=lambda: print("io")) fn_reload = tr.Callable(default_value=None, allow_none=True) + show_io = tr.Bool(default_value=False) show_support = tr.Bool(default_value=True) + @tr.observe("show_io") + def _observe_show_io(self, change): + if change["new"]: + self.io.layout.display = "" + else: + self.io.layout.display = "None" + @tr.observe("show_support") def _observe_show_support(self, change): if change["new"]: @@ -387,6 +408,7 @@ def __init__( self.edit, self.copy, self.delete, + self.io, self.reload, self.support, self.message, @@ -400,17 +422,20 @@ def _init_form(self): self.edit = w.ToggleButton() self.copy = w.ToggleButton() self.delete = w.ToggleButton() + self.io = w.ToggleButton() self.reload = w.Button() self.support = w.ToggleButton() # ^ KWARGS for the buttons are set by CrudView self.message = w.HTML() self._set_crud_view_options() + self.io.layout.display = "" if self.show_io else "None" def _init_controls(self): self.add.observe(self._add, "value") self.edit.observe(self._edit, "value") self.copy.observe(self._copy, "value") self.delete.observe(self._delete, "value") + self.io.observe(self._io, "value") self.support.observe(self._support, "value") self.reload.on_click(self._reload) @@ -448,6 +473,9 @@ def _delete(self, onchange): def _support(self, onchange): self._onclick("support") + def _io(self, onchange): + self._onclick("io") + def _reload(self, on_click): logger.info("Reloading all data") self.fn_reload() @@ -470,6 +498,8 @@ def reset_toggles_except(self, name=None): setattr(getattr(self, n), "value", False) +# + +# len(DEFAULT_BUTTONBAR_CONFIG) # - if __name__ == "__main__": @@ -489,12 +519,16 @@ def delete(): def backward(): print("BACK") + def io(): + print("IO") + buttonbar = CrudButtonBar( fn_add=add, fn_edit=edit, fn_copy=copy, fn_delete=delete, fn_backward=backward, + fn_io=io, fn_reload=lambda: print("fn_reload"), ) display(buttonbar) diff --git a/src/ipyautoui/custom/editgrid.py b/src/ipyautoui/custom/editgrid.py index 97d3e261..eb3cbba3 100644 --- a/src/ipyautoui/custom/editgrid.py +++ b/src/ipyautoui/custom/editgrid.py @@ -11,7 +11,7 @@ import pandas as pd import ipywidgets as w from IPython.display import clear_output, display -from pydantic import BaseModel, Field +from pydantic import BaseModel, RootModel, Field import json from ipyautoui.autoobject import AutoObjectForm @@ -19,9 +19,11 @@ from ipyautoui._utils import frozenmap, traits_in_kwargs from ipyautoui.constants import BUTTON_WIDTH_MIN from ipyautoui.custom.autogrid import AutoGrid +from ipyautoui.custom.edittsv import EditTsvWithDiff from ipyautoui.custom.title_description import TitleDescription MAP_TRANSPOSED_SELECTION_MODE = frozenmap({True: "column", False: "row"}) +logger = logging.getLogger(__name__) # TODO: rename "add" to "fn_add" so not ambiguous... # - @@ -42,26 +44,18 @@ class DataHandler(BaseModel): # REVIEW... MAYBE SHOULD USE *ARGS AND **KWARGS fn_get_all_data: ty.Callable # TODO: rename to fn_get - fn_post: ty.Callable[[dict], None] + fn_post: ty.Callable[[dict], None] # should return int fn_patch: ty.Callable[[ty.Any, dict], None] # TODO: need to add index fn_delete: ty.Callable[[list[int]], None] fn_copy: ty.Callable[[list[int]], None] + fn_io: ty.Optional[ty.Callable] = None if __name__ == "__main__": + from ipyautoui.demo_schemas import EditableGrid + from ipyautoui.demo_schemas.editable_datagrid import DataFrameCols - class TestModel(BaseModel): - string: str = Field("string", title="Important String") - integer: int = Field(40, title="Integer of somesort") - floater: float = Field(1.33, title="floater") - - def test_save(): - print("Saved.") - - def test_revert(): - print("Reverted.") - - ui = AutoObjectForm.from_pydantic_model(TestModel) + ui = AutoObjectForm.from_pydantic_model(DataFrameCols) display(ui) if __name__ == "__main__": @@ -72,15 +66,6 @@ def test_revert(): ui.value = {"string": "adfs", "integer": 2, "floater": 1.22} -class RowEditor: - fn_add: ty.List[ty.Callable[[ty.Any, dict], None]] # post - fn_edit: ty.List[ty.Callable[[ty.Any, dict], None]] # patch - fn_move: ty.Callable - fn_copy: ty.Callable - fn_delete: ty.Callable - - -# + class UiDelete(w.VBox): value = tr.Dict(default_value={}) columns = tr.List(default_value=[]) @@ -213,17 +198,38 @@ def _bn_copy(self, onclick): if __name__ == "__main__": display(UiCopy()) + + + +# + +import json +import ipywidgets as widgets +from IPython.display import Javascript + +def copy_text_button(text: str) -> widgets.Widget: + button = widgets.Button(description="Copy", icon="copy") + output = widgets.Output(layout=widgets.Layout(display="none")) + copy_js = Javascript(f"navigator.clipboard.writeText({json.dumps(text)})") + + def on_click(_: widgets.Button) -> None: + output.clear_output() + output.append_display_data(copy_js) + button.on_click(on_click) + + return widgets.Box((button, output)) + + # + # TODO: refactor how the datahandler works... # TODO: add a test for the datahandler... - # from ipyautoui.watch_validate import WatchValidate class EditGrid(w.VBox, TitleDescription): _value = tr.Tuple() # using a tuple to guarantee no accidental mutation warn_on_delete = tr.Bool() show_copy_dialogue = tr.Bool() close_crud_dialogue_on_action = tr.Bool() + show_ui_io = tr.Bool(default_value=False) @tr.observe("warn_on_delete") def observe_warn_on_delete(self, on_change): @@ -238,7 +244,7 @@ def observe_show_copy_dialogue(self, on_change): self.ui_copy.layout.display = "" else: self.ui_copy.layout.display = "None" - + @property def json(self): # HOTFIX: not required if WatchValidate is used return json.dumps(self.value, indent=4) @@ -250,6 +256,11 @@ def transposed(self): @transposed.setter def transposed(self, value: bool): self.grid.transposed = value + if getattr(self, "ui_io", None) is not None: + if "transposed" in self.ui_io.traits(): + self.ui_io.transposed = value + else: + logger.warning("transposed not found in ui_io") @property def value(self): @@ -292,16 +303,19 @@ def __init__( ui_edit: ty.Optional[ty.Callable] = None, ui_delete: ty.Optional[ty.Callable] = None, ui_copy: ty.Optional[ty.Callable] = None, + ui_io: ty.Optional[ty.Callable] = None, warn_on_delete: bool = False, show_copy_dialogue: bool = False, close_crud_dialogue_on_action: bool = False, title: str = None, description: str = None, show_title: bool = True, + generate_pydantic_model_from_json_schema: bool = False, + show_ui_io: bool = False, **kwargs, ): # TODO: use **kwargs to pass attributes to EditGrid as in AutoObject and AutoArray self.vbx_error = w.VBox() - self.vbx_widget = w.VBox() + self.vbx_widget = w.VBox(layout={"width": "100%"}) # TODO: ^ move common container attributes to WatchValidate self.description = description self.title = title @@ -309,11 +323,17 @@ def __init__( self.by_title = by_title self.by_alias = by_alias self.datahandler = datahandler + self.generate_pydantic_model_from_json_schema = generate_pydantic_model_from_json_schema + + self.ui_io = None + self._ui_io_factory = None + self.show_ui_io = show_ui_io + self.ui_io_initialised = False self.close_crud_dialogue_on_action = close_crud_dialogue_on_action self._init_autogrid(schema, value, **kwargs) self._init_ui_callables( - ui_add=ui_add, ui_edit=ui_edit, ui_delete=ui_delete, ui_copy=ui_copy + ui_add=ui_add, ui_edit=ui_edit, ui_delete=ui_delete, ui_copy=ui_copy, ui_io=ui_io ) self._init_form() self._init_row_controls() @@ -342,17 +362,19 @@ def update_from_schema( ui_edit: ty.Optional[ty.Callable] = None, ui_delete: ty.Optional[ty.Callable] = None, ui_copy: ty.Optional[ty.Callable] = None, + ui_io: ty.Optional[ty.Callable] = None, **kwargs, ): getvalue = lambda value: ( None if value is None or value == [{}] else pd.DataFrame(value) ) self.grid.update_from_schema( - schema, data=getvalue(value), by_alias=self.by_alias, **kwargs + schema, data=getvalue(value), by_alias=self.by_alias, generate_pydantic_model_from_json_schema=self.generate_pydantic_model_from_json_schema, **kwargs ) self._init_ui_callables( - ui_add=ui_add, ui_edit=ui_edit, ui_delete=ui_delete, ui_copy=ui_copy + ui_add=ui_add, ui_edit=ui_edit, ui_delete=ui_delete, ui_copy=ui_copy, ui_io=ui_io ) + self._init_ui_io(ui_io=ui_io) self._init_row_controls() self._init_controls() self._set_children_editgrid() @@ -368,7 +390,7 @@ def _init_autogrid( None if value is None or value == [{}] else pd.DataFrame(value) ) self.grid = AutoGrid( - schema, data=getvalue(value), by_alias=self.by_alias, **kwargs + schema, data=getvalue(value), generate_pydantic_model_from_json_schema=self.generate_pydantic_model_from_json_schema, by_alias=self.by_alias, **kwargs ) def _init_ui_callables( @@ -377,6 +399,7 @@ def _init_ui_callables( ui_edit: ty.Optional[ty.Callable] = None, ui_delete: ty.Optional[ty.Callable] = None, ui_copy: ty.Optional[ty.Callable] = None, + ui_io: ty.Optional[ty.Callable] = None, ): if ui_add is None: self.ui_add = AutoObjectForm.from_jsonschema(self.row_schema) @@ -395,9 +418,61 @@ def _init_ui_callables( self.ui_copy = UiCopy() else: self.ui_copy = ui_copy() + self.ui_io = None + self._ui_io_factory = None + if self.show_ui_io: + def _missing_model_ui(): + return w.HTML("must instantiate with pydantic model for this feature") + + if ui_io is None: + def _factory(): + if self.model is None: + return _missing_model_ui() + return EditTsvWithDiff( + model=self.model, fn_upload=self.fn_upload, transposed=self.transposed + ) + self._ui_io_factory = _factory + else: + def _factory_custom(): + if self.model is None: + return _missing_model_ui() + try: + return ui_io( + model=self.model, fn_upload=self.fn_upload, transposed=self.transposed + ) + except Exception as e: + raise RuntimeError( + f"Failed to initialize ui_io '{ui_io.__name__}'." + " Required traits are: `model`, `fn_upload`, `transposed`." + f" Original error: {e}" + ) from e + self._ui_io_factory = _factory_custom self.ui_copy.layout.display = "None" self.ui_delete.fn_delete = self._delete_selected + def _init_ui_io(self, ui_io): + if ui_io is not None and self.ui_io_initialised: + self.ui_io = ui_io( + model=self.model, fn_upload=self.fn_upload, transposed=self.transposed + ) + + def _ensure_ui_io_initialised(self): + if not self.show_ui_io: + return None + if self.ui_io is not None: + return self.ui_io + if self._ui_io_factory is None: + return None + self.ui_io = self._ui_io_factory() + if hasattr(self.ui_io, "traits") and "transposed" in self.ui_io.traits(): + self.ui_io.transposed = self.transposed + self._set_children_editgrid() + return self.ui_io + + def fn_upload(self, value): + """This method sets the grid's value to the ui_io value. Override this method to add additional functionality to save changes.""" + self.value=value + def _init_row_controls(self): self.ui_edit.show_savebuttonbar = True self.ui_edit.savebuttonbar.fns_onsave = [self._patch, self._save_edit_to_grid] @@ -416,6 +491,8 @@ def _init_form(self): fn_copy=self._copy, fn_delete=self._delete, fn_reload=get_reload(), + fn_io=self._io, + show_io=self.show_ui_io ) self.stk_crud = w.Stack( children=[self.ui_add, self.ui_edit, self.ui_copy, self.ui_delete] @@ -438,12 +515,15 @@ def _set_datahandler(self, datahandler): def _set_children_editgrid(self): self.vbx_widget.children = [self.buttonbar_grid, self.stk_crud, self.grid] - self.stk_crud.children = [ - self.ui_add, - self.ui_edit, - self.ui_copy, - self.ui_delete, - ] + + # Base CRUD UIs + children = [self.ui_add, self.ui_edit, self.ui_copy, self.ui_delete] + + # Conditionally add ui io + if self.show_ui_io and self.ui_io is not None: + children.append(self.ui_io) + + self.stk_crud.children = children self.children = [self.hbx_title_description, self.vbx_widget] def _observe_order(self, on_change): @@ -466,6 +546,9 @@ def _grid_changed(self, onchange): self._update_value_from_grid() def _setview(self, onchange): + if self.buttonbar_grid.active == "io": + self.ui_io_initialised = True + self._ensure_ui_io_initialised() if self.buttonbar_grid.active is None: self.stk_crud.selected_index = None elif self.buttonbar_grid.active == "support": @@ -658,6 +741,24 @@ def _delete(self): print("delete error") traceback.print_exc() + # io + # -------------------------------------------------------------------------- + def _io(self): + ui = self._ensure_ui_io_initialised() + if ui is None: + self.buttonbar_grid.io.value = False + self.buttonbar_grid.message.value = ( + "⚠️ Import/Export unavailable for this configuration" + ) + return + try: + ui.value = self.value + except Exception as exc: + logger.warning("Unable to sync IO widget value: %s", exc) + if hasattr(ui, "traits") and "upload_status" in ui.traits(): + ui.upload_status = "None" + + # - @@ -706,6 +807,7 @@ class TestDataFrame(RootModel): close_crud_dialogue_on_action=False, global_decimal_places=1, column_width={"String": 400}, + show_ui_io=True ) editgrid.observe(lambda c: print("_value changed"), "_value") display(editgrid) @@ -812,7 +914,7 @@ class Test(RootModel): root: list[TestListCol] gr = EditGrid(Test, value=[{"li_col": ["a", "b"], "stringy": "string", "num": 23}]) - display(gr) + display(gr) # TODO: this needs fixing. not handling the list correctly. if __name__ == "__main__": import random @@ -823,6 +925,7 @@ class Test(RootModel): fn_patch=lambda v: v, fn_delete=lambda v: print(v), fn_copy=lambda v: print(v), + fn_io = lambda v: print("io") ) title = "The Wonderful Edit Grid Application" description = "Useful for all editing purposes whatever they may be 👍" @@ -878,4 +981,6 @@ class TestDataFrame(RootModel): display(editgrid) if __name__ == "__main__": - editgrid.transposed = True + editgrid.transposed = False + + diff --git a/src/ipyautoui/custom/editgridfile.py b/src/ipyautoui/custom/editgridfile.py new file mode 100644 index 00000000..037f4483 --- /dev/null +++ b/src/ipyautoui/custom/editgridfile.py @@ -0,0 +1,226 @@ +from ipyautoui.custom.editgrid import ( + EditGrid, + DataHandler, +) +from ipyautoui.custom.edittsv import Changes +import pathlib +import traitlets as tr +import json +from pydantic import BaseModel, RootModel, Field +import typing as ty +import ipywidgets as w +import functools + + +# + +# --- LOAD & SAVE HELPERS --- +def load_json(fpth: pathlib.Path = pathlib.Path("text.json")) -> list[dict]: + """Load JSON list data safely.""" + with fpth.open("r", encoding="utf-8") as f: + data = json.load(f) + if not isinstance(data, list): + raise ValueError("Expected list of dicts in JSON file.") + return data + + +def save_json(data: list[dict], fpth: pathlib.Path) -> pathlib.Path: + """Save JSON list data safely.""" + with fpth.open("w", encoding="utf-8") as f: + json.dump(data, f, indent=4) + return fpth + + +# --- DELETE --- +def delete_rows(primary_keys_list: list[str | int], primary_key_name, fpth: pathlib.Path) -> list[dict]: + """Delete rows from JSON based on keys in 'primary_keys' (list of strings or ints).""" + data = load_json(fpth) + + # Normalize all keys to strings for consistent comparison + delete_keys = [str(k) for k in primary_keys_list] + + # Keep only rows whose 'primary_key_name' is NOT in delete_ids + updated_data = [row for row in data if str(row.get(primary_key_name)) not in delete_keys] + + save_json(updated_data, fpth) + print(f"🗑️ Deleted rows with IDs: {delete_keys}") + return updated_data + + +# --- ADD --- +def add_rows(additions: list[dict], primary_key_name = "id", fpth: pathlib.Path = pathlib.Path("text.json")) -> list[dict]: + """Add new rows from 'insert' (dict-of-dicts form).""" + data = load_json(fpth) + maxId = max(data, key=lambda x:x[primary_key_name])[primary_key_name] + + for addition in additions: + new_addition = {} + new_addition[primary_key_name] = maxId + 1 + addition.pop(primary_key_name, None) + new_addition.update(addition) + data.append(new_addition) + + save_json(data, fpth) + print(f"➕ Added {len(additions)} new row(s)") + return data + + +# --- EDIT --- +def edit_rows(edits: dict[str | int, dict], primary_key_name, fpth: pathlib.Path) -> list[dict]: + """Update existing rows based on 'update' section.""" + data = load_json(fpth) + + for key, update_fields_dict in edits.items(): + for record in data: + if str(record.get(primary_key_name)) == str(key): + record.update(update_fields_dict) + + save_json(data, fpth) + print(f"✏️ Updated {len(edits)} row(s)") + return data + + +# --- COMBINED HANDLER --- +def handle_crud(primary_key_name, changes: Changes, fpth: pathlib.Path): + """Apply delete → insert → update in order.""" + if changes.deletions: + delete_rows(changes.deletions, primary_key_name, fpth) + if changes.additions: + add_rows(changes.additions, primary_key_name, fpth) + if changes.edits: + edit_rows(changes.edits, primary_key_name, fpth) +# --- COMBINED HANDLER --- + +def delete_row(value: dict, primary_key_name = "id", fpth: pathlib.Path = pathlib.Path("text.json")) -> list[dict]: + data = load_json(fpth) + deleted_id = value[primary_key_name] + # Keep only rows whose 'primary_key_name' is NOT delete_id + updated_data = [row for row in data if str(row.get(primary_key_name)) != str(deleted_id)] + save_json(updated_data, fpth) + return updated_data + +def edit_row(value: dict, primary_key_name = "id", fpth: pathlib.Path = pathlib.Path("text.json")) -> list[dict]: + data = load_json(fpth) + row_id = value[primary_key_name] + + # Update matching record + for record in data: + if str(record.get(primary_key_name)) == str(row_id): + # update all keys except 'primary_key_name' + record.update({k: v for k, v in value.items() if k != primary_key_name}) + break + + save_json(data, fpth) + return data + +def add_row(addition: dict, primary_key_name = "id", fpth: pathlib.Path = pathlib.Path("text.json")) -> list[dict]: + data = load_json(fpth) + maxId = max(data, key=lambda x:x[primary_key_name])[primary_key_name] + new_addition = {} + new_addition[primary_key_name] = maxId + 1 + addition.pop(primary_key_name, None) + new_addition.update(addition) + data.append(new_addition) + save_json(data, fpth) + print(f"➕ Added new row") + return data + +class EditGridFile(EditGrid): + primary_key_name = tr.Unicode(default_value="id") + fpth = tr.Instance(klass=pathlib.Path, allow_none=False) + + @tr.observe("fpth") + def update_handler(self, change): + self.datahandler.fn_get_all_data = functools.partial(load_json, fpth=self.fpth) + self.datahandler.fn_post = functools.partial(add_row, primary_key_name=self.primary_key_name, fpth=self.fpth) + self.datahandler.fn_patch = functools.partial(edit_row, primary_key_name=self.primary_key_name, fpth=self.fpth) + self.datahandler.fn_delete = functools.partial(delete_row, primary_key_name=self.primary_key_name, fpth=self.fpth) + self.datahandler.fn_copy = functools.partial(add_row, primary_key_name=self.primary_key_name, fpth=self.fpth) + self.datahandler.fn_io = functools.partial(self.handle_crud) + + self._set_datahandler(self.datahandler) + + def __init__( + self, + **kwargs, + ): + + datahandler = DataHandler( + fn_get_all_data=lambda v: print(v), + fn_post=lambda v: print(v), + fn_patch=lambda v: v, + fn_delete=lambda v: print(v), + fn_copy=lambda v: print(v), + fn_io = lambda v: print("io") + ) + super().__init__( + datahandler=datahandler, + warn_on_delete=True, + layout=w.Layout(height="800px"), + **kwargs, + ) + + if hasattr(self, "ui_io") and hasattr(self.ui_io, "primary_key_name"): + self.ui_io.primary_key_name = self.primary_key_name + + self.update_handler("") + + def fn_upload(self, value): + self.value=value + if self.ui_io is not None: + self.datahandler.fn_io(self.ui_io.changes) + + # --- HANDLERS --- + def handle_crud(self, changes: Changes): + handle_crud(self.ui_io.primary_key_name, changes, self.fpth) + + +if __name__ == "__main__": + json_path = pathlib.Path("../../..") / "tests" / "test_data" / "edit-grid-file-data.json" + with json_path.open('r', encoding='utf-8') as file: + data = json.load(file) + + # Test: EditGrid instance with multi-indexing. + AUTO_GRID_DEFAULT_VALUE = data + + class DataFrameCols(BaseModel): + id: int = Field(1, json_schema_extra=dict(column_width=80, section="a")) + string: str = Field( + "string", json_schema_extra=dict(column_width=400, section="a") + ) + integer: int = Field(1, json_schema_extra=dict(column_width=80, section="a")) + floater: float = Field( + None, json_schema_extra=dict(column_width=70, section="b") + ) + + class TestDataFrame(RootModel): + """a description of TestDataFrame""" + root: ty.List[DataFrameCols] = Field( + default=AUTO_GRID_DEFAULT_VALUE, + json_schema_extra=dict( + format="dataframe", datagrid_index_name=("section", "title") + ), + ) + + title = "Testing Crud Info Grid" + description = "Useful for all editing purposes whatever they may be 👍" + edit_grid_file = EditGridFile( + schema=TestDataFrame, + title=title, + description=description, + ui_add=None, + ui_edit=None, + show_copy_dialogue=False, + close_crud_dialogue_on_action=False, + global_decimal_places=1, + column_width={"String": 400}, + fpth=json_path, + show_ui_io=True + ) + display(edit_grid_file) + + + + +# - + + diff --git a/src/ipyautoui/custom/edittsv.py b/src/ipyautoui/custom/edittsv.py new file mode 100644 index 00000000..1584a09f --- /dev/null +++ b/src/ipyautoui/custom/edittsv.py @@ -0,0 +1,700 @@ +# + +import io +import csv +import json +import logging +import ipywidgets as w +import traitlets as tr +from IPython.display import Javascript +from pydantic import BaseModel +from markdown import markdown +from IPython.display import clear_output +from deepdiff import DeepDiff +from deepdiff.helper import COLORED_COMPACT_VIEW # COLORED_VIEW, +from ipyautoui.custom.filedownload import MakeFileAndDownload +from ipyautoui.custom.fileupload import TempFileUploadProcessor +from copy import deepcopy +import typing as ty +import xlsxdatagrid as xdg +from pathlib import Path + +from ipyautoui.constants import BUTTON_WIDTH_MIN + + +logger = logging.getLogger(__name__) + + +def data_to_tsv(data): + output = io.StringIO() + writer = csv.writer(output, delimiter="\t") + + if data: + headers = data[0].keys() + writer.writerow(headers) + for row in data: + writer.writerow([row[key] for key in headers]) + + tsv_string = output.getvalue() + return tsv_string + +def data_to_tsv_transposed(tsv_string): + input_io = io.StringIO(tsv_string) + reader = csv.reader(input_io, delimiter="\t") + + rows = list(reader) + if not rows: + return "" + + # Transpose using zip + transposed = list(zip(*rows)) + + output = io.StringIO() + writer = csv.writer(output, delimiter="\t") + for row in transposed: + writer.writerow(row) + + return output.getvalue() + +def header_from_tsv(tsv_string): + tsv_file = io.StringIO(tsv_string) + reader = csv.reader(tsv_file, delimiter="\t") + return next(reader) # Read the header row + + +def data_from_tsv(tsv_string): # TODO: validate_headings + """ + Reads TSV data from a string and returns it as a list of dictionaries. + Each dictionary represents a row, with column headers as keys. + + Args: + tsv_string (str): A string containing TSV data. + + Returns: + list: A list of dictionaries, where each dictionary represents a row + of data from the TSV string. + """ + data = [] + # Use io.StringIO to treat the string as a file-like object + tsv_file = io.StringIO(tsv_string) + reader = csv.reader(tsv_file, delimiter="\t") + header = next(reader) # Read the header row + for row in reader: + # Create a dictionary for each row, mapping header to row values + row_dict = dict(zip(header, row)) + data.append(row_dict) + return data + + +def markdown_error(e): + type, url, loc, input, msg = e["type"], e["url"], e["loc"], e["input"], e["msg"] + return f"❌ **[{type}]({url}) error**: loc(row,col)={loc} | input={input} | msg=*{msg}*" # TODO: link in new tab and style + + +class CopyToClipboard(w.VBox): + def __init__(self, **kwargs): + value = kwargs.get("value") + self.text = w.Textarea( + layout={"width": "800px", "height": "300px"} + ) # value=value, # TODO: why is % not working? + self.bn_copy = w.Button(icon="copy", layout={"width": BUTTON_WIDTH_MIN}) + self.vbx_bns = w.VBox(layout={"width": "48px"}) + self.hbx_main = w.HBox() + self.output = w.Output(layout=w.Layout(display="none")) + super().__init__(**kwargs) + + self._init_controls_c_to_c() + self._set_children() + + def _init_controls_c_to_c(self): + self.bn_copy.on_click(self._bn_copy) + + def _set_children(self): + self.vbx_bns.children = [self.bn_copy] + self.hbx_main.children = [self.vbx_bns, self.text, self.output] + self.children = [self.hbx_main] + + def _bn_copy(self, event): + copy_js = Javascript( + f"navigator.clipboard.writeText({json.dumps(self.text.value)})" + ) + self.output.clear_output() + self.output.append_display_data(copy_js) + +if __name__ == "__main__": + cc = CopyToClipboard() + display(cc) + + +def default_fn_upload(value): + print(value) + + +class EditTsv(CopyToClipboard): + _value = tr.List(value=None, trait=tr.Dict, allow_none=True) + model = tr.Type(klass=BaseModel) + errors = tr.List(value=[], trait=tr.Dict) + fn_upload = tr.Callable(default_value=default_fn_upload) + upload_status = tr.Enum( + values=["enabled", "disabled", "None"], allow_none=False, default_value="None" + ) + transposed = tr.Bool(default_value=False) + allow_download = tr.Bool(default_value=True) + exclude_metadata = tr.Bool(default_value=True) + header_depth = tr.Int(default_value=1) + disable_text_editing = tr.Bool(default_value=False) + + @tr.observe("upload_status") + def upload_status_onchange(self, on_change): + if self.upload_status == "disabled": + self.bn_upload_text.disabled = True + self.bn_upload_text.button_style = "danger" + elif self.upload_status == "enabled": + self.bn_upload_text.disabled = False + self.bn_upload_text.button_style = "success" + elif self.upload_status == "None": + self.bn_upload_text.disabled = True + self.bn_upload_text.button_style = "" + else: + raise ValueError( + "button style must be in list: ['enabled', 'disabled', 'None']" + ) + + @tr.observe("value") + def value_onchange(self, on_change): + self.text.value = self.get_tsv_data() + + @tr.observe("errors") + def errors_onchange(self, on_change): + self.vbx_errors.children = [ + w.HTML(markdown(markdown_error(e))) for e in self.errors + ] + if self.errors: + self.upload_status = "disabled" + else: + self.upload_status = "enabled" + + @tr.observe("transposed") + def transpose(self, on_change): + self.text.value = self.get_tsv_data() + + @tr.observe("allow_download") + def show_hide_download_btn(self, on_change): + if self.allow_download: + self.mfdld.layout.display = "" + else: + self.mfdld.layout.display = "None" + + @tr.observe("disable_text_editing") + def disable_text_editing_onchange(self, on_change): + if self.disable_text_editing: + self.text.disabled = True + else: + self.text.disabled = False + + def __init__(self, **kwargs): + self.vbx_errors = w.VBox() + self.bn_upload_text = w.Button( + icon="save", disabled=True, layout={"width": BUTTON_WIDTH_MIN} + ) + self.mfdld = MakeFileAndDownload(fn_create_file=self.create_file) + super().__init__(**kwargs) + self.value = kwargs.get("value") + + self._init_contols() + + def _set_children(self): + self.vbx_bns.children = [self.bn_copy, self.bn_upload_text, self.mfdld] + self.hbx_main.children = [self.vbx_bns, self.text, self.output] + self.children = [self.hbx_main] + + @property + def value(self): + return self._value + + @value.setter + def value(self, value): + data = self.model.model_validate(value).model_dump(mode="json", by_alias=True) if value else [] + self._value = data + self.text.value = self.get_tsv_data() + + def get_tsv_data(self): + if self.transposed: + return data_to_tsv_transposed(data_to_tsv(self.value)) + else: + return data_to_tsv(self.value) + + def _init_contols(self): + self.text.observe(self._text, "value") + self.bn_upload_text.on_click(self._bn_upload_text) + + def _bn_upload_text(self, on_click): + return self.fn_upload(self.value) + + def create_file(self): + pydantic_obj = self.model(self.value) + fpth = xdg.xdg_from_pydantic_object( + pydantic_obj, + is_transposed=self.transposed, + exclude_metadata=self.exclude_metadata, + )[0] + return fpth + + def _text(self, change): + value = [] + if self.text.value: + value, self.errors = xdg.read_csv_string( + self.text.value, + is_transposed=self.transposed, + model=self.model, + delimiter="\t", + header_depth=self.header_depth) + if self.errors: + self.vbx_errors.children = [ + w.HTML(markdown(markdown_error(e))) for e in self.errors + ] + else: + self._value = value + self.upload_status = "enabled" + + @property + def tsv_data(self): # TODO: ensure header row unchanged + return xdg.read_csv_string( + self.text.value, + is_transposed=self.transposed, + model=self.model, + delimiter="\t", + header_depth=self.header_depth) + + @property + def pydantic_object(self): + return self.model(self.value) + +if __name__ == "__main__": + from pydantic import RootModel + from ipyautoui.demo_schemas import EditableGrid + + # Test: EditGrid instance with multi-indexing. + AUTO_GRID_DEFAULT_VALUE = [ + { + "id": 3, + "string": "apples", + "integer": 5, + "floater": 2.0, + }, + { + "id": 4, + "string": "bananas", + "integer": 2, + "floater": 3.5, + }, + { + "id": 5, + "string": "oranges", + "integer": 2, + "floater": 4.0, + }, + { + "id": 6, + "string": "pineapples", + "integer": 1, + "floater": 7.0 + }, + ] + # AUTO_GRID_DEFAULT_VALUE = AUTO_GRID_DEFAULT_VALUE * 4 + + def fn_upload(value): + print(value[0].keys()) + + edit_tsv = EditTsv( + value=AUTO_GRID_DEFAULT_VALUE, model=EditableGrid, fn_upload=fn_upload, transposed=False, allow_download = True + ) + display(edit_tsv) +# - + + +if __name__ == "__main__": + # edit_tsv.transposed = True + # edit_tsv.allow_download = False + print(edit_tsv.pydantic_object.root) + print(edit_tsv.model.model_json_schema().get("title", edit_tsv.model.__name__)) + +if __name__ == "__main__": + # example of how to use DeepDiff + from deepdiff import DeepDiff + from deepdiff.helper import COLORED_VIEW, COLORED_COMPACT_VIEW + + t1 = [ + { + "name": "John", + "age": 30, + "scores": [1, 2, 3], + "address": {"city": "New York", "zip": "10001"}, + }, + { + "name": "John", + "age": 30, + "scores": [1, 2, 3], + "address": {"city": "New York", "zip": "10001"}, + }, + ] + t2 = [ + { + "name": "John", + "age": 31, + "scores": [1, 2, 4], + "address": {"city": "Boston", "zip": "10001"}, + "new": "value", + }, + { + "name": "John", + "age": 30, + "scores": [1, 2, 3], + "address": {"city": "New York", "zip": "10001"}, + }, + ] + + diff = DeepDiff(t1, t2, view=COLORED_COMPACT_VIEW) + print(diff) + +if __name__ == "__main__": + import pandas as pd + pd.DataFrame.from_dict({"a": [12, 3], "b": ["ad", "daf"]}).set_index("a") + + +if __name__ == "__main__": + # NOTE: maybe useful later... + display( + w.HBox( + [ + w.Button(icon="file-import"), + w.Button(icon="file-export"), + ] + ) + ) + +if __name__ == "__main__": + from deepdiff import DeepDiff + d1 = { + 3: { + "string": "important string 3", + "integer": 3, + "floater": 17.5 + }, + 5: { + "string": "str", + "integer": 6, + "floater": 7.0 + } + } + + d2 = { + 3: { + "string": "important string 3", + "integer": 3, + "floater": 18.0 + }, + 5: { + "string": "str", + "integer": 6, + "floater": 8.5 + } + } + + ddiff = DeepDiff(d1, d2, ignore_order=True) + + display(ddiff) + + + +class DisplayDeepDiff(w.VBox): + value = tr.Dict(value=None, trait=tr.Dict, allow_none=True) + new_value = tr.Dict(value=None, trait=tr.Dict, allow_none=True) + diff = tr.Instance(value=None, klass=DeepDiff, allow_none=True) + + def __init__(self, **kwargs): + self.out = w.Output(layout=w.Layout(width="400px")) # Explicit width value NEEDED to render properly on voila. Otherwise, it takes up all the width and nothing besides it is visible on screen. + super().__init__(**kwargs) + self.children = [w.HTML('Additions in Green, ' + 'Deletions in Red'), self.out] + + @tr.observe("new_value") + def _update_diff(self, on_change): + if self.value is not None and self.new_value is not None: + self.diff = DeepDiff(self.value, self.new_value, view=COLORED_COMPACT_VIEW, threshold_to_diff_deeper=0) + + @tr.observe("diff") + def _display_diff(self, on_change): + with self.out: + clear_output() + print(self.diff) + + +class Changes(BaseModel): + deletions: list[ty.Union[str, int]] + edits: dict[ty.Union[str, int], dict] + additions: list[dict] + edited_rows: dict[ty.Union[str, int], dict] + + +class EditTsvWithDiff(EditTsv): + primary_key_name = tr.Unicode() + prev_value = tr.List(value=None, trait=tr.Dict, allow_none=True) + changes = Changes( + deletions=[], + edits={}, + additions=[], + edited_rows={} + ) + # add ui functionality to use deepdiff to view changes between new_value and _value and prompt the user to accept changes before proceeding + + @property + def value(self): + return self._value + + @value.setter + def value(self, value): + data = self.model.model_validate(value).model_dump(mode="json", by_alias=True) if value else [] + self._value = data + """Code added to trigger manual validation if needed (text new value is same as previous text value - In that case,text obsever fn won't be triggered automatically)""" + trigger_manual_validation = False + if self.text.value and self.text.value == self.get_tsv_data(): + trigger_manual_validation = True + + self.text.value = self.get_tsv_data() + ### Trigger manual validation + if trigger_manual_validation: + self._text(None) + self.prev_value = deepcopy(self.value or []) + + def __init__(self, **kwargs): + value = kwargs.get("value") + if "value" in kwargs: + kwargs.pop("value") + self.ddiff = DisplayDeepDiff(layout=w.Layout(display="None")) + self.bn_confirmation = w.Button( + icon="check", disabled=True, layout={"width": BUTTON_WIDTH_MIN, "display": "None"} + ) + self.bn_cross = w.Button( + icon="ban", disabled=True, layout={"width": BUTTON_WIDTH_MIN, "display": "None"} + ) + + self.ddiff.observe(self._update_changes, "diff") + + self.bn_confirmation.on_click(self._bn_check_upload) + self.bn_cross.on_click(self._bn_cross_clicked) + super().__init__(**kwargs) + self.value = value + self.upload_status = "None" + + def _update_changes(self, change): + """Called when self.ddiff.diff changes""" + if change["new"] is not None: + self.changes = self.deepdiff_to_crud(change["new"]) + + def _set_children(self): + if self.allow_download: + self.vbx_bns.children = [self.bn_copy, self.bn_upload_text, self.mfdld, self.bn_confirmation, self.bn_cross] + else: + self.vbx_bns.children = [self.bn_copy, self.bn_upload_text, self.bn_confirmation, self.bn_cross] + self.hbx_main.children = [self.vbx_bns, self.text, self.ddiff, self.output] + self.children = [self.vbx_errors, self.hbx_main] + + + def _bn_upload_text(self, on_click): + # hide grid/errors + self.text.layout.display = "None" + + # Hide upload button and show check button + self.bn_upload_text.layout.display = "None" + self.bn_confirmation.layout.display = "" + self.bn_confirmation.disabled = False + self.bn_confirmation.button_style = "success" + self.bn_cross.layout.display = "" + self.bn_cross.disabled = False + self.bn_cross.button_style = "danger" + + # Show DeepDiff widget + self.ddiff.layout.display = "" + + # update deepdiff with original vs edited values + pk = getattr(self, "primary_key_name", None) + + if not pk: + # no primary key given → use index + self.ddiff.value = { + i: v for i, v in enumerate(self.prev_value) + } + self.ddiff.new_value = { + i: v for i, v in enumerate(self.value) + } + else: + # primary key given → use it, excluding the pk field in the nested dict + self.ddiff.value = { + v[pk]: {k: val for k, val in v.items() if k != pk} + for v in self.prev_value + } + self.ddiff.new_value = { + v[pk]: {k: val for k, val in v.items() if k != pk} + for v in self.value + } + + def _bn_check_upload(self, onclick): + self.prev_value = deepcopy(self.value) + self.show_upload_button_and_hide_deepdiff() + + self.fn_upload(self.value) + self.reset_deep_diff() + + def _bn_cross_clicked(self, onclick): + self.show_upload_button_and_hide_deepdiff(upload_disabled=False) + + def show_upload_button_and_hide_deepdiff(self, upload_disabled=True): + # Hide check button and show upload button as well as text area + self.bn_upload_text.layout.display = "" + if upload_disabled: + self.upload_status = "None" + self.bn_confirmation.layout.display = "None" + self.bn_confirmation.disabled = True + self.bn_cross.layout.display = "None" + self.bn_cross.disabled = True + self.text.layout.display = "" + self.ddiff.layout.display = "None" + + def reset_deep_diff(self): + self.ddiff.diff = None + self.changes = Changes( + deletions=[], + edits={}, + additions=[], + edited_rows={} + ) + + def deepdiff_to_crud(self, diff: DeepDiff): + changes = Changes( + deletions=[], + edits={}, + additions=[], + edited_rows={}, + ) + + # Additions + if "dictionary_item_added" in diff: + for delta in diff["dictionary_item_added"]: + changes.additions.append(getattr(delta, "t2", None)) + + # Deletions + if "dictionary_item_removed" in diff: + for delta in diff["dictionary_item_removed"]: + path_list = delta.path(output_format="list") + primary_key = str(path_list[0]) # first key (primary key) + changes.deletions.append(primary_key) + + + if "values_changed" in diff: + for delta in diff["values_changed"]: + path_list = delta.path(output_format="list") + primary_key = str(path_list[0]) # first key (primary key) + field = path_list[-1] # last key (field name) + + if primary_key not in changes.edits: + changes.edits[primary_key] = {} + + changes.edits[primary_key][field] = delta.t2 + + if "type_changes" in diff: + for delta in diff["type_changes"]: + path_list = delta.path(output_format="list") + primary_key = str(path_list[0]) # first key (primary key) + field = path_list[-1] # last key (field name) + + if primary_key not in changes.edits: + changes.edits[primary_key] = {} + + changes.edits[primary_key][field] = delta.t2 + + #Adding edited_rows (all the fields included for edited rows) + if len(changes.edits): #TODO: use index instead of pk when pk is none + pk = getattr(self, "primary_key_name", None) # Confirm that primary key exists + if pk: + for primary_key in changes.edits.keys(): + for row in self.value: + if str(row.get(pk)) == str(primary_key): + changes.edited_rows[primary_key] = row + break + else: + rows_by_index = {str(index): row for index, row in enumerate(self.value)} + for index in changes.edits.keys(): + if index in rows_by_index: + changes.edited_rows[index] = rows_by_index[index] + + return changes + + +if __name__ == "__main__": + edit_tsv_w_diff = EditTsvWithDiff(value=AUTO_GRID_DEFAULT_VALUE, model=EditableGrid, transposed = False, primary_key_name="id") + display(edit_tsv_w_diff) + +if __name__ == "__main__": + display(edit_tsv_w_diff.value) + display(edit_tsv_w_diff.text.value) + + +class EditTsvFileUpload(EditTsvWithDiff): + """ + A widget for editing and uploading Excel files (e.g. .xlsx). + - Inherits full diffing and validation logic from EditTsvWithDiff. + - Disables manual text editing. + - Adds an upload button for Excel files. + """ + + def __init__(self, **kwargs): + # Ensure text editing is disabled by default + kwargs.setdefault("disable_text_editing", True) + + # Create uploader before parent init so it's available during layout build + self.file_uploader = TempFileUploadProcessor( + fn_process=self._process_uploaded_file, + allowed_file_type=".xlsx", + ) + + # Initialize base class + super().__init__(**kwargs) + self.last_upload_metadata = None + + def _set_children(self): + super()._set_children() + buttons = list(self.vbx_bns.children) + if self.file_uploader not in buttons: + insert_at = 1 if buttons else 0 + buttons.insert(insert_at, self.file_uploader) + self.vbx_bns.children = tuple(buttons) + + def _text(self, change): + pass + + def _process_uploaded_file(self, path: Path): + """Handle Excel file upload and load into the widget.""" + if path is None: + return + + path = Path(path) + try: + data, errors = xdg.read_excel( + path, + is_transposed=self.transposed, + header_depth=self.header_depth, + model=self.model, + ) + except Exception: + logger.exception("Failed to read uploaded Excel file") + self.upload_status = "disabled" + return + + self.errors = errors or [] + if self.errors: + self.upload_status = "disabled" + return + + self._value = data + self.upload_status = "enabled" + self.text.value = self.get_tsv_data() diff --git a/src/ipyautoui/custom/edittsv_with_diff_and_key_mapping.py b/src/ipyautoui/custom/edittsv_with_diff_and_key_mapping.py new file mode 100644 index 00000000..f3f75b78 --- /dev/null +++ b/src/ipyautoui/custom/edittsv_with_diff_and_key_mapping.py @@ -0,0 +1,192 @@ +from deepdiff import DeepDiff +from pydantic import RootModel, create_model +from ipyautoui.custom.edittsv import Changes, EditTsvWithDiff +import traitlets as tr +import typing as ty + +class EditTsvWithDiffAndKeyMapping(EditTsvWithDiff): + primary_key_name = tr.List(tr.Unicode(), + default_value=None, + allow_none=True, + ) + exclude_fields_from_model = tr.List(tr.Unicode(), default_value=[]) + + def __init__(self, **kwargs): + super().__init__(**kwargs) + if self.exclude_fields_from_model: + inner_model = self.model.model_fields['root'].annotation.__args__[0] + # Keep alias names in the new model + fields = {} + for name, field in inner_model.model_fields.items(): + converted_name = field.alias or name + if converted_name not in self.exclude_fields_from_model: + alias = field.alias or name + fields[alias] = (field.annotation, field.default) + + stripped_inner = create_model( + inner_model.__name__, + **fields, + ) + self.model = type( + self.model.__name__, + (RootModel[list[stripped_inner]],), + {}, + ) + + def _bn_upload_text(self, on_click): + # hide grid/errors + self.text.layout.display = "None" + + # Hide upload button and show check button + self.bn_upload_text.layout.display = "None" + self.bn_confirmation.layout.display = "" + self.bn_confirmation.disabled = False + self.bn_confirmation.button_style = "success" + self.bn_cross.layout.display = "" + self.bn_cross.disabled = False + self.bn_cross.button_style = "danger" + + # Show DeepDiff widget + self.ddiff.layout.display = "" + + def build_diff_map(records): + result = {} + for i, v in enumerate(records or []): + # --- Determine key --- + if self.primary_key_name: + # Replace None with "" and filter out empty parts + parts = [str(v.get(f) or "") for f in self.primary_key_name] + non_empty_parts = [p for p in parts if p] # remove empty strings + key = "-".join(non_empty_parts) + # --- Normalize None → "" for values --- + clean_row = { + k: ("" if val is None else val) + for k, val in v.items() + } + result[key] = clean_row + return result + + self.ddiff.value = build_diff_map(self.prev_value or []) + self.ddiff.new_value = build_diff_map(self.value or []) + + def deepdiff_to_crud(self, diff: DeepDiff): + """Convert DeepDiff result into CRUD Changes.""" + changes = Changes( + deletions=[], + edits={}, + additions=[], + edited_rows={} + ) + + # Helper for consistent key resolution + def key_from_path(path_list): + key = path_list[0] + if isinstance(key, (list, tuple)): + key = "::".join(map(str, key)) + return str(key) + + # Additions + if "dictionary_item_added" in diff: + for delta in diff["dictionary_item_added"]: + changes.additions.append(getattr(delta, "t2", None)) + + # Deletions + if "dictionary_item_removed" in diff: + for delta in diff["dictionary_item_removed"]: + path_list = delta.path(output_format="list") + primary_key = key_from_path(path_list) + changes.deletions.append(primary_key) + + # Edits / type changes + for category in ("values_changed", "type_changes"): + if category not in diff: + continue + for delta in diff[category]: + path_list = delta.path(output_format="list") + primary_key = key_from_path(path_list) + field = path_list[-1] + if primary_key not in changes.edits: + changes.edits[primary_key] = {} + changes.edits[primary_key][field] = delta.t2 + + #Adding edited_rows (all the fields included for edited rows) + if len(changes.edits): + if self.primary_key_name: + # Composite key mode + for comp_key in changes.edits.keys(): + for row in self.value: + row_key = self._composite_key_from_row(row) + if row_key and str(row_key) == str(comp_key): + changes.edited_rows[comp_key] = row + break + + return changes + + def _composite_key_from_row(self, row: dict) -> str: + """Build a composite key string from the configured primary key fields.""" + if not row: + return "" + fields = getattr(self, "primary_key_name", None) or [] + parts = [] + for field in fields: + value = row.get(field) + if value is None: + continue + value_str = str(value) + if value_str: + parts.append(value_str) + return "-".join(parts) + + def _composite_key_for_id(self, Id: ty.Union[int, str], key_to_id_map: dict[str, int]) -> str: # noqa: N803 + try: + target_id = int(Id) + except (TypeError, ValueError): + return "" + + for composite_key, mapped_id in key_to_id_map.items(): + try: + if int(mapped_id) == target_id: + return composite_key + except (TypeError, ValueError): + continue + return "" + + def _build_composite_key_to_id_map( + self, data: ty.Union[list[dict], tuple[dict, ...]] + ) -> dict[str, int]: + """Build mapping from composite key to the actual database Id.""" + mapping = {} + for row in data: + key = self._composite_key_from_row(row) + if "Id" in row and key: + mapping[key] = row["Id"] + return mapping + + def _resolve_composite_to_ids(self, changes: Changes, key_to_id_map: dict[str, int]) -> Changes: + """Translate composite keys from Changes to actual database Ids.""" + resolved = Changes( + deletions=[], + edits={}, + additions=changes.additions, + edited_rows={} + ) + + # Resolve deletions + for comp_key in changes.deletions: + id_ = key_to_id_map.get(comp_key) + if id_ is not None: + resolved.deletions.append(id_) + + # Resolve edits + for comp_key, edit in changes.edits.items(): + id_ = key_to_id_map.get(comp_key) + if id_ is not None: + resolved.edits[id_] = edit + + # --- Resolve edited_rows --- + for comp_key, row in changes.edited_rows.items(): + id_ = key_to_id_map.get(comp_key) + if id_ is not None: + resolved.edited_rows[id_] = row + + return resolved \ No newline at end of file diff --git a/src/ipyautoui/custom/filedownload.py b/src/ipyautoui/custom/filedownload.py index 45f3d731..c2f48167 100644 --- a/src/ipyautoui/custom/filedownload.py +++ b/src/ipyautoui/custom/filedownload.py @@ -1,8 +1,6 @@ - """file download widget""" -# + import ipywidgets as w import traitlets as tr import pathlib @@ -88,27 +86,52 @@ def obs_fpth(self, on_change): self.reload() def reload(self): - if self.value.is_file(): + if self.value is not None and self.value.is_file(): self.content_b64 = load_file_to_b64(self.value) self.bn_download.disabled = False else: - self.bn_download.disabled = True - self.bn_download.tooltip = f"download file: {self.value.name}" + self.bn_download.disabled = False + if self.value is None: + name = "None" + else: + name = self.value.name + self.bn_download.tooltip = f"download file: {name}" def __init__(self, **kwargs): super().__init__(**kwargs) - self.bn_download.disabled = True + self.reload() def trigger_download(self): + self.reload() trigger_download(self.content_b64, self.filename, self.output) if __name__ == "__main__": fpth = pathlib.Path("../../../tests/filetypes/eg_pdf.pdf") - fd = FileDownload(value=fpth) + fd = FileDownload(value =fpth) display(fd) +# + +class MakeFileAndDownload(FileDownload): + fn_create_file = tr.Callable() + def __init__(self, **kwargs): + super().__init__(**kwargs) + + def _on_bn_download_clicked(self, on_click): + p = self.fn_create_file() + self.value = p + self.trigger_download() + +def create_file(): + p = pathlib.Path("test.txt") + p.write_text("asdfsadfas") + return p +if __name__ == "__main__": + mfdld = MakeFileAndDownload(fn_create_file=create_file) + display(mfdld) + + # + def get_filename(): return datetime.now().strftime("%Y-%m-%dT%H%M") + "-file-dump.zip" @@ -204,4 +227,3 @@ def download_on_click(self, on_click): title="Download Files", ) display(sd) -# - diff --git a/src/ipyautoui/custom/fileupload.py b/src/ipyautoui/custom/fileupload.py index 852facc9..560666d7 100644 --- a/src/ipyautoui/custom/fileupload.py +++ b/src/ipyautoui/custom/fileupload.py @@ -11,6 +11,7 @@ import traitlets as tr import logging import time +import tempfile from ipyautoui.constants import DELETE_BUTTON_KWARGS from ipyautoui._utils import getuser, trait_order @@ -201,6 +202,55 @@ def add_file(self, paths: list[str]): fupld = FileUploadToDir(value="IMG_0688.jpg") display(fupld) # + +class TempFileUploadProcessor(FileUploadToDir): + """A wrapper widget that uploads a file, processes it via callback, and deletes it after use.""" + fn_process = tr.Callable(default_value=None, allow_none=True) + allowed_file_type = tr.Unicode(default_value="", allow_none=True) + + def __init__(self, **kwargs): + self.fn_process = kwargs.pop("fn_process", None) + allowed_file_type = kwargs.pop("allowed_file_type", None) + super().__init__(**kwargs) + self.children = [w.HBox([self.bn_delete, self.upld])] + if allowed_file_type is not None: + self.allowed_file_type = allowed_file_type + self._apply_allowed_file_type() + + def _upld(self, on_change): + """Override upload handler to use temp directory and auto-delete.""" + if not self.upld.value: + return + + with tempfile.TemporaryDirectory() as tmpdir: + tmp_path = pathlib.Path(tmpdir) + + paths = add_files(self.upld.value, fdir=tmp_path) + + # Run callback on uploaded file(s) + if self.fn_process is not None: + try: + for path in paths: + self.fn_process(path) + except Exception as e: + logger.exception("Processing failed", exc_info=e) + + self.upld.value = () + + def _apply_allowed_file_type(self): + """Sync the trait with the widget accept attribute.""" + if hasattr(self, "upld"): + self.upld.accept = self.allowed_file_type or "" + + @tr.observe("allowed_file_type") + def _obs_allowed_file_type(self, change): + self._apply_allowed_file_type() + +if __name__ == "__main__": + def process_file_callback(path: pathlib.Path): + print(f"Processing uploaded file: {path}") + upload_widget = TempFileUploadProcessor(fn_process=process_file_callback) + display(upload_widget) +# + MAP_FILEUPLOAD_TYPE = {True: VuetifyFileUplad, False: w.FileUpload} MAP_CLEARFILEUPLOAD = { True: lambda wgdt: wgdt.upld.clear(), diff --git a/src/ipyautoui/custom/showopenurl.py b/src/ipyautoui/custom/showopenurl.py index f8651df1..bab092bb 100644 --- a/src/ipyautoui/custom/showopenurl.py +++ b/src/ipyautoui/custom/showopenurl.py @@ -33,6 +33,7 @@ def _obs_url_launch(self, change): self.btn_launch.layout.display = "None" else: self.btn_launch.layout.display = "" + self.display_out("click") @tr.observe("description_launch") def _obs_description_launch(self, change): diff --git a/src/ipyautoui/demo_schemas/__init__.py b/src/ipyautoui/demo_schemas/__init__.py index c0fea8d6..30df33d4 100644 --- a/src/ipyautoui/demo_schemas/__init__.py +++ b/src/ipyautoui/demo_schemas/__init__.py @@ -7,6 +7,7 @@ from ipyautoui.demo_schemas.nested import Nested from ipyautoui.demo_schemas.null_and_required import NullAndRequired from ipyautoui.demo_schemas.editable_datagrid import EditableGrid +from ipyautoui.demo_schemas.editable_datagrid_transposed import EditableGridTransposed from ipyautoui.demo_schemas.editable_datagrid_with_nullable import ( EditableGridWithNullable, ) diff --git a/src/ipyautoui/demo_schemas/editable_datagrid.py b/src/ipyautoui/demo_schemas/editable_datagrid.py index b0005268..6a4cb973 100644 --- a/src/ipyautoui/demo_schemas/editable_datagrid.py +++ b/src/ipyautoui/demo_schemas/editable_datagrid.py @@ -4,6 +4,7 @@ DATAGRID_TEST_VALUE = [ { + "id": 1, "string": "how long", "integer": 1, "floater": 3.14, @@ -13,6 +14,7 @@ class DataFrameCols(BaseModel): + id: int = Field(1) string: str = Field("string", json_schema_extra=dict(column_width=200)) integer: int = Field(1) floater: float = Field(3.1415, json_schema_extra=dict(column_width=70)) diff --git a/src/ipyautoui/demo_schemas/editable_datagrid_transposed.py b/src/ipyautoui/demo_schemas/editable_datagrid_transposed.py new file mode 100644 index 00000000..08127697 --- /dev/null +++ b/src/ipyautoui/demo_schemas/editable_datagrid_transposed.py @@ -0,0 +1,34 @@ +from ipyautoui.basemodel import BaseModel +from pydantic import Field, RootModel, ConfigDict +import typing as ty + +DATAGRID_TEST_VALUE = [ + { + "string": "how long", + "integer": 1, + "floater": 3.14, + "something_else": 324, + }, +] + + +class DataFrameCols(BaseModel): + string: str = Field("string", json_schema_extra=dict(column_width=200)) + integer: int = Field(1) + floater: float = Field(3.1415, json_schema_extra=dict(column_width=70)) + something_else: float = Field(324, json_schema_extra=dict(column_width=100)) + + +class EditableGridTransposed(RootModel): + root: ty.List[DataFrameCols] + model_config = ConfigDict( + json_schema_extra=dict( + default=DATAGRID_TEST_VALUE, + # default_factory=lambda: DATAGRID_TEST_VALUE, # TODO: AutoUi isn't getting data when set using default_factory. make this work! + format="DataFrame", + warn_on_delete=True, # TODO: this isn't being passed + global_decimal_places=2, + allow_download = False, + transposed=True, + ) + ) diff --git a/src/ipyautoui/watch_validate.py b/src/ipyautoui/watch_validate.py index 448d9994..bb9639d3 100644 --- a/src/ipyautoui/watch_validate.py +++ b/src/ipyautoui/watch_validate.py @@ -12,7 +12,7 @@ def pydantic_validate(model: BaseModel, value): - return model.model_validate(value).model_dump(mode="json") + return model.model_validate(value).model_dump(mode="json", by_alias=True) class _WatchSilent(tr.HasTraits): # TODO: contains context manager for silencing traits diff --git a/tests/custom/test_edittsv.py b/tests/custom/test_edittsv.py new file mode 100644 index 00000000..fae0882c --- /dev/null +++ b/tests/custom/test_edittsv.py @@ -0,0 +1,216 @@ +import numpy as np +from ipyautoui.custom.edittsv import DisplayDeepDiff +from ipyautoui.custom.edittsv import EditTsvWithDiff +from ipyautoui.demo_schemas import EditableGrid +from ipyautoui.custom.edittsv import data_to_tsv +from deepdiff import DeepDiff + +def test_DisplayDeepDiff(): + d1 = { + 1: {"name": "John", "age": 30, "scores": [1, 2, 3], "address": {"city": "New York", "zip": "10001"}}, + 2: {"name": "John", "age": 30, "scores": [1, 2, 3], "address": {"city": "New York", "zip": "10001"}} + } + + d2 = { + 1: {"name": "John", "age": 31, "scores": [1, 2, 4], "address": {"city": "Boston", "zip": "10001"}, "new": "value"}, + 2: {"name": "John", "age": 30, "scores": [1, 2, 3], "address": {"city": "New York", "zip": "10001"}} + } + + ddiff = DisplayDeepDiff() + assert ddiff.diff is None + assert ddiff is not None + + ddiff.value = d1 + ddiff.new_value = d2 + + assert ddiff.diff is not None + +def test_deepdiff_replaces_whole_list_items(): + ''' + Edge case 1: When a property from all objects is changed, deepdiff thinks the whole object has been changed rather than just the property that was changed. + In this case, only the floater value has been changed, but deepdiff thinks the whole object was changed. + ''' + d1 = [ + { + "id": 3, + "string": "important string 3", + "integer": 3, + "floater": 17.5 + }, + { + "id": 5, + "string": "str", + "integer": 6, + "floater": 7.0 + } + ] + d2 = [ + { + "id": 3, + "string": "important string 3", + "integer": 3, + "floater": 18.0 + }, + { + "id": 5, + "string": "str", + "integer": 6, + "floater": 8.5 + } + ] + + ddiff = DeepDiff(d1, d2, ignore_order=True) + + assert ddiff is not None + + assert "values_changed" in ddiff or "iterable_item_added" in ddiff + + diff_str = str(ddiff) + assert "floater" not in diff_str or "root[0]['floater']" not in diff_str, \ + "DeepDiff detected key-level change — expected it to miss this granularity." + +def test_list_add_remove_edge_case(): + ''' + Edge case 2: DeepDiff treats added/removed list elements as edits instead of separate add/remove events + when comparing lists of dicts without unique identifiers. + ''' + + d1 = [ + {"id": 1, "value": "line A"}, + {"id": 2, "value": "line B"}, + ] + + d2 = [ + {"id": 3, "value": "line C"}, # new line added + {"id": 2, "value": "line B"}, # one line retained + ] + + ddiff = DeepDiff(d1, d2, ignore_order=True) + + assert ddiff is not None + + # DeepDiff likely interprets this as a change of the first element (index 0) + # rather than a removal of {'id': 1, 'value': 'line A'} and addition of {'id': 3, 'value': 'line C'} + + assert "values_changed" in ddiff + +def get_edit_tsv_with_diff(): + AUTO_GRID_DEFAULT_VALUE = [ + { + "id": 1, + "string": "important string", + "integer": 1, + "floater": 3.14, + }, + ] + AUTO_GRID_DEFAULT_VALUE = AUTO_GRID_DEFAULT_VALUE * 4 + + updatedData = [{ + "id": 1, + "string": "important string", + "integer": 2, + "floater": 3.24, + }] + edit_tsv_with_diff = EditTsvWithDiff(value=AUTO_GRID_DEFAULT_VALUE, model=EditableGrid, transposed = False, primary_key_name="id") + + return updatedData, edit_tsv_with_diff + +def check_objects_initialised(edit_tsv_with_diff): + assert edit_tsv_with_diff.ddiff is not None + assert edit_tsv_with_diff.bn_confirmation is not None + assert edit_tsv_with_diff.bn_cross is not None + assert edit_tsv_with_diff.text is not None + +def check_initial_editing_mode(edit_tsv_with_diff): + assert edit_tsv_with_diff.bn_confirmation.layout.display == "None" + assert edit_tsv_with_diff.bn_cross.layout.display == "None" + assert edit_tsv_with_diff.ddiff.layout.display == "None" + assert edit_tsv_with_diff.text.layout.display is None + assert edit_tsv_with_diff.bn_upload_text.layout.display is None + +def check_diff_mode(edit_tsv_with_diff): + assert edit_tsv_with_diff.bn_upload_text.layout.display == "None" + assert edit_tsv_with_diff.bn_confirmation.layout.display == "" + assert edit_tsv_with_diff.bn_cross.layout.display == "" + assert edit_tsv_with_diff.ddiff.layout.display == "" + +def check_editing_mode(edit_tsv_with_diff): + assert edit_tsv_with_diff.bn_confirmation.layout.display == "None" + assert edit_tsv_with_diff.bn_cross.layout.display == "None" + assert edit_tsv_with_diff.ddiff.layout.display == "None" + assert edit_tsv_with_diff.text.layout.display == "" + assert edit_tsv_with_diff.bn_upload_text.layout.display == "" + +def test_edit_tsv_with_diff_confirmation(): + updatedData, edit_tsv_with_diff = get_edit_tsv_with_diff() + + assert edit_tsv_with_diff is not None + + check_objects_initialised(edit_tsv_with_diff) + check_initial_editing_mode(edit_tsv_with_diff) + + assert edit_tsv_with_diff.value == edit_tsv_with_diff.prev_value + + edit_tsv_with_diff.text.value = data_to_tsv(updatedData) + assert edit_tsv_with_diff.bn_upload_text.disabled is False + + edit_tsv_with_diff.bn_upload_text.click() + check_diff_mode(edit_tsv_with_diff) + + assert edit_tsv_with_diff.value != edit_tsv_with_diff.prev_value + + edit_tsv_with_diff.bn_confirmation.click() + assert edit_tsv_with_diff.value == edit_tsv_with_diff.prev_value + + check_editing_mode(edit_tsv_with_diff) + + assert edit_tsv_with_diff.bn_upload_text.disabled is True + + +def test_edit_tsv_with_diff_rejection(): + updatedData, edit_tsv_with_diff = get_edit_tsv_with_diff() + + assert edit_tsv_with_diff is not None + + check_objects_initialised(edit_tsv_with_diff) + check_initial_editing_mode(edit_tsv_with_diff) + + assert edit_tsv_with_diff.value == edit_tsv_with_diff.prev_value + + edit_tsv_with_diff.text.value = data_to_tsv(updatedData) + assert edit_tsv_with_diff.bn_upload_text.disabled is False + + edit_tsv_with_diff.bn_upload_text.click() + check_diff_mode(edit_tsv_with_diff) + + assert edit_tsv_with_diff.value != edit_tsv_with_diff.prev_value + + edit_tsv_with_diff.bn_cross.click() + assert edit_tsv_with_diff.value != updatedData + + check_editing_mode(edit_tsv_with_diff) + + assert edit_tsv_with_diff.bn_upload_text.disabled is False + +def test_edit_tsv_blank_from_empty_volume_reference(): + """Test that an edittsv becomes blank when a property is nan / None.""" + AUTO_GRID_DEFAULT_VALUE = [ + { + "id": 1, + "string": "important string", + "integer": 1, + "floater": 3.14, + }, + ] + edit_tsv_with_diff = EditTsvWithDiff(value=AUTO_GRID_DEFAULT_VALUE, model=EditableGrid) + new_tuple = ( + { + "id": 1, + 'string': "test string", + "integer": 2, + "floater": 3.24, + }, + ) + edit_tsv_with_diff.value = new_tuple + + assert edit_tsv_with_diff.value != [] \ No newline at end of file diff --git a/tests/custom/test_edittsv_with_diff_and_key_mapping.py b/tests/custom/test_edittsv_with_diff_and_key_mapping.py new file mode 100644 index 00000000..20b5ef74 --- /dev/null +++ b/tests/custom/test_edittsv_with_diff_and_key_mapping.py @@ -0,0 +1,141 @@ +import typing as ty + +from pydantic import BaseModel, RootModel + +from ipyautoui.custom.edittsv import Changes +from ipyautoui.custom.edittsv_with_diff_and_key_mapping import ( + EditTsvWithDiffAndKeyMapping, +) + + +class ExampleModel(BaseModel): + Id: int + Site: ty.Optional[str] = None + Meter: ty.Optional[str] = None + reading: int + nullable: ty.Optional[str] = None + + +class Example(RootModel): + root: list[ExampleModel] + + +def _validate(widget: EditTsvWithDiffAndKeyMapping, data: list[dict]) -> list[dict]: + """Run data through the widget's pydantic model for consistent structure.""" + return widget.model.model_validate(data).model_dump(mode="json", by_alias=True) + + +def _make_widget(initial_value: list[dict]) -> EditTsvWithDiffAndKeyMapping: + widget = EditTsvWithDiffAndKeyMapping( + value=initial_value, + model=Example, + primary_key_name=["Site", "Meter"], + ) + return widget + + +def test_bn_upload_text_builds_composite_key_maps(): + initial = [ + {"Id": 1, "Site": "A", "Meter": "001", "reading": 1, "nullable": None}, + ] + updated = [ + {"Id": 1, "Site": "A", "Meter": "001", "reading": 2, "nullable": None}, + {"Id": 2, "Site": "B", "Meter": None, "reading": 3, "nullable": "x"}, + ] + + widget = _make_widget(initial) + widget.prev_value = _validate(widget, initial) + widget._value = _validate(widget, updated) + + widget._bn_upload_text(None) + + expected_prev = { + "A-001": { + "Id": 1, + "Site": "A", + "Meter": "001", + "reading": 1, + "nullable": "", + } + } + expected_new = { + "A-001": { + "Id": 1, + "Site": "A", + "Meter": "001", + "reading": 2, + "nullable": "", + }, + "B": { + "Id": 2, + "Site": "B", + "Meter": "", + "reading": 3, + "nullable": "x", + }, + } + + assert widget.ddiff.value == expected_prev + assert widget.ddiff.new_value == expected_new + assert widget.ddiff.diff is not None + + assert widget.bn_upload_text.layout.display == "None" + assert widget.bn_confirmation.layout.display == "" + assert widget.bn_cross.layout.display == "" + assert widget.ddiff.layout.display == "" + + +def test_deepdiff_to_crud_handles_composite_keys(): + initial = [ + {"Id": 1, "Site": "A", "Meter": "001", "reading": 1, "nullable": None}, + {"Id": 3, "Site": "C", "Meter": "009", "reading": 4, "nullable": None}, + ] + updated = [ + {"Id": 1, "Site": "A", "Meter": "001", "reading": 2, "nullable": None}, + {"Id": 2, "Site": "B", "Meter": None, "reading": 3, "nullable": "x"}, + ] + + widget = _make_widget(initial) + widget.prev_value = _validate(widget, initial) + widget._value = _validate(widget, updated) + + widget._bn_upload_text(None) + changes = widget.deepdiff_to_crud(widget.ddiff.diff) + + assert changes.deletions == ["C-009"] + assert changes.additions == [ + {"Id": 2, "Site": "B", "Meter": "", "reading": 3, "nullable": "x"} + ] + assert changes.edits == {"A-001": {"reading": 2}} + + +def test_resolve_composite_keys_to_real_ids(): + widget = _make_widget( + [{"Id": 1, "Site": "A", "Meter": "001", "reading": 1, "nullable": None}] + ) + + dataset = [ + {"Id": 101, "Site": "A", "Meter": "001"}, + {"Id": 102, "Site": "B", "Meter": None}, + {"Id": 103, "Site": None, "Meter": None}, + ] + mapping = widget._build_composite_key_to_id_map(dataset) + + assert mapping == {"A-001": 101, "B": 102} + assert widget._composite_key_for_id(101, mapping) == "A-001" + assert widget._composite_key_for_id("102", mapping) == "B" + assert widget._composite_key_for_id("invalid", mapping) == "" + + raw_changes = Changes( + deletions=["A-001", "missing"], + edits={"A-001": {"reading": 9}, "missing": {"reading": 5}}, + additions=[{"Id": 200, "Site": "X"}], + edited_rows={"A-001": {"reading": 9}, "missing": {"reading": 5}} + ) + + resolved = widget._resolve_composite_to_ids(raw_changes, mapping) + + assert resolved.deletions == [101] + assert resolved.edits == {101: {"reading": 9}} + assert resolved.additions == [{"Id": 200, "Site": "X"}] + assert resolved.edited_rows == {101: {"reading": 9}} diff --git a/tests/test_automapschema.py b/tests/test_automapschema.py index e0cafc78..95c9e003 100644 --- a/tests/test_automapschema.py +++ b/tests/test_automapschema.py @@ -1,7 +1,12 @@ import pytest import pathlib +import sys from pytest_examples import find_examples, CodeExample, EvalExample -from ipyautoui.automapschema import _init_model_schema, map_widget +from ipyautoui.automapschema import ( + _init_model_schema, + map_widget, + pydantic_model_from_json_schema, +) import casefy from pydantic import BaseModel, Field, conint from ipyautoui.demo_schemas import ( @@ -12,7 +17,7 @@ ) import typing as ty from typing_extensions import Annotated -from enum import Enum +from enum import Enum, IntEnum from jsonref import replace_refs from ipyautoui.automapschema import widgetcaller @@ -88,8 +93,7 @@ class Test(BaseModel): combobox: ty.Union[str, FruitEnum] = Field("apple") - model, schema = _init_model_schema(Test) - assert_widget_map(schema) + assert_widget_map(Test) def test_combobox_mapped(): @@ -136,3 +140,186 @@ class MyObject(BaseModel): assert "anyOf" in caller.kwargs["properties"]["floaty"] ui = widgetcaller(caller) assert len(ui.di_widgets["floaty"].anyOf) == 2 + + +PROJECT_BUILDING_AREA_TARGET_YEARS = [ + 2025, + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032, + 2033, + 2034, + 2035, + 2036, + 2037, + 2038, + 2039, + 2040, + 2050, +] + + +PROJECT_BUILDING_AREA_SCHEMA = { + "title": "Project Building Area", + "type": "array", + "format": "DataFrame", + "hide_nan": True, + "datagrid_index_name": ["section", "title"], + "items": { + "title": "Project Buildings", + "description": "Add any buildings that exist within the project", + "type": "object", + "parameter_type": "T", + "override_units": True, + "classification": "", + "properties": { + "Abbreviation": { + "enum": ["BLDG"], + "type": "string", + "revit_data_type": "TEXT", + "ifc_data_type": "IfcText", + "namespace_uri": None, + "guid": "4ec7e9b3-b1f0-4b76-b0d4-9dd1338b8c2f", + "guid_source": "MXF", + "title": "Abbreviation", + "name": "Abbreviation", + "description": "equipment type abbreviation, alphabetic characters only, variable length, between 2 and 6 characters", + "category": "Specifications", + "section": "Identity Data", + "tooltip": "asset abbreviation is defined by the [BDNS](https://github.com/theodi/BDNS). Abbreviations must be from those defined in the [BDNS_Abbreviations_Register.csv](https://github.com/theodi/BDNS/blob/master/BDNS_Abbreviations_Register.csv)", + "property_value_kind": "Single", + "unit": "", + "unit_code": "", + "parameter_type": "T", + "pset": "Pset_IdentityCore", + "id": 2696, + "default": "BLDG", + }, + "TypeReference": { + "type": "integer", + "revit_data_type": "INTEGER", + "ifc_data_type": "IfcInteger", + "namespace_uri": None, + "guid": "f2cb3fad-ff04-4e62-bffa-80d6d3fd2862", + "guid_source": "MXF", + "title": "Type Reference", + "name": "TypeReference", + "description": "equipment type reference, integer only. Refers to equipment type, there may be multiple instances of the same type", + "category": "Specifications", + "section": "Identity Data", + "tooltip": "", + "property_value_kind": "Single", + "unit": "", + "unit_code": "", + "parameter_type": "T", + "pset": "Pset_IdentityCore", + "id": 2698, + "default": 1, + }, + "TargetYear": { + "enum": PROJECT_BUILDING_AREA_TARGET_YEARS.copy(), + "revit_data_type": "INTEGER", + "ifc_data_type": "IfcInteger", + "namespace_uri": None, + "guid": "38d4ec6a-9fbb-458f-88a2-b29b33c1ec48", + "guid_source": "MXF", + "title": "Target Year", + "name": "TargetYear", + "description": "Net Zero Carbon targets change annually. This defined what year the Benchmark Targets should be defined by.", + "category": "Specifications", + "section": "Identity Data", + "tooltip": None, + "property_value_kind": "Single", + "unit": "", + "unit_code": "", + "parameter_type": "T", + "pset": "BuildingArea", + "id": 3090, + "type": "integer", + }, + "Name": { + "revit_data_type": "TEXT", + "ifc_data_type": "IfcText", + "namespace_uri": "https://identifier.buildingsmart.org/uri/buildingsmart/ifc/4.3/prop/Name", + "guid": "a13b623a-94ea-4864-a42c-76d3a40acd47", + "guid_source": "MXF", + "title": "Building Name", + "name": "Name", + "description": "Optional. Add a building name as used in the project for easier identification.", + "category": "Facilities/Asset Management", + "section": "Identity Data", + "tooltip": None, + "property_value_kind": "Single", + "unit": "", + "unit_code": "", + "parameter_type": "T", + "pset": "BuildingArea", + "id": 3091, + "type": "string", + }, + "Id": { + "format": "default", + "revit_data_type": "INTEGER", + "ifc_data_type": "IfcInteger", + "namespace_uri": None, + "guid": "958e6995-9f04-49d3-ba03-738b6bd66fd0", + "guid_source": "MXF", + "title": "Id", + "name": "Id", + "description": "", + "category": "Undefined", + "section": "Identity Data", + "tooltip": None, + "property_value_kind": "Single", + "unit": "", + "unit_code": "", + "parameter_type": "T", + "pset": "", + "id": 0, + "type": "integer", + }, + }, + "id": 835, + }, +} + + +def test_pydantic_model_from_json_schema_project_building_area_int_enum(): + model = pydantic_model_from_json_schema(PROJECT_BUILDING_AREA_SCHEMA) + module = sys.modules[model.__module__] + target_year_enum = getattr(module, "TargetYear") + + assert issubclass(target_year_enum, IntEnum) + assert {member.value for member in target_year_enum} == set( + PROJECT_BUILDING_AREA_TARGET_YEARS + ) + + validated = model.model_validate( + [ + { + "Abbreviation": "BLDG", + "TypeReference": 1, + "TargetYear": 2025, + "Name": "Main Building", + "Id": 1, + } + ] + ) + + validated_string_date = model.model_validate( + [ + { + "Abbreviation": "BLDG", + "TypeReference": 1, + "TargetYear": "2025", + "Name": "Main Building", + "Id": 1, + } + ] + ) + + assert validated, validated_string_date \ No newline at end of file diff --git a/tests/test_data/edit-grid-file-data.json b/tests/test_data/edit-grid-file-data.json new file mode 100644 index 00000000..070a8be6 --- /dev/null +++ b/tests/test_data/edit-grid-file-data.json @@ -0,0 +1,20 @@ +[ + { + "id": 8, + "string": "apple", + "integer": 3, + "floater": 2.6 + }, + { + "id": 9, + "string": "abc", + "integer": 4, + "floater": 1.1 + }, + { + "id": 11, + "string": "hij", + "integer": 4, + "floater": 1.1 + } +] \ No newline at end of file diff --git a/tests/test_editgrid.py b/tests/test_editgrid.py index 9e70568f..7209f466 100644 --- a/tests/test_editgrid.py +++ b/tests/test_editgrid.py @@ -55,6 +55,16 @@ def test_editgrid_change_data(self): grid._save_add_to_grid() assert v != grid._value + def test_editgrid_set_data_coerce_titles(self): + grid = EditGrid(schema=EditableGrid) + v = grid.value + titles = ['String', 'Integer', 'Floater', 'Something Else'] + v_with_titles = [dict(zip(titles, list(_.keys()))) for _ in v] + v_with_titles[0]["Something Else"] = 1 + grid.value = v_with_titles + assert grid._value[0]["something_else"] == 1 + + def test_editgrid_multiindex_change_data(self): class TestProperties(BaseModel): string: str = Field(json_schema_extra=dict(column_width=100, section="a"))