From b3e7efc71b4b65e8042fbbd8ddadb2d944358329 Mon Sep 17 00:00:00 2001 From: Vinod Muthusamy Date: Tue, 20 Jan 2026 15:15:53 -0600 Subject: [PATCH] Improve trajectory storage and fix schema handling - Add architecture diagram to README - Store trajectory as single entity per span/trace ID - Support list and dict content types (not just strings) - Fix Milvus backend to handle non-string content - Fix SQLite schema for new content format --- README.md | 4 + docs/assets/architecture.png | Bin 0 -> 55656 bytes kaizen/backend/filesystem.py | 12 +- kaizen/backend/milvus.py | 39 +- kaizen/db/sqlite_manager.py | 4 +- kaizen/schema/conflict_resolution.py | 4 +- kaizen/schema/core.py | 2 +- kaizen/sync/phoenix_sync.py | 37 +- pyproject.toml | 3 +- tests/unit/test_phoenix_sync.py | 21 +- uv.lock | 612 ++++++++++++++++++++++++++- 11 files changed, 682 insertions(+), 56 deletions(-) create mode 100644 docs/assets/architecture.png diff --git a/README.md b/README.md index fc4b4adb..cf7de604 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,10 @@ Kaizen is a system designed to help agents improve over time by learning from th - **Trajectory Analysis**: Automatically analyzes agent trajectories to generate tips and best practices. - **Milvus Integration**: Uses Milvus (or Milvus Lite) for efficient vector storage and retrieval. +## Architecture + +Architecture + ## Quick Start ### Installation diff --git a/docs/assets/architecture.png b/docs/assets/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..d22804c3c5265fba480cf0553421025cfcdf80e7 GIT binary patch literal 55656 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�uBFU2@20l;9$Xy>3UJNAEv2}s-va{0 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 z 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 PS0EOq$4p)sxkUUw#Y=PG literal 0 HcmV?d00001 diff --git a/kaizen/backend/filesystem.py b/kaizen/backend/filesystem.py index c8a0a333..01a6712c 100644 --- a/kaizen/backend/filesystem.py +++ b/kaizen/backend/filesystem.py @@ -248,10 +248,14 @@ def _search_entities_internal( else: # Simple case-insensitive text matching query_lower = query.lower() - matching = [ - ent for ent in entities - if query_lower in ent.get("content", "").lower() - ] + matching = [] + for ent in entities: + content = ent.get("content", "") + # Convert non-string content to JSON string for searching + if not isinstance(content, str): + content = json.dumps(content) + if query_lower in content.lower(): + matching.append(ent) results = matching[:limit] return [ diff --git a/kaizen/backend/milvus.py b/kaizen/backend/milvus.py index 4b25da07..ac98c78d 100644 --- a/kaizen/backend/milvus.py +++ b/kaizen/backend/milvus.py @@ -1,4 +1,5 @@ import datetime +import json import logging import uuid @@ -15,6 +16,22 @@ logging.basicConfig(level=logging.INFO) logger = logging.getLogger("katas-db.milvus") + +def serialize_content(content) -> str: + """Serialize content to string for Milvus storage.""" + if isinstance(content, str): + return content + return json.dumps(content) + + +def deserialize_content(content: str): + """Deserialize content from Milvus storage.""" + try: + return json.loads(content) + except (json.JSONDecodeError, TypeError): + return content + + class MilvusKataBackend(BaseKataBackend): milvus = MilvusClient(**milvus_client_settings.model_dump()) embedding_model = SentenceTransformer(milvus_other_settings.embedding_model) @@ -93,27 +110,29 @@ def update_entities( if enable_conflict_resolution: old_entities = [] for entity in entities: - old_entities.extend(self.search_entities(namespace_id=namespace_id, query=entity.content)) + query_str = serialize_content(entity.content) + old_entities.extend(self.search_entities(namespace_id=namespace_id, query=query_str)) updates = resolve_conflicts(old_entities, entities_with_temporary_ids) for update in updates: + content_str = serialize_content(update.content) match update.event: case 'ADD': entity_id = str(self.milvus.insert(collection_name=namespace_id, data={ 'type': entity_type, - 'content': update.content, + 'content': content_str, 'created_at': int(now.timestamp()), - 'embedding': self.embedding_model.encode(update.content), + 'embedding': self.embedding_model.encode(content_str), 'metadata': update.metadata, })['ids'][0]) update.id = entity_id case 'UPDATE': self.milvus.upsert(collection_name=namespace_id, data={ 'type': entity_type, - 'id': update.id, - 'content': update.content, + 'id': int(update.id), + 'content': content_str, 'created_at': int(now.timestamp()), - 'embedding': self.embedding_model.encode(update.content), + 'embedding': self.embedding_model.encode(content_str), 'metadata': update.metadata }, partial_update=True) case 'DELETE': @@ -123,11 +142,12 @@ def update_entities( else: updates = [] for entity in entities: + content_str = serialize_content(entity.content) entity_id = str(self.milvus.insert(collection_name=namespace_id, data={ 'type': entity_type, - 'content': entity.content, + 'content': content_str, 'created_at': int(now.timestamp()), - 'embedding': self.embedding_model.encode(entity.content), + 'embedding': self.embedding_model.encode(content_str), 'metadata': entity.metadata })['ids'][0]) updates.append(EntityUpdate( @@ -175,7 +195,7 @@ def delete_entity_by_id(self, namespace_id: str, entity_id: str): # Keep it as an INT64 or else you won't be able to list all entities. FieldSchema(name='id', is_primary=True, auto_id=True, dtype=DataType.INT64, max_length=128), FieldSchema(name='type', dtype=DataType.VARCHAR, max_length=128), - FieldSchema(name='content', dtype=DataType.VARCHAR, max_length=512), + FieldSchema(name='content', dtype=DataType.VARCHAR, max_length=65535), FieldSchema(name='created_at', dtype=DataType.INT64), FieldSchema(name='embedding', dtype=DataType.FLOAT_VECTOR, dim=384), FieldSchema(name='metadata', dtype=DataType.JSON), @@ -185,5 +205,6 @@ def parse_milvus_entity(entity: dict) -> RecordedEntity: return RecordedEntity.model_validate({ **entity, 'id': str(entity['id']), + 'content': deserialize_content(entity['content']), 'created_at': datetime.datetime.fromtimestamp(entity['created_at'], datetime.UTC), }) \ No newline at end of file diff --git a/kaizen/db/sqlite_manager.py b/kaizen/db/sqlite_manager.py index 39cff85f..3568ef47 100644 --- a/kaizen/db/sqlite_manager.py +++ b/kaizen/db/sqlite_manager.py @@ -95,8 +95,8 @@ def search_namespaces( with self._lock: cursor: sqlite3.Cursor = self.connection.cursor() cursor.row_factory = Namespace.row_factory - cursor.execute(f""" - SELECT id, created_at, user_id, agent_id, app_id + cursor.execute(""" + SELECT id, created_at FROM namespaces LIMIT ? """, diff --git a/kaizen/schema/conflict_resolution.py b/kaizen/schema/conflict_resolution.py index 3d6ed8ae..31c38d5a 100644 --- a/kaizen/schema/conflict_resolution.py +++ b/kaizen/schema/conflict_resolution.py @@ -6,7 +6,7 @@ class SimpleEntity(BaseModel): """Derived from either a `Entity` or `RecordedEntity`. Optimized for LLM-based conflict resolution.""" id: str = Field(description='The unique ID of an entity.') type: str = Field(description='The type of the entity.') - content: str = Field(description='The content of the entity.') + content: str | list | dict = Field(description='The content of the entity.') @staticmethod def from_recorded_entities(entities: list[RecordedEntity]) -> list['SimpleEntity']: @@ -17,7 +17,7 @@ class EntityUpdate(BaseModel): """Produced by the LLM, to be processed by a kata backend.""" id: str = Field(description='The unique ID of an entity.') type: str = Field(description='The type of the entity.') - content: str = Field(description='The content of the entity.') + content: str | list | dict = Field(description='The content of the entity.') event: Literal['ADD', 'UPDATE', 'DELETE', 'NONE'] = Field(description='The type of update operation to perform.') old_entity: str | None = Field(default=None, description='The entity before it was updated.') metadata: dict | None = Field(default=None, description='Arbitrary metadata which is related to the entity.') \ No newline at end of file diff --git a/kaizen/schema/core.py b/kaizen/schema/core.py index 4db971cd..0f42c728 100644 --- a/kaizen/schema/core.py +++ b/kaizen/schema/core.py @@ -16,7 +16,7 @@ def row_factory(cursor: Cursor, row: Row) -> 'Namespace': class Entity(BaseModel): """Basic data stored in the DB""" - content: str = Field(description='Some relatively short searchable text.') + content: str | list | dict = Field(description='Searchable text or structured data.') metadata: dict | None = Field(default=None, description='Arbitrary metadata which is related to the entity.') type: str = Field(description='The type of the entity.') diff --git a/kaizen/sync/phoenix_sync.py b/kaizen/sync/phoenix_sync.py index e4585b90..c0bc266e 100644 --- a/kaizen/sync/phoenix_sync.py +++ b/kaizen/sync/phoenix_sync.py @@ -298,29 +298,24 @@ def _process_trajectory(self, trajectory: dict) -> int: Returns the number of tips generated. """ - # Store trajectory messages - entities = [] - for msg in trajectory.get("messages", []): - content = msg.get("content") - if isinstance(content, str) and content: - entities.append( - Entity( - type="trajectory", - content=content, - metadata={ - "trace_id": trajectory["trace_id"], - "span_id": trajectory["span_id"], - "model": trajectory["model"], - "role": msg.get("role"), - "timestamp": trajectory["timestamp"], - }, - ) - ) - - if entities: + # Store trajectory as a single entity with all messages + messages = trajectory.get("messages", []) + if messages: + entity = Entity( + type="trajectory", + content=messages, + metadata={ + "trace_id": trajectory["trace_id"], + "span_id": trajectory["span_id"], + "model": trajectory["model"], + "timestamp": trajectory["timestamp"], + "message_count": len(messages), + "usage": trajectory.get("usage"), + }, + ) self.client.update_entities( namespace_id=self.namespace_id, - entities=entities, + entities=[entity], enable_conflict_resolution=False, ) diff --git a/pyproject.toml b/pyproject.toml index 900f897f..597a3816 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [ + "arize-phoenix>=12.30.0", "fastmcp", "jinja2", "litellm", @@ -44,4 +45,4 @@ markers = [ "unit", "phoenix" ] -anyio_mode = "auto" \ No newline at end of file +anyio_mode = "auto" diff --git a/tests/unit/test_phoenix_sync.py b/tests/unit/test_phoenix_sync.py index 96c0a007..49d2922d 100644 --- a/tests/unit/test_phoenix_sync.py +++ b/tests/unit/test_phoenix_sync.py @@ -638,7 +638,18 @@ def test_sync_processes_valid_spans(self, mock_generate_tips, mock_urlopen, phoe mock_urlopen.return_value = mock_response phoenix_sync.client.search_entities.return_value = [] - mock_generate_tips.return_value = ["Tip 1", "Tip 2"] + # Create mock Tip objects with required attributes + mock_tip1 = MagicMock() + mock_tip1.content = "Tip 1 content" + mock_tip1.category = "strategy" + mock_tip1.rationale = "Tip 1 rationale" + mock_tip1.trigger = "Tip 1 trigger" + mock_tip2 = MagicMock() + mock_tip2.content = "Tip 2 content" + mock_tip2.category = "optimization" + mock_tip2.rationale = "Tip 2 rationale" + mock_tip2.trigger = "Tip 2 trigger" + mock_generate_tips.return_value = [mock_tip1, mock_tip2] result = phoenix_sync.sync(limit=10) @@ -684,7 +695,13 @@ def test_sync_returns_correct_counts(self, mock_generate_tips, mock_urlopen, pho mock_entity = MagicMock() mock_entity.metadata = {"span_id": "old_span"} phoenix_sync.client.search_entities.return_value = [mock_entity] - mock_generate_tips.return_value = ["Generated tip"] + # Create mock Tip object with required attributes + mock_tip = MagicMock() + mock_tip.content = "Generated tip content" + mock_tip.category = "strategy" + mock_tip.rationale = "Tip rationale" + mock_tip.trigger = "Tip trigger" + mock_generate_tips.return_value = [mock_tip] result = phoenix_sync.sync(limit=10) diff --git a/uv.lock b/uv.lock index 73b67127..1a7be777 100644 --- a/uv.lock +++ b/uv.lock @@ -2,8 +2,12 @@ version = 1 revision = 1 requires-python = ">=3.12" resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version < '3.14'", + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.14' and sys_platform != 'win32'", + "python_full_version == '3.13.*' and sys_platform == 'win32'", + "python_full_version < '3.13' and sys_platform == 'win32'", + "python_full_version == '3.13.*' and sys_platform != 'win32'", + "python_full_version < '3.13' and sys_platform != 'win32'", ] [[package]] @@ -100,6 +104,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694 }, ] +[[package]] +name = "aioitertools" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fd/3c/53c4a17a05fb9ea2313ee1777ff53f5e001aefd5cc85aa2f4c2d982e1e38/aioitertools-0.13.0.tar.gz", hash = "sha256:620bd241acc0bbb9ec819f1ab215866871b4bbd1f73836a55f799200ee86950c", size = 19322 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/a1/510b0a7fadc6f43a6ce50152e69dbd86415240835868bb0bd9b5b88b1e06/aioitertools-0.13.0-py3-none-any.whl", hash = "sha256:0be0292b856f08dfac90e31f4739432f4cb6d7520ab9eb73e143f4f2fa5259be", size = 24182 }, +] + [[package]] name = "aiosignal" version = "1.4.0" @@ -113,6 +126,38 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490 }, ] +[[package]] +name = "aiosqlite" +version = "0.22.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/8a/64761f4005f17809769d23e518d915db74e6310474e733e3593cfc854ef1/aiosqlite-0.22.1.tar.gz", hash = "sha256:043e0bd78d32888c0a9ca90fc788b38796843360c855a7262a532813133a0650", size = 14821 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/b7/e3bf5133d697a08128598c8d0abc5e16377b51465a33756de24fa7dee953/aiosqlite-0.22.1-py3-none-any.whl", hash = "sha256:21c002eb13823fad740196c5a2e9d8e62f6243bd9e7e4a1f87fb5e44ecb4fceb", size = 17405 }, +] + +[[package]] +name = "alembic" +version = "1.18.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mako" }, + { name = "sqlalchemy" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/cc/aca263693b2ece99fa99a09b6d092acb89973eb2bb575faef1777e04f8b4/alembic-1.18.1.tar.gz", hash = "sha256:83ac6b81359596816fb3b893099841a0862f2117b2963258e965d70dc62fb866", size = 2044319 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/36/cd9cb6101e81e39076b2fbe303bfa3c85ca34e55142b0324fcbf22c5c6e2/alembic-1.18.1-py3-none-any.whl", hash = "sha256:f1c3b0920b87134e851c25f1f7f236d8a332c34b75416802d06971df5d1b7810", size = 260973 }, +] + +[[package]] +name = "annotated-doc" +version = "0.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303 }, +] + [[package]] name = "annotated-types" version = "0.7.0" @@ -135,6 +180,116 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592 }, ] +[[package]] +name = "arize-phoenix" +version = "12.30.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aioitertools" }, + { name = "aiosqlite" }, + { name = "alembic" }, + { name = "arize-phoenix-client" }, + { name = "arize-phoenix-evals" }, + { name = "arize-phoenix-otel" }, + { name = "authlib" }, + { name = "cachetools" }, + { name = "email-validator" }, + { name = "fastapi" }, + { name = "grpc-interceptor" }, + { name = "grpcio" }, + { name = "httpx" }, + { name = "jinja2" }, + { name = "jmespath" }, + { name = "ldap3" }, + { name = "numpy" }, + { name = "openinference-instrumentation" }, + { name = "openinference-semantic-conventions" }, + { name = "opentelemetry-exporter-otlp" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "orjson" }, + { name = "pandas" }, + { name = "prometheus-client" }, + { name = "protobuf" }, + { name = "psutil" }, + { name = "pyarrow" }, + { name = "pydantic" }, + { name = "python-dateutil" }, + { name = "python-multipart" }, + { name = "scikit-learn" }, + { name = "scipy" }, + { name = "sqlalchemy", extra = ["asyncio"] }, + { name = "sqlean-py" }, + { name = "starlette" }, + { name = "strawberry-graphql" }, + { name = "tqdm" }, + { name = "typing-extensions" }, + { name = "uvicorn" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/14/e2/22424fd20253f1c59e3da71c94931a8c68dc554979bc84b4b98cf975fad7/arize_phoenix-12.30.0.tar.gz", hash = "sha256:8377197b2baf803a40fdf4c2845f9f06f2ec03ea1a716bccb9763d16f8f21b02", size = 2389288 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/b0/81f78329766bacb5f77cee5d6ed72fb78cd9ff3b0bc6228b365f194ab6f7/arize_phoenix-12.30.0-py3-none-any.whl", hash = "sha256:a9f4234507dbac5e8c2c9912438a9d8feb593c8343c32334b4af9d397bc1adaa", size = 2614872 }, +] + +[[package]] +name = "arize-phoenix-client" +version = "1.27.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "openinference-instrumentation" }, + { name = "openinference-semantic-conventions" }, + { name = "opentelemetry-exporter-otlp" }, + { name = "opentelemetry-sdk" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/16/fc82724016356a914f88e55f242c741f956b73eed170e89ba388778d2316/arize_phoenix_client-1.27.2.tar.gz", hash = "sha256:a4ab7eb474bf15f4c431d9b22d255901b8793025c077977996934b441b793c9a", size = 141389 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/f6/687ee8d94141683a938312754ff2fec531761d8ad471901c81aea07609a5/arize_phoenix_client-1.27.2-py3-none-any.whl", hash = "sha256:30314eca082bb923b7985f2f7f139813b6f371d8790539c53a4373bdc9a2dcb5", size = 148242 }, +] + +[[package]] +name = "arize-phoenix-evals" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonpath-ng" }, + { name = "openinference-instrumentation" }, + { name = "openinference-semantic-conventions" }, + { name = "opentelemetry-api" }, + { name = "pandas" }, + { name = "pydantic" }, + { name = "pystache" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4b/7d/7422485753261e58166d0b47311c5491336e798088fd0b6e5121b211ca69/arize_phoenix_evals-2.8.0.tar.gz", hash = "sha256:b5f74247e501002a90ddb488f6a02668d90c34017e60c85eeb454aaf997798a8", size = 113690 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/11/bf89296de7b6b857fbbffa21f8091dcc9e35e940829f4da029f9ee74ef1b/arize_phoenix_evals-2.8.0-py3-none-any.whl", hash = "sha256:27feff84c50ca0c79ee2fbdd14817feaf60e4d1f1da069b7473084b0e4bbb35f", size = 161850 }, +] + +[[package]] +name = "arize-phoenix-otel" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "openinference-instrumentation" }, + { name = "openinference-semantic-conventions" }, + { name = "opentelemetry-exporter-otlp" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "typing-extensions" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/17/ebd502f1bd8a0a6087ea28be8de8b765bcf34fb1b9bc4d6fd6d91bd822f1/arize_phoenix_otel-0.14.0.tar.gz", hash = "sha256:ad1368f0f52c242591ec554cedeccf718abda81383cf8c8d3ade218a7b20b955", size = 20155 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/be/e7ddb54c4ad6115d2d468b71e90d7a2718735fd217f05c50759799191bfe/arize_phoenix_otel-0.14.0-py3-none-any.whl", hash = "sha256:47bf5563b9342a931385a16609ca83ada44d56a00bf6ed3be199226792b9937f", size = 17708 }, +] + [[package]] name = "attrs" version = "25.4.0" @@ -379,6 +534,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, ] +[[package]] +name = "cross-web" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a4/58/e688e99d1493c565d1587e64b499268d0a3129ae59f4efe440aac395f803/cross_web-0.4.1.tar.gz", hash = "sha256:0466295028dcae98c9ab3d18757f90b0e74fac2ff90efbe87e74657546d9993d", size = 157385 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/49/92b46b6e65f09b717a66c4e5a9bc47a45ebc83dd0e0ed126f8258363479d/cross_web-0.4.1-py3-none-any.whl", hash = "sha256:41b07c3a38253c517ec0603c1a366353aff77538946092b0f9a2235033f192c2", size = 14320 }, +] + [[package]] name = "cryptography" version = "46.0.3" @@ -561,6 +728,21 @@ lua = [ { name = "lupa" }, ] +[[package]] +name = "fastapi" +version = "0.128.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc" }, + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/52/08/8c8508db6c7b9aae8f7175046af41baad690771c9bcde676419965e338c7/fastapi-0.128.0.tar.gz", hash = "sha256:1cc179e1cef10a6be60ffe429f79b829dce99d8de32d7acb7e6c8dfdf7f2645a", size = 365682 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/05/5cbb59154b093548acd0f4c7c474a118eda06da25aa75c616b72d8fcd92a/fastapi-0.128.0-py3-none-any.whl", hash = "sha256:aebd93f9716ee3b4f4fcfe13ffb7cf308d99c9f3ab5622d8877441072561582d", size = 103094 }, +] + [[package]] name = "fastmcp" version = "2.14.3" @@ -736,6 +918,78 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/01/c9/97cc5aae1648dcb851958a3ddf73ccd7dbe5650d95203ecb4d7720b4cdbf/fsspec-2026.1.0-py3-none-any.whl", hash = "sha256:cb76aa913c2285a3b49bdd5fc55b1d7c708d7208126b60f2eb8194fe1b4cbdcc", size = 201838 }, ] +[[package]] +name = "googleapis-common-protos" +version = "1.72.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e5/7b/adfd75544c415c487b33061fe7ae526165241c1ea133f9a9125a56b39fd8/googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5", size = 147433 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/ab/09169d5a4612a5f92490806649ac8d41e3ec9129c636754575b3553f4ea4/googleapis_common_protos-1.72.0-py3-none-any.whl", hash = "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038", size = 297515 }, +] + +[[package]] +name = "graphql-core" +version = "3.2.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ac/9b/037a640a2983b09aed4a823f9cf1729e6d780b0671f854efa4727a7affbe/graphql_core-3.2.7.tar.gz", hash = "sha256:27b6904bdd3b43f2a0556dad5d579bdfdeab1f38e8e8788e555bdcb586a6f62c", size = 513484 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/14/933037032608787fb92e365883ad6a741c235e0ff992865ec5d904a38f1e/graphql_core-3.2.7-py3-none-any.whl", hash = "sha256:17fc8f3ca4a42913d8e24d9ac9f08deddf0a0b2483076575757f6c412ead2ec0", size = 207262 }, +] + +[[package]] +name = "greenlet" +version = "3.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/e5/40dbda2736893e3e53d25838e0f19a2b417dfc122b9989c91918db30b5d3/greenlet-3.3.0.tar.gz", hash = "sha256:a82bb225a4e9e4d653dd2fb7b8b2d36e4fb25bc0165422a11e48b88e9e6f78fb", size = 190651 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/0a/a3871375c7b9727edaeeea994bfff7c63ff7804c9829c19309ba2e058807/greenlet-3.3.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b01548f6e0b9e9784a2c99c5651e5dc89ffcbe870bc5fb2e5ef864e9cc6b5dcb", size = 276379 }, + { url = "https://files.pythonhosted.org/packages/43/ab/7ebfe34dce8b87be0d11dae91acbf76f7b8246bf9d6b319c741f99fa59c6/greenlet-3.3.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349345b770dc88f81506c6861d22a6ccd422207829d2c854ae2af8025af303e3", size = 597294 }, + { url = "https://files.pythonhosted.org/packages/a4/39/f1c8da50024feecd0793dbd5e08f526809b8ab5609224a2da40aad3a7641/greenlet-3.3.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8e18ed6995e9e2c0b4ed264d2cf89260ab3ac7e13555b8032b25a74c6d18655", size = 607742 }, + { url = "https://files.pythonhosted.org/packages/77/cb/43692bcd5f7a0da6ec0ec6d58ee7cddb606d055ce94a62ac9b1aa481e969/greenlet-3.3.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c024b1e5696626890038e34f76140ed1daf858e37496d33f2af57f06189e70d7", size = 622297 }, + { url = "https://files.pythonhosted.org/packages/75/b0/6bde0b1011a60782108c01de5913c588cf51a839174538d266de15e4bf4d/greenlet-3.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:047ab3df20ede6a57c35c14bf5200fcf04039d50f908270d3f9a7a82064f543b", size = 609885 }, + { url = "https://files.pythonhosted.org/packages/49/0e/49b46ac39f931f59f987b7cd9f34bfec8ef81d2a1e6e00682f55be5de9f4/greenlet-3.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d9ad37fc657b1102ec880e637cccf20191581f75c64087a549e66c57e1ceb53", size = 1567424 }, + { url = "https://files.pythonhosted.org/packages/05/f5/49a9ac2dff7f10091935def9165c90236d8f175afb27cbed38fb1d61ab6b/greenlet-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83cd0e36932e0e7f36a64b732a6f60c2fc2df28c351bae79fbaf4f8092fe7614", size = 1636017 }, + { url = "https://files.pythonhosted.org/packages/6c/79/3912a94cf27ec503e51ba493692d6db1e3cd8ac7ac52b0b47c8e33d7f4f9/greenlet-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7a34b13d43a6b78abf828a6d0e87d3385680eaf830cd60d20d52f249faabf39", size = 301964 }, + { url = "https://files.pythonhosted.org/packages/02/2f/28592176381b9ab2cafa12829ba7b472d177f3acc35d8fbcf3673d966fff/greenlet-3.3.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a1e41a81c7e2825822f4e068c48cb2196002362619e2d70b148f20a831c00739", size = 275140 }, + { url = "https://files.pythonhosted.org/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808", size = 599219 }, + { url = "https://files.pythonhosted.org/packages/c2/ff/7c985128f0514271b8268476af89aee6866df5eec04ac17dcfbc676213df/greenlet-3.3.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d2d9fd66bfadf230b385fdc90426fcd6eb64db54b40c495b72ac0feb5766c54", size = 610211 }, + { url = "https://files.pythonhosted.org/packages/79/07/c47a82d881319ec18a4510bb30463ed6891f2ad2c1901ed5ec23d3de351f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30a6e28487a790417d036088b3bcb3f3ac7d8babaa7d0139edbaddebf3af9492", size = 624311 }, + { url = "https://files.pythonhosted.org/packages/fd/8e/424b8c6e78bd9837d14ff7df01a9829fc883ba2ab4ea787d4f848435f23f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:087ea5e004437321508a8d6f20efc4cfec5e3c30118e1417ea96ed1d93950527", size = 612833 }, + { url = "https://files.pythonhosted.org/packages/b5/ba/56699ff9b7c76ca12f1cdc27a886d0f81f2189c3455ff9f65246780f713d/greenlet-3.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ab97cf74045343f6c60a39913fa59710e4bd26a536ce7ab2397adf8b27e67c39", size = 1567256 }, + { url = "https://files.pythonhosted.org/packages/1e/37/f31136132967982d698c71a281a8901daf1a8fbab935dce7c0cf15f942cc/greenlet-3.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5375d2e23184629112ca1ea89a53389dddbffcf417dad40125713d88eb5f96e8", size = 1636483 }, + { url = "https://files.pythonhosted.org/packages/7e/71/ba21c3fb8c5dce83b8c01f458a42e99ffdb1963aeec08fff5a18588d8fd7/greenlet-3.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:9ee1942ea19550094033c35d25d20726e4f1c40d59545815e1128ac58d416d38", size = 301833 }, + { url = "https://files.pythonhosted.org/packages/d7/7c/f0a6d0ede2c7bf092d00bc83ad5bafb7e6ec9b4aab2fbdfa6f134dc73327/greenlet-3.3.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:60c2ef0f578afb3c8d92ea07ad327f9a062547137afe91f38408f08aacab667f", size = 275671 }, + { url = "https://files.pythonhosted.org/packages/44/06/dac639ae1a50f5969d82d2e3dd9767d30d6dbdbab0e1a54010c8fe90263c/greenlet-3.3.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a5d554d0712ba1de0a6c94c640f7aeba3f85b3a6e1f2899c11c2c0428da9365", size = 646360 }, + { url = "https://files.pythonhosted.org/packages/e0/94/0fb76fe6c5369fba9bf98529ada6f4c3a1adf19e406a47332245ef0eb357/greenlet-3.3.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3a898b1e9c5f7307ebbde4102908e6cbfcb9ea16284a3abe15cab996bee8b9b3", size = 658160 }, + { url = "https://files.pythonhosted.org/packages/93/79/d2c70cae6e823fac36c3bbc9077962105052b7ef81db2f01ec3b9bf17e2b/greenlet-3.3.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dcd2bdbd444ff340e8d6bdf54d2f206ccddbb3ccfdcd3c25bf4afaa7b8f0cf45", size = 671388 }, + { url = "https://files.pythonhosted.org/packages/b8/14/bab308fc2c1b5228c3224ec2bf928ce2e4d21d8046c161e44a2012b5203e/greenlet-3.3.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5773edda4dc00e173820722711d043799d3adb4f01731f40619e07ea2750b955", size = 660166 }, + { url = "https://files.pythonhosted.org/packages/4b/d2/91465d39164eaa0085177f61983d80ffe746c5a1860f009811d498e7259c/greenlet-3.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ac0549373982b36d5fd5d30beb8a7a33ee541ff98d2b502714a09f1169f31b55", size = 1615193 }, + { url = "https://files.pythonhosted.org/packages/42/1b/83d110a37044b92423084d52d5d5a3b3a73cafb51b547e6d7366ff62eff1/greenlet-3.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d198d2d977460358c3b3a4dc844f875d1adb33817f0613f663a656f463764ccc", size = 1683653 }, + { url = "https://files.pythonhosted.org/packages/7c/9a/9030e6f9aa8fd7808e9c31ba4c38f87c4f8ec324ee67431d181fe396d705/greenlet-3.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:73f51dd0e0bdb596fb0417e475fa3c5e32d4c83638296e560086b8d7da7c4170", size = 305387 }, + { url = "https://files.pythonhosted.org/packages/a0/66/bd6317bc5932accf351fc19f177ffba53712a202f9df10587da8df257c7e/greenlet-3.3.0-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:d6ed6f85fae6cdfdb9ce04c9bf7a08d666cfcfb914e7d006f44f840b46741931", size = 282638 }, + { url = "https://files.pythonhosted.org/packages/30/cf/cc81cb030b40e738d6e69502ccbd0dd1bced0588e958f9e757945de24404/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9125050fcf24554e69c4cacb086b87b3b55dc395a8b3ebe6487b045b2614388", size = 651145 }, + { url = "https://files.pythonhosted.org/packages/9c/ea/1020037b5ecfe95ca7df8d8549959baceb8186031da83d5ecceff8b08cd2/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:87e63ccfa13c0a0f6234ed0add552af24cc67dd886731f2261e46e241608bee3", size = 654236 }, + { url = "https://files.pythonhosted.org/packages/69/cc/1e4bae2e45ca2fa55299f4e85854606a78ecc37fead20d69322f96000504/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2662433acbca297c9153a4023fe2161c8dcfdcc91f10433171cf7e7d94ba2221", size = 662506 }, + { url = "https://files.pythonhosted.org/packages/57/b9/f8025d71a6085c441a7eaff0fd928bbb275a6633773667023d19179fe815/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c6e9b9c1527a78520357de498b0e709fb9e2f49c3a513afd5a249007261911b", size = 653783 }, + { url = "https://files.pythonhosted.org/packages/f6/c7/876a8c7a7485d5d6b5c6821201d542ef28be645aa024cfe1145b35c120c1/greenlet-3.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:286d093f95ec98fdd92fcb955003b8a3d054b4e2cab3e2707a5039e7b50520fd", size = 1614857 }, + { url = "https://files.pythonhosted.org/packages/4f/dc/041be1dff9f23dac5f48a43323cd0789cb798342011c19a248d9c9335536/greenlet-3.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c10513330af5b8ae16f023e8ddbfb486ab355d04467c4679c5cfe4659975dd9", size = 1676034 }, +] + +[[package]] +name = "grpc-interceptor" +version = "0.15.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "grpcio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/28/57449d5567adf4c1d3e216aaca545913fbc21a915f2da6790d6734aac76e/grpc-interceptor-0.15.4.tar.gz", hash = "sha256:1f45c0bcb58b6f332f37c637632247c9b02bc6af0fdceb7ba7ce8d2ebbfb0926", size = 19322 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/ac/8d53f230a7443401ce81791ec50a3b0e54924bf615ad287654fa4a2f5cdc/grpc_interceptor-0.15.4-py3-none-any.whl", hash = "sha256:0035f33228693ed3767ee49d937bac424318db173fef4d2d0170b3215f254d9d", size = 20848 }, +] + [[package]] name = "grpcio" version = "1.76.0" @@ -1032,6 +1286,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2f/9c/6753e6522b8d0ef07d3a3d239426669e984fb0eba15a315cdbc1253904e4/jiter-0.12.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c24e864cb30ab82311c6425655b0cdab0a98c5d973b065c66a3f020740c2324c", size = 346110 }, ] +[[package]] +name = "jmespath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/00/2a/e867e8531cf3e36b41201936b7fa7ba7b5702dbef42922193f05c8976cd6/jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe", size = 25843 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256 }, +] + [[package]] name = "joblib" version = "1.5.3" @@ -1041,6 +1304,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071 }, ] +[[package]] +name = "jsonpath-ng" +version = "1.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ply" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/86/08646239a313f895186ff0a4573452038eed8c86f54380b3ebac34d32fb2/jsonpath-ng-1.7.0.tar.gz", hash = "sha256:f6f5f7fd4e5ff79c785f1573b394043b39849fb2bb47bcead935d12b00beab3c", size = 37838 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/5a/73ecb3d82f8615f32ccdadeb9356726d6cae3a4bbc840b437ceb95708063/jsonpath_ng-1.7.0-py3-none-any.whl", hash = "sha256:f3d7f9e848cba1b6da28c55b1c26ff915dc9e0b1ba7e752a53d6da8d5cbd00b6", size = 30105 }, +] + [[package]] name = "jsonschema" version = "4.26.0" @@ -1088,6 +1363,7 @@ name = "kaizen" version = "0.1.0" source = { editable = "." } dependencies = [ + { name = "arize-phoenix" }, { name = "fastmcp" }, { name = "jinja2" }, { name = "litellm" }, @@ -1108,6 +1384,7 @@ dev = [ [package.metadata] requires-dist = [ + { name = "arize-phoenix", specifier = ">=12.30.0" }, { name = "fastmcp" }, { name = "jinja2" }, { name = "litellm" }, @@ -1143,6 +1420,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160 }, ] +[[package]] +name = "ldap3" +version = "2.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/ac/96bd5464e3edbc61595d0d69989f5d9969ae411866427b2500a8e5b812c0/ldap3-2.9.1.tar.gz", hash = "sha256:f3e7fc4718e3f09dda568b57100095e0ce58633bcabbed8667ce3f8fbaa4229f", size = 398830 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/f6/71d6ec9f18da0b2201287ce9db6afb1a1f637dedb3f0703409558981c723/ldap3-2.9.1-py2.py3-none-any.whl", hash = "sha256:5869596fc4948797020d3f03b7939da938778a0f9e2009f7a072ccf92b8e8d70", size = 432192 }, +] + +[[package]] +name = "lia-web" +version = "0.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cross-web" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/3d/7d574a7a5cf5fbc5fc09c07ea3696dd400353b7702bc009cf596b8c12035/lia_web-0.3.1.tar.gz", hash = "sha256:7f551269eddd729f1437e9341ad21622a849eb0c0975d9232ccbbaadbdc74c06", size = 2021 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/8b/b628fc18658f94b3d094708a18b71083cf47628e85cbc6b9edba54d5b2d7/lia_web-0.3.1-py3-none-any.whl", hash = "sha256:e4e6e7a9381e228aca60a6f3d67dbae9a5f4638eced242d931f95797ddba3f8b", size = 5933 }, +] + [[package]] name = "litellm" version = "1.80.16" @@ -1219,6 +1520,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7d/5e/db903ce9cf82c48d6b91bf6d63ae4c8d0d17958939a4e04ba6b9f38b8643/lupa-2.6-cp314-cp314t-win_amd64.whl", hash = "sha256:fc1498d1a4fc028bc521c26d0fad4ca00ed63b952e32fb95949bda76a04bad52", size = 1913818 }, ] +[[package]] +name = "mako" +version = "1.3.10" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/38/bd5b78a920a64d708fe6bc8e0a2c075e1389d53bef8413725c63ba041535/mako-1.3.10.tar.gz", hash = "sha256:99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28", size = 392474 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl", hash = "sha256:baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59", size = 78509 }, +] + [[package]] name = "markdown-it-py" version = "4.0.0" @@ -1333,7 +1646,7 @@ name = "milvus-lite" version = "2.5.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "tqdm" }, + { name = "tqdm", marker = "sys_platform != 'win32'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/a9/b2/acc5024c8e8b6a0b034670b8e8af306ebd633ede777dcbf557eac4785937/milvus_lite-2.5.1-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:6b014453200ba977be37ba660cb2d021030375fa6a35bc53c2e1d92980a0c512", size = 27934713 }, @@ -1575,7 +1888,7 @@ name = "nvidia-cudnn-cu12" version = "9.10.2.21" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cublas-cu12" }, + { name = "nvidia-cublas-cu12", marker = "sys_platform != 'win32'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/ba/51/e123d997aa098c61d029f76663dedbfb9bc8dcf8c60cbd6adbe42f76d049/nvidia_cudnn_cu12-9.10.2.21-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:949452be657fa16687d0930933f032835951ef0892b37d2d53824d1a84dc97a8", size = 706758467 }, @@ -1586,7 +1899,7 @@ name = "nvidia-cufft-cu12" version = "11.3.3.83" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-nvjitlink-cu12" }, + { name = "nvidia-nvjitlink-cu12", marker = "sys_platform != 'win32'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/1f/13/ee4e00f30e676b66ae65b4f08cb5bcbb8392c03f54f2d5413ea99a5d1c80/nvidia_cufft_cu12-11.3.3.83-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d2dd21ec0b88cf61b62e6b43564355e5222e4a3fb394cac0db101f2dd0d4f74", size = 193118695 }, @@ -1613,9 +1926,9 @@ name = "nvidia-cusolver-cu12" version = "11.7.3.90" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cublas-cu12" }, - { name = "nvidia-cusparse-cu12" }, - { name = "nvidia-nvjitlink-cu12" }, + { name = "nvidia-cublas-cu12", marker = "sys_platform != 'win32'" }, + { name = "nvidia-cusparse-cu12", marker = "sys_platform != 'win32'" }, + { name = "nvidia-nvjitlink-cu12", marker = "sys_platform != 'win32'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/85/48/9a13d2975803e8cf2777d5ed57b87a0b6ca2cc795f9a4f59796a910bfb80/nvidia_cusolver_cu12-11.7.3.90-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:4376c11ad263152bd50ea295c05370360776f8c3427b30991df774f9fb26c450", size = 267506905 }, @@ -1626,7 +1939,7 @@ name = "nvidia-cusparse-cu12" version = "12.5.8.93" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-nvjitlink-cu12" }, + { name = "nvidia-nvjitlink-cu12", marker = "sys_platform != 'win32'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/c2/f5/e1854cb2f2bcd4280c44736c93550cc300ff4b8c95ebe370d0aa7d2b473d/nvidia_cusparse_cu12-12.5.8.93-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ec05d76bbbd8b61b06a80e1eaf8cf4959c3d4ce8e711b65ebd0443bb0ebb13b", size = 288216466 }, @@ -1703,6 +2016,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/12/cf/03675d8bd8ecbf4445504d8071adab19f5f993676795708e36402ab38263/openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", size = 96381 }, ] +[[package]] +name = "openinference-instrumentation" +version = "0.1.42" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "openinference-semantic-conventions" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-sdk" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/d0/b19061a21fd6127d2857c77744a36073bba9c1502d1d5e8517b708eb8b7c/openinference_instrumentation-0.1.42.tar.gz", hash = "sha256:2275babc34022e151b5492cfba41d3b12e28377f8e08cb45e5d64fe2d9d7fe37", size = 23954 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/71/43ee4616fc95dbd2f560550f199c6652a5eb93f84e8aa0039bc95c19cfe0/openinference_instrumentation-0.1.42-py3-none-any.whl", hash = "sha256:e7521ff90833ef7cc65db526a2f59b76a496180abeaaee30ec6abbbc0b43f8ec", size = 30086 }, +] + +[[package]] +name = "openinference-semantic-conventions" +version = "0.1.25" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/68/81c8a0b90334ff11e4f285e4934c57f30bea3ef0c0b9f99b65e7b80fae3b/openinference_semantic_conventions-0.1.25.tar.gz", hash = "sha256:f0a8c2cfbd00195d1f362b4803518341e80867d446c2959bf1743f1894fce31d", size = 12767 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/3d/dd14ee2eb8a3f3054249562e76b253a1545c76adbbfd43a294f71acde5c3/openinference_semantic_conventions-0.1.25-py3-none-any.whl", hash = "sha256:3814240f3bd61f05d9562b761de70ee793d55b03bca1634edf57d7a2735af238", size = 10395 }, +] + [[package]] name = "opentelemetry-api" version = "1.39.1" @@ -1716,6 +2053,67 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cf/df/d3f1ddf4bb4cb50ed9b1139cc7b1c54c34a1e7ce8fd1b9a37c0d1551a6bd/opentelemetry_api-1.39.1-py3-none-any.whl", hash = "sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950", size = 66356 }, ] +[[package]] +name = "opentelemetry-exporter-otlp" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-exporter-otlp-proto-grpc" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/30/9c/3ab1db90f32da200dba332658f2bbe602369e3d19f6aba394031a42635be/opentelemetry_exporter_otlp-1.39.1.tar.gz", hash = "sha256:7cf7470e9fd0060c8a38a23e4f695ac686c06a48ad97f8d4867bc9b420180b9c", size = 6147 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/6c/bdc82a066e6fb1dcf9e8cc8d4e026358fe0f8690700cc6369a6bf9bd17a7/opentelemetry_exporter_otlp-1.39.1-py3-none-any.whl", hash = "sha256:68ae69775291f04f000eb4b698ff16ff685fdebe5cb52871bc4e87938a7b00fe", size = 7019 }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-proto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/9d/22d241b66f7bbde88a3bfa6847a351d2c46b84de23e71222c6aae25c7050/opentelemetry_exporter_otlp_proto_common-1.39.1.tar.gz", hash = "sha256:763370d4737a59741c89a67b50f9e39271639ee4afc999dadfe768541c027464", size = 20409 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/02/ffc3e143d89a27ac21fd557365b98bd0653b98de8a101151d5805b5d4c33/opentelemetry_exporter_otlp_proto_common-1.39.1-py3-none-any.whl", hash = "sha256:08f8a5862d64cc3435105686d0216c1365dc5701f86844a8cd56597d0c764fde", size = 18366 }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-grpc" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "grpcio" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/53/48/b329fed2c610c2c32c9366d9dc597202c9d1e58e631c137ba15248d8850f/opentelemetry_exporter_otlp_proto_grpc-1.39.1.tar.gz", hash = "sha256:772eb1c9287485d625e4dbe9c879898e5253fea111d9181140f51291b5fec3ad", size = 24650 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/a3/cc9b66575bd6597b98b886a2067eea2693408d2d5f39dad9ab7fc264f5f3/opentelemetry_exporter_otlp_proto_grpc-1.39.1-py3-none-any.whl", hash = "sha256:fa1c136a05c7e9b4c09f739469cbdb927ea20b34088ab1d959a849b5cc589c18", size = 19766 }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/80/04/2a08fa9c0214ae38880df01e8bfae12b067ec0793446578575e5080d6545/opentelemetry_exporter_otlp_proto_http-1.39.1.tar.gz", hash = "sha256:31bdab9745c709ce90a49a0624c2bd445d31a28ba34275951a6a362d16a0b9cb", size = 17288 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/f1/b27d3e2e003cd9a3592c43d099d2ed8d0a947c15281bf8463a256db0b46c/opentelemetry_exporter_otlp_proto_http-1.39.1-py3-none-any.whl", hash = "sha256:d9f5207183dd752a412c4cd564ca8875ececba13be6e9c6c370ffb752fd59985", size = 19641 }, +] + [[package]] name = "opentelemetry-exporter-prometheus" version = "0.60b1" @@ -1745,6 +2143,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/d2/6788e83c5c86a2690101681aeef27eeb2a6bf22df52d3f263a22cee20915/opentelemetry_instrumentation-0.60b1-py3-none-any.whl", hash = "sha256:04480db952b48fb1ed0073f822f0ee26012b7be7c3eac1a3793122737c78632d", size = 33096 }, ] +[[package]] +name = "opentelemetry-proto" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/1d/f25d76d8260c156c40c97c9ed4511ec0f9ce353f8108ca6e7561f82a06b2/opentelemetry_proto-1.39.1.tar.gz", hash = "sha256:6c8e05144fc0d3ed4d22c2289c6b126e03bcd0e6a7da0f16cedd2e1c2772e2c8", size = 46152 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/95/b40c96a7b5203005a0b03d8ce8cd212ff23f1793d5ba289c87a097571b18/opentelemetry_proto-1.39.1-py3-none-any.whl", hash = "sha256:22cdc78efd3b3765d09e68bfbd010d4fc254c9818afd0b6b423387d9dee46007", size = 72535 }, +] + [[package]] name = "opentelemetry-sdk" version = "1.39.1" @@ -1917,6 +2327,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538 }, ] +[[package]] +name = "ply" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e5/69/882ee5c9d017149285cab114ebeab373308ef0f874fcdac9beb90e0ac4da/ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3", size = 159130 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce", size = 49567 }, +] + [[package]] name = "pre-commit" version = "4.5.1" @@ -2041,6 +2460,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/75/b1/1dc83c2c661b4c62d56cc081706ee33a4fc2835bd90f965baa2663ef7676/protobuf-6.33.4-py3-none-any.whl", hash = "sha256:1fe3730068fcf2e595816a6c34fe66eeedd37d51d0400b72fabc848811fdc1bc", size = 170532 }, ] +[[package]] +name = "psutil" +version = "7.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/73/cb/09e5184fb5fc0358d110fc3ca7f6b1d033800734d34cac10f4136cfac10e/psutil-7.2.1.tar.gz", hash = "sha256:f7583aec590485b43ca601dd9cea0dcd65bd7bb21d30ef4ddbf4ea6b5ed1bdd3", size = 490253 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/8e/f0c242053a368c2aa89584ecd1b054a18683f13d6e5a318fc9ec36582c94/psutil-7.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ba9f33bb525b14c3ea563b2fd521a84d2fa214ec59e3e6a2858f78d0844dd60d", size = 129624 }, + { url = "https://files.pythonhosted.org/packages/26/97/a58a4968f8990617decee234258a2b4fc7cd9e35668387646c1963e69f26/psutil-7.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:81442dac7abfc2f4f4385ea9e12ddf5a796721c0f6133260687fec5c3780fa49", size = 130132 }, + { url = "https://files.pythonhosted.org/packages/db/6d/ed44901e830739af5f72a85fa7ec5ff1edea7f81bfbf4875e409007149bd/psutil-7.2.1-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea46c0d060491051d39f0d2cff4f98d5c72b288289f57a21556cc7d504db37fc", size = 180612 }, + { url = "https://files.pythonhosted.org/packages/c7/65/b628f8459bca4efbfae50d4bf3feaab803de9a160b9d5f3bd9295a33f0c2/psutil-7.2.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35630d5af80d5d0d49cfc4d64c1c13838baf6717a13effb35869a5919b854cdf", size = 183201 }, + { url = "https://files.pythonhosted.org/packages/fb/23/851cadc9764edcc18f0effe7d0bf69f727d4cf2442deb4a9f78d4e4f30f2/psutil-7.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:923f8653416604e356073e6e0bccbe7c09990acef442def2f5640dd0faa9689f", size = 139081 }, + { url = "https://files.pythonhosted.org/packages/59/82/d63e8494ec5758029f31c6cb06d7d161175d8281e91d011a4a441c8a43b5/psutil-7.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cfbe6b40ca48019a51827f20d830887b3107a74a79b01ceb8cc8de4ccb17b672", size = 134767 }, + { url = "https://files.pythonhosted.org/packages/05/c2/5fb764bd61e40e1fe756a44bd4c21827228394c17414ade348e28f83cd79/psutil-7.2.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:494c513ccc53225ae23eec7fe6e1482f1b8a44674241b54561f755a898650679", size = 129716 }, + { url = "https://files.pythonhosted.org/packages/c9/d2/935039c20e06f615d9ca6ca0ab756cf8408a19d298ffaa08666bc18dc805/psutil-7.2.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3fce5f92c22b00cdefd1645aa58ab4877a01679e901555067b1bd77039aa589f", size = 130133 }, + { url = "https://files.pythonhosted.org/packages/77/69/19f1eb0e01d24c2b3eacbc2f78d3b5add8a89bf0bb69465bc8d563cc33de/psutil-7.2.1-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93f3f7b0bb07711b49626e7940d6fe52aa9940ad86e8f7e74842e73189712129", size = 181518 }, + { url = "https://files.pythonhosted.org/packages/e1/6d/7e18b1b4fa13ad370787626c95887b027656ad4829c156bb6569d02f3262/psutil-7.2.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d34d2ca888208eea2b5c68186841336a7f5e0b990edec929be909353a202768a", size = 184348 }, + { url = "https://files.pythonhosted.org/packages/98/60/1672114392dd879586d60dd97896325df47d9a130ac7401318005aab28ec/psutil-7.2.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2ceae842a78d1603753561132d5ad1b2f8a7979cb0c283f5b52fb4e6e14b1a79", size = 140400 }, + { url = "https://files.pythonhosted.org/packages/fb/7b/d0e9d4513c46e46897b46bcfc410d51fc65735837ea57a25170f298326e6/psutil-7.2.1-cp314-cp314t-win_arm64.whl", hash = "sha256:08a2f175e48a898c8eb8eace45ce01777f4785bc744c90aa2cc7f2fa5462a266", size = 135430 }, + { url = "https://files.pythonhosted.org/packages/c5/cf/5180eb8c8bdf6a503c6919f1da28328bd1e6b3b1b5b9d5b01ae64f019616/psutil-7.2.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b2e953fcfaedcfbc952b44744f22d16575d3aa78eb4f51ae74165b4e96e55f42", size = 128137 }, + { url = "https://files.pythonhosted.org/packages/c5/2c/78e4a789306a92ade5000da4f5de3255202c534acdadc3aac7b5458fadef/psutil-7.2.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:05cc68dbb8c174828624062e73078e7e35406f4ca2d0866c272c2410d8ef06d1", size = 128947 }, + { url = "https://files.pythonhosted.org/packages/29/f8/40e01c350ad9a2b3cb4e6adbcc8a83b17ee50dd5792102b6142385937db5/psutil-7.2.1-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e38404ca2bb30ed7267a46c02f06ff842e92da3bb8c5bfdadbd35a5722314d8", size = 154694 }, + { url = "https://files.pythonhosted.org/packages/06/e4/b751cdf839c011a9714a783f120e6a86b7494eb70044d7d81a25a5cd295f/psutil-7.2.1-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab2b98c9fc19f13f59628d94df5cc4cc4844bc572467d113a8b517d634e362c6", size = 156136 }, + { url = "https://files.pythonhosted.org/packages/44/ad/bbf6595a8134ee1e94a4487af3f132cef7fce43aef4a93b49912a48c3af7/psutil-7.2.1-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f78baafb38436d5a128f837fab2d92c276dfb48af01a240b861ae02b2413ada8", size = 148108 }, + { url = "https://files.pythonhosted.org/packages/1c/15/dd6fd869753ce82ff64dcbc18356093471a5a5adf4f77ed1f805d473d859/psutil-7.2.1-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:99a4cd17a5fdd1f3d014396502daa70b5ec21bf4ffe38393e152f8e449757d67", size = 147402 }, + { url = "https://files.pythonhosted.org/packages/34/68/d9317542e3f2b180c4306e3f45d3c922d7e86d8ce39f941bb9e2e9d8599e/psutil-7.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:b1b0671619343aa71c20ff9767eced0483e4fc9e1f489d50923738caf6a03c17", size = 136938 }, + { url = "https://files.pythonhosted.org/packages/3e/73/2ce007f4198c80fcf2cb24c169884f833fe93fbc03d55d302627b094ee91/psutil-7.2.1-cp37-abi3-win_arm64.whl", hash = "sha256:0d67c1822c355aa6f7314d92018fb4268a76668a536f133599b91edd48759442", size = 133836 }, +] + [[package]] name = "py-key-value-aio" version = "0.3.0" @@ -2082,6 +2529,58 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/e4/b8b0a03ece72f47dce2307d36e1c34725b7223d209fc679315ffe6a4e2c3/py_key_value_shared-0.3.0-py3-none-any.whl", hash = "sha256:5b0efba7ebca08bb158b1e93afc2f07d30b8f40c2fc12ce24a4c0d84f42f9298", size = 19560 }, ] +[[package]] +name = "pyarrow" +version = "23.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/33/ffd9c3eb087fa41dd79c3cf20c4c0ae3cdb877c4f8e1107a446006344924/pyarrow-23.0.0.tar.gz", hash = "sha256:180e3150e7edfcd182d3d9afba72f7cf19839a497cc76555a8dce998a8f67615", size = 1167185 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/bd/c861d020831ee57609b73ea721a617985ece817684dc82415b0bc3e03ac3/pyarrow-23.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:5961a9f646c232697c24f54d3419e69b4261ba8a8b66b0ac54a1851faffcbab8", size = 34189116 }, + { url = "https://files.pythonhosted.org/packages/8c/23/7725ad6cdcbaf6346221391e7b3eecd113684c805b0a95f32014e6fa0736/pyarrow-23.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:632b3e7c3d232f41d64e1a4a043fb82d44f8a349f339a1188c6a0dd9d2d47d8a", size = 35803831 }, + { url = "https://files.pythonhosted.org/packages/57/06/684a421543455cdc2944d6a0c2cc3425b028a4c6b90e34b35580c4899743/pyarrow-23.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:76242c846db1411f1d6c2cc3823be6b86b40567ee24493344f8226ba34a81333", size = 44436452 }, + { url = "https://files.pythonhosted.org/packages/c6/6f/8f9eb40c2328d66e8b097777ddcf38494115ff9f1b5bc9754ba46991191e/pyarrow-23.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b73519f8b52ae28127000986bf228fda781e81d3095cd2d3ece76eb5cf760e1b", size = 47557396 }, + { url = "https://files.pythonhosted.org/packages/10/6e/f08075f1472e5159553501fde2cc7bc6700944bdabe49a03f8a035ee6ccd/pyarrow-23.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:068701f6823449b1b6469120f399a1239766b117d211c5d2519d4ed5861f75de", size = 48147129 }, + { url = "https://files.pythonhosted.org/packages/7d/82/d5a680cd507deed62d141cc7f07f7944a6766fc51019f7f118e4d8ad0fb8/pyarrow-23.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1801ba947015d10e23bca9dd6ef5d0e9064a81569a89b6e9a63b59224fd060df", size = 50596642 }, + { url = "https://files.pythonhosted.org/packages/a9/26/4f29c61b3dce9fa7780303b86895ec6a0917c9af927101daaaf118fbe462/pyarrow-23.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:52265266201ec25b6839bf6bd4ea918ca6d50f31d13e1cf200b4261cd11dc25c", size = 27660628 }, + { url = "https://files.pythonhosted.org/packages/66/34/564db447d083ec7ff93e0a883a597d2f214e552823bfc178a2d0b1f2c257/pyarrow-23.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:ad96a597547af7827342ffb3c503c8316e5043bb09b47a84885ce39394c96e00", size = 34184630 }, + { url = "https://files.pythonhosted.org/packages/aa/3a/3999daebcb5e6119690c92a621c4d78eef2ffba7a0a1b56386d2875fcd77/pyarrow-23.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:b9edf990df77c2901e79608f08c13fbde60202334a4fcadb15c1f57bf7afee43", size = 35796820 }, + { url = "https://files.pythonhosted.org/packages/ec/ee/39195233056c6a8d0976d7d1ac1cd4fe21fb0ec534eca76bc23ef3f60e11/pyarrow-23.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:36d1b5bc6ddcaff0083ceec7e2561ed61a51f49cce8be079ee8ed406acb6fdef", size = 44438735 }, + { url = "https://files.pythonhosted.org/packages/2c/41/6a7328ee493527e7afc0c88d105ecca69a3580e29f2faaeac29308369fd7/pyarrow-23.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4292b889cd224f403304ddda8b63a36e60f92911f89927ec8d98021845ea21be", size = 47557263 }, + { url = "https://files.pythonhosted.org/packages/c6/ee/34e95b21ee84db494eae60083ddb4383477b31fb1fd19fd866d794881696/pyarrow-23.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dfd9e133e60eaa847fd80530a1b89a052f09f695d0b9c34c235ea6b2e0924cf7", size = 48153529 }, + { url = "https://files.pythonhosted.org/packages/52/88/8a8d83cea30f4563efa1b7bf51d241331ee5cd1b185a7e063f5634eca415/pyarrow-23.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832141cc09fac6aab1cd3719951d23301396968de87080c57c9a7634e0ecd068", size = 50598851 }, + { url = "https://files.pythonhosted.org/packages/c6/4c/2929c4be88723ba025e7b3453047dc67e491c9422965c141d24bab6b5962/pyarrow-23.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:7a7d067c9a88faca655c71bcc30ee2782038d59c802d57950826a07f60d83c4c", size = 27577747 }, + { url = "https://files.pythonhosted.org/packages/64/52/564a61b0b82d72bd68ec3aef1adda1e3eba776f89134b9ebcb5af4b13cb6/pyarrow-23.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:ce9486e0535a843cf85d990e2ec5820a47918235183a5c7b8b97ed7e92c2d47d", size = 34446038 }, + { url = "https://files.pythonhosted.org/packages/cc/c9/232d4f9855fd1de0067c8a7808a363230d223c83aeee75e0fe6eab851ba9/pyarrow-23.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:075c29aeaa685fd1182992a9ed2499c66f084ee54eea47da3eb76e125e06064c", size = 35921142 }, + { url = "https://files.pythonhosted.org/packages/96/f2/60af606a3748367b906bb82d41f0032e059f075444445d47e32a7ff1df62/pyarrow-23.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:799965a5379589510d888be3094c2296efd186a17ca1cef5b77703d4d5121f53", size = 44490374 }, + { url = "https://files.pythonhosted.org/packages/ff/2d/7731543050a678ea3a413955a2d5d80d2a642f270aa57a3cb7d5a86e3f46/pyarrow-23.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:ef7cac8fe6fccd8b9e7617bfac785b0371a7fe26af59463074e4882747145d40", size = 47527896 }, + { url = "https://files.pythonhosted.org/packages/5a/90/f3342553b7ac9879413aed46500f1637296f3c8222107523a43a1c08b42a/pyarrow-23.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15a414f710dc927132dd67c361f78c194447479555af57317066ee5116b90e9e", size = 48210401 }, + { url = "https://files.pythonhosted.org/packages/f3/da/9862ade205ecc46c172b6ce5038a74b5151c7401e36255f15975a45878b2/pyarrow-23.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3e0d2e6915eca7d786be6a77bf227fbc06d825a75b5b5fe9bcbef121dec32685", size = 50579677 }, + { url = "https://files.pythonhosted.org/packages/c2/4c/f11f371f5d4740a5dafc2e11c76bcf42d03dfdb2d68696da97de420b6963/pyarrow-23.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:4b317ea6e800b5704e5e5929acb6e2dc13e9276b708ea97a39eb8b345aa2658b", size = 27631889 }, + { url = "https://files.pythonhosted.org/packages/97/bb/15aec78bcf43a0c004067bd33eb5352836a29a49db8581fc56f2b6ca88b7/pyarrow-23.0.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:20b187ed9550d233a872074159f765f52f9d92973191cd4b93f293a19efbe377", size = 34213265 }, + { url = "https://files.pythonhosted.org/packages/f6/6c/deb2c594bbba41c37c5d9aa82f510376998352aa69dfcb886cb4b18ad80f/pyarrow-23.0.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:18ec84e839b493c3886b9b5e06861962ab4adfaeb79b81c76afbd8d84c7d5fda", size = 35819211 }, + { url = "https://files.pythonhosted.org/packages/e0/e5/ee82af693cb7b5b2b74f6524cdfede0e6ace779d7720ebca24d68b57c36b/pyarrow-23.0.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:e438dd3f33894e34fd02b26bd12a32d30d006f5852315f611aa4add6c7fab4bc", size = 44502313 }, + { url = "https://files.pythonhosted.org/packages/9c/86/95c61ad82236495f3c31987e85135926ba3ec7f3819296b70a68d8066b49/pyarrow-23.0.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:a244279f240c81f135631be91146d7fa0e9e840e1dfed2aba8483eba25cd98e6", size = 47585886 }, + { url = "https://files.pythonhosted.org/packages/bb/6e/a72d901f305201802f016d015de1e05def7706fff68a1dedefef5dc7eff7/pyarrow-23.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c4692e83e42438dba512a570c6eaa42be2f8b6c0f492aea27dec54bdc495103a", size = 48207055 }, + { url = "https://files.pythonhosted.org/packages/f9/e5/5de029c537630ca18828db45c30e2a78da03675a70ac6c3528203c416fe3/pyarrow-23.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae7f30f898dfe44ea69654a35c93e8da4cef6606dc4c72394068fd95f8e9f54a", size = 50619812 }, + { url = "https://files.pythonhosted.org/packages/59/8d/2af846cd2412e67a087f5bda4a8e23dfd4ebd570f777db2e8686615dafc1/pyarrow-23.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:5b86bb649e4112fb0614294b7d0a175c7513738876b89655605ebb87c804f861", size = 28263851 }, + { url = "https://files.pythonhosted.org/packages/7b/7f/caab863e587041156f6786c52e64151b7386742c8c27140f637176e9230e/pyarrow-23.0.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:ebc017d765d71d80a3f8584ca0566b53e40464586585ac64176115baa0ada7d3", size = 34463240 }, + { url = "https://files.pythonhosted.org/packages/c9/fa/3a5b8c86c958e83622b40865e11af0857c48ec763c11d472c87cd518283d/pyarrow-23.0.0-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:0800cc58a6d17d159df823f87ad66cefebf105b982493d4bad03ee7fab84b993", size = 35935712 }, + { url = "https://files.pythonhosted.org/packages/c5/08/17a62078fc1a53decb34a9aa79cf9009efc74d63d2422e5ade9fed2f99e3/pyarrow-23.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:3a7c68c722da9bb5b0f8c10e3eae71d9825a4b429b40b32709df5d1fa55beb3d", size = 44503523 }, + { url = "https://files.pythonhosted.org/packages/cc/70/84d45c74341e798aae0323d33b7c39194e23b1abc439ceaf60a68a7a969a/pyarrow-23.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:bd5556c24622df90551063ea41f559b714aa63ca953db884cfb958559087a14e", size = 47542490 }, + { url = "https://files.pythonhosted.org/packages/61/d9/d1274b0e6f19e235de17441e53224f4716574b2ca837022d55702f24d71d/pyarrow-23.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:54810f6e6afc4ffee7c2e0051b61722fbea9a4961b46192dcfae8ea12fa09059", size = 48233605 }, + { url = "https://files.pythonhosted.org/packages/39/07/e4e2d568cb57543d84482f61e510732820cddb0f47c4bb7df629abfed852/pyarrow-23.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:14de7d48052cf4b0ed174533eafa3cfe0711b8076ad70bede32cf59f744f0d7c", size = 50603979 }, + { url = "https://files.pythonhosted.org/packages/72/9c/47693463894b610f8439b2e970b82ef81e9599c757bf2049365e40ff963c/pyarrow-23.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:427deac1f535830a744a4f04a6ac183a64fcac4341b3f618e693c41b7b98d2b0", size = 28338905 }, +] + +[[package]] +name = "pyasn1" +version = "0.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/b6/6e630dff89739fcd427e3f72b3d905ce0acb85a45d4ec3e2678718a3487f/pyasn1-0.6.2.tar.gz", hash = "sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b", size = 146586 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/b5/a96872e5184f354da9c84ae119971a0a4c221fe9b27a4d94bd43f2596727/pyasn1-0.6.2-py3-none-any.whl", hash = "sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf", size = 83371 }, +] + [[package]] name = "pycparser" version = "2.23" @@ -2273,6 +2772,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/df/80/fc9d01d5ed37ba4c42ca2b55b4339ae6e200b456be3a1aaddf4a9fa99b8c/pyperclip-1.11.0-py3-none-any.whl", hash = "sha256:299403e9ff44581cb9ba2ffeed69c7aa96a008622ad0c46cb575ca75b5b84273", size = 11063 }, ] +[[package]] +name = "pystache" +version = "0.6.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/89/0a712ca22930b8c71bced8703e5bb45669c31690ea81afe15f6cb284550c/pystache-0.6.8.tar.gz", hash = "sha256:3707518e6a4d26dd189b07c10c669b1fc17df72684617c327bd3550e7075c72c", size = 101892 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fa/78/ffd13a516219129cef6a754a11ba2a1c0d69f1e281af4f6bca9ed5327219/pystache-0.6.8-py3-none-any.whl", hash = "sha256:7211e000974a6e06bce2d4d5cad8df03bcfffefd367209117376e4527a1c3cb8", size = 82051 }, +] + [[package]] name = "pytest" version = "9.0.2" @@ -2775,8 +3283,8 @@ name = "secretstorage" version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography" }, - { name = "jeepney" }, + { name = "cryptography", marker = "sys_platform != 'win32'" }, + { name = "jeepney", marker = "sys_platform != 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884 } wheels = [ @@ -2846,6 +3354,66 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 }, ] +[[package]] +name = "sqlalchemy" +version = "2.0.45" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/be/f9/5e4491e5ccf42f5d9cfc663741d261b3e6e1683ae7812114e7636409fcc6/sqlalchemy-2.0.45.tar.gz", hash = "sha256:1632a4bda8d2d25703fdad6363058d882541bdaaee0e5e3ddfa0cd3229efce88", size = 9869912 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/c7/1900b56ce19bff1c26f39a4ce427faec7716c81ac792bfac8b6a9f3dca93/sqlalchemy-2.0.45-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3ee2aac15169fb0d45822983631466d60b762085bc4535cd39e66bea362df5f", size = 3333760 }, + { url = "https://files.pythonhosted.org/packages/0a/93/3be94d96bb442d0d9a60e55a6bb6e0958dd3457751c6f8502e56ef95fed0/sqlalchemy-2.0.45-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba547ac0b361ab4f1608afbc8432db669bd0819b3e12e29fb5fa9529a8bba81d", size = 3348268 }, + { url = "https://files.pythonhosted.org/packages/48/4b/f88ded696e61513595e4a9778f9d3f2bf7332cce4eb0c7cedaabddd6687b/sqlalchemy-2.0.45-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:215f0528b914e5c75ef2559f69dca86878a3beeb0c1be7279d77f18e8d180ed4", size = 3278144 }, + { url = "https://files.pythonhosted.org/packages/ed/6a/310ecb5657221f3e1bd5288ed83aa554923fb5da48d760a9f7622afeb065/sqlalchemy-2.0.45-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:107029bf4f43d076d4011f1afb74f7c3e2ea029ec82eb23d8527d5e909e97aa6", size = 3313907 }, + { url = "https://files.pythonhosted.org/packages/5c/39/69c0b4051079addd57c84a5bfb34920d87456dd4c90cf7ee0df6efafc8ff/sqlalchemy-2.0.45-cp312-cp312-win32.whl", hash = "sha256:0c9f6ada57b58420a2c0277ff853abe40b9e9449f8d7d231763c6bc30f5c4953", size = 2112182 }, + { url = "https://files.pythonhosted.org/packages/f7/4e/510db49dd89fc3a6e994bee51848c94c48c4a00dc905e8d0133c251f41a7/sqlalchemy-2.0.45-cp312-cp312-win_amd64.whl", hash = "sha256:8defe5737c6d2179c7997242d6473587c3beb52e557f5ef0187277009f73e5e1", size = 2139200 }, + { url = "https://files.pythonhosted.org/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe187fc31a54d7fd90352f34e8c008cf3ad5d064d08fedd3de2e8df83eb4a1cf", size = 3277082 }, + { url = "https://files.pythonhosted.org/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:672c45cae53ba88e0dad74b9027dddd09ef6f441e927786b05bec75d949fbb2e", size = 3293131 }, + { url = "https://files.pythonhosted.org/packages/da/4c/13dab31266fc9904f7609a5dc308a2432a066141d65b857760c3bef97e69/sqlalchemy-2.0.45-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:470daea2c1ce73910f08caf10575676a37159a6d16c4da33d0033546bddebc9b", size = 3225389 }, + { url = "https://files.pythonhosted.org/packages/74/04/891b5c2e9f83589de202e7abaf24cd4e4fa59e1837d64d528829ad6cc107/sqlalchemy-2.0.45-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9c6378449e0940476577047150fd09e242529b761dc887c9808a9a937fe990c8", size = 3266054 }, + { url = "https://files.pythonhosted.org/packages/f1/24/fc59e7f71b0948cdd4cff7a286210e86b0443ef1d18a23b0d83b87e4b1f7/sqlalchemy-2.0.45-cp313-cp313-win32.whl", hash = "sha256:4b6bec67ca45bc166c8729910bd2a87f1c0407ee955df110d78948f5b5827e8a", size = 2110299 }, + { url = "https://files.pythonhosted.org/packages/c0/c5/d17113020b2d43073412aeca09b60d2009442420372123b8d49cc253f8b8/sqlalchemy-2.0.45-cp313-cp313-win_amd64.whl", hash = "sha256:afbf47dc4de31fa38fd491f3705cac5307d21d4bb828a4f020ee59af412744ee", size = 2136264 }, + { url = "https://files.pythonhosted.org/packages/3d/8d/bb40a5d10e7a5f2195f235c0b2f2c79b0bf6e8f00c0c223130a4fbd2db09/sqlalchemy-2.0.45-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:83d7009f40ce619d483d26ac1b757dfe3167b39921379a8bd1b596cf02dab4a6", size = 3521998 }, + { url = "https://files.pythonhosted.org/packages/75/a5/346128b0464886f036c039ea287b7332a410aa2d3fb0bb5d404cb8861635/sqlalchemy-2.0.45-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d8a2ca754e5415cde2b656c27900b19d50ba076aa05ce66e2207623d3fe41f5a", size = 3473434 }, + { url = "https://files.pythonhosted.org/packages/cc/64/4e1913772646b060b025d3fc52ce91a58967fe58957df32b455de5a12b4f/sqlalchemy-2.0.45-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f46ec744e7f51275582e6a24326e10c49fbdd3fc99103e01376841213028774", size = 3272404 }, + { url = "https://files.pythonhosted.org/packages/b3/27/caf606ee924282fe4747ee4fd454b335a72a6e018f97eab5ff7f28199e16/sqlalchemy-2.0.45-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:883c600c345123c033c2f6caca18def08f1f7f4c3ebeb591a63b6fceffc95cce", size = 3277057 }, + { url = "https://files.pythonhosted.org/packages/85/d0/3d64218c9724e91f3d1574d12eb7ff8f19f937643815d8daf792046d88ab/sqlalchemy-2.0.45-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2c0b74aa79e2deade948fe8593654c8ef4228c44ba862bb7c9585c8e0db90f33", size = 3222279 }, + { url = "https://files.pythonhosted.org/packages/24/10/dd7688a81c5bc7690c2a3764d55a238c524cd1a5a19487928844cb247695/sqlalchemy-2.0.45-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8a420169cef179d4c9064365f42d779f1e5895ad26ca0c8b4c0233920973db74", size = 3244508 }, + { url = "https://files.pythonhosted.org/packages/aa/41/db75756ca49f777e029968d9c9fee338c7907c563267740c6d310a8e3f60/sqlalchemy-2.0.45-cp314-cp314-win32.whl", hash = "sha256:e50dcb81a5dfe4b7b4a4aa8f338116d127cb209559124f3694c70d6cd072b68f", size = 2113204 }, + { url = "https://files.pythonhosted.org/packages/89/a2/0e1590e9adb292b1d576dbcf67ff7df8cf55e56e78d2c927686d01080f4b/sqlalchemy-2.0.45-cp314-cp314-win_amd64.whl", hash = "sha256:4748601c8ea959e37e03d13dcda4a44837afcd1b21338e637f7c935b8da06177", size = 2138785 }, + { url = "https://files.pythonhosted.org/packages/42/39/f05f0ed54d451156bbed0e23eb0516bcad7cbb9f18b3bf219c786371b3f0/sqlalchemy-2.0.45-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd337d3526ec5298f67d6a30bbbe4ed7e5e68862f0bf6dd21d289f8d37b7d60b", size = 3522029 }, + { url = "https://files.pythonhosted.org/packages/54/0f/d15398b98b65c2bce288d5ee3f7d0a81f77ab89d9456994d5c7cc8b2a9db/sqlalchemy-2.0.45-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9a62b446b7d86a3909abbcd1cd3cc550a832f99c2bc37c5b22e1925438b9367b", size = 3475142 }, + { url = "https://files.pythonhosted.org/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl", hash = "sha256:5225a288e4c8cc2308dbdd874edad6e7d0fd38eac1e9e5f23503425c8eee20d0", size = 1936672 }, +] + +[package.optional-dependencies] +asyncio = [ + { name = "greenlet" }, +] + +[[package]] +name = "sqlean-py" +version = "3.49.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/67/eb/ac95fab0bc4658124b4ec8fbc31fc494165ab4544606ae91b9a489907dad/sqlean_py-3.49.1.tar.gz", hash = "sha256:210d89989226b988d7d6391f837387d3b81e8cd608c997e0bd37826e395970e7", size = 3319012 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/0e/95379c801907f8da939be30c61b63ef881eb18cc0a90713cc74002deaf16/sqlean_py-3.49.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:b43397ac27312a20fef8f5db0d011d3676fddea04850d6c35ad1d7644d146f71", size = 1129522 }, + { url = "https://files.pythonhosted.org/packages/65/94/b4c5d0ff47f179a0729dc71832558f63a1605e931f773b6d435a767baca9/sqlean_py-3.49.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:56a3388f4fe08e1332af424eaaf378eb9e258165885a4e284c5238e4837b2232", size = 1053757 }, + { url = "https://files.pythonhosted.org/packages/2d/11/f8a5c0f7fb889cabbd8c7f887f9e261b65bf45fa1d33a245490855bff53e/sqlean_py-3.49.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9bbc00d57f68dbb3f5dea20380bdad7fa9299b3c2a8d8b3798c2bf315146be9", size = 3003708 }, + { url = "https://files.pythonhosted.org/packages/47/84/065a21e9a578ef13d9749c2bf3c382f7e50a1644af7d7a109924fbc6faee/sqlean_py-3.49.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae92413470409b3b3678c797db82c1d247b6ed2198017b5e893d9fc0606e061f", size = 3008238 }, + { url = "https://files.pythonhosted.org/packages/e8/e5/d980bf0c5e67cfd4486b5e6d8daea6815fdac57b3d0899c23127a30283b5/sqlean_py-3.49.1-cp312-cp312-win_amd64.whl", hash = "sha256:b45ed4adb8442299019988d5e90aa1474f3ef8c71f6e8921a70705b9d971c590", size = 804506 }, + { url = "https://files.pythonhosted.org/packages/f2/d1/8828ec685022e2b86ebd717743359dd5e8eab70a9c1ebff78aa733848216/sqlean_py-3.49.1-cp312-cp312-win_arm64.whl", hash = "sha256:c2537f69879adaed22b16e840d494c440ece5b49d28a5a51094e6c8ca6a2b0a5", size = 739690 }, + { url = "https://files.pythonhosted.org/packages/c4/d3/30a7dc9f6030ea2a1c76fcbb220d1f5d95a16f22f50d4cd80c8778ca5018/sqlean_py-3.49.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:ba8e5fc5b9d6682f3fbb626e1f936a4c4ac7377c3d044beaef695e6306a9a39b", size = 1129238 }, + { url = "https://files.pythonhosted.org/packages/87/73/ccd43c0d6ca4248005687c5c1ce121924e368c0b195b98880810f468312d/sqlean_py-3.49.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3112cce35bb97f17b55419e955dc74c7deebb0b548e54d99b3e32bb3d3c62ce4", size = 1053654 }, + { url = "https://files.pythonhosted.org/packages/82/d5/cfdb8098117fff9f7856d5c86c93d9c7bebdb5801b551cfabf36e117b764/sqlean_py-3.49.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9974027675e1edf8a8c90383f95e4038052e96ef7a9a8fa7f8125ed275cc28ba", size = 3000002 }, + { url = "https://files.pythonhosted.org/packages/96/52/7e713a61ded163a5fece9fb144b60107889e5d813ba9cff278e65673b6f9/sqlean_py-3.49.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fe4e2e74c1749bf98e4aae8fb02978e4c03d4a491be18c4e5b244b29408fdf", size = 3004709 }, + { url = "https://files.pythonhosted.org/packages/c4/d6/455e75e1e540b64e230f7282ec55777e030190a486e98a2fce5d6437afa2/sqlean_py-3.49.1-cp313-cp313-win_amd64.whl", hash = "sha256:de820bdb39729044f9ed94f0addfe308b020479334146036a773f470d7594d87", size = 804300 }, + { url = "https://files.pythonhosted.org/packages/99/bf/b63830855455fd22278ddc78cc7c64dffb5e1a69c15245c18275317ae9d5/sqlean_py-3.49.1-cp313-cp313-win_arm64.whl", hash = "sha256:3c1661f2fcf4d10ec3940ef8d2146bb58260b409c9033f7a727a6962e2032b7c", size = 739448 }, +] + [[package]] name = "sse-starlette" version = "3.1.2" @@ -2861,15 +3429,31 @@ wheels = [ [[package]] name = "starlette" -version = "0.51.0" +version = "0.50.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e7/65/5a1fadcc40c5fdc7df421a7506b79633af8f5d5e3a95c3e72acacec644b9/starlette-0.51.0.tar.gz", hash = "sha256:4c4fda9b1bc67f84037d3d14a5112e523509c369d9d47b111b2f984b0cc5ba6c", size = 2647658 } +sdist = { url = "https://files.pythonhosted.org/packages/ba/b8/73a0e6a6e079a9d9cfa64113d771e421640b6f679a52eeb9b32f72d871a1/starlette-0.50.0.tar.gz", hash = "sha256:a2a17b22203254bcbc2e1f926d2d55f3f9497f769416b3190768befe598fa3ca", size = 2646985 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/52/1064f510b141bd54025f9b55105e26d1fa970b9be67ad766380a3c9b74b0/starlette-0.50.0-py3-none-any.whl", hash = "sha256:9e5391843ec9b6e472eed1365a78c8098cfceb7a74bfd4d6b1c0c0095efb3bca", size = 74033 }, +] + +[[package]] +name = "strawberry-graphql" +version = "0.287.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "graphql-core" }, + { name = "lia-web" }, + { name = "packaging" }, + { name = "python-dateutil" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e5/45/5a466ecd7503ad165ed5050e694f3a871b4df085cfaff5c357259bef0ccc/strawberry_graphql-0.287.3.tar.gz", hash = "sha256:c81126cc75102aa32417048f074429d6c5c8d096424aa939fdb8827b8c5f84a9", size = 211998 } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/c4/09985a03dba389d4fe16a9014147a7b02fa76ef3519bf5846462a485876d/starlette-0.51.0-py3-none-any.whl", hash = "sha256:fb460a3d6fd3c958d729fdd96aee297f89a51b0181f16401fe8fd4cb6129165d", size = 74133 }, + { url = "https://files.pythonhosted.org/packages/7c/8e/ffd20e179cc8218465599922660323f453c7b955aca2b909e5b86ba61eb0/strawberry_graphql-0.287.3-py3-none-any.whl", hash = "sha256:2bb1f9b122ef1213f82f01cf27a095eb0776fda78e12af9e60c54de6e543797c", size = 309183 }, ] [[package]]