From 32bde41319b09fafbc7e8a04cb76b41f1734b86d Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Wed, 5 Nov 2025 20:38:16 +0000 Subject: [PATCH 1/7] feat(adk): Implement decimal coercion in Oracle ADK store deserialization tests --- sqlspec/adapters/oracledb/adk/store.py | 182 +++++++++--------- .../test_oracledb/test_adk_store.py | 49 +++++ 2 files changed, 140 insertions(+), 91 deletions(-) create mode 100644 tests/unit/test_adapters/test_oracledb/test_adk_store.py diff --git a/sqlspec/adapters/oracledb/adk/store.py b/sqlspec/adapters/oracledb/adk/store.py index c2156e63..fe60ed0c 100644 --- a/sqlspec/adapters/oracledb/adk/store.py +++ b/sqlspec/adapters/oracledb/adk/store.py @@ -1,11 +1,17 @@ """Oracle ADK store for Google Agent Development Kit session/event storage.""" +from decimal import Decimal from enum import Enum -from typing import TYPE_CHECKING, Any, Final +from typing import TYPE_CHECKING, Any, Final, cast import oracledb from sqlspec import SQL +from sqlspec.adapters.oracledb.data_dictionary import ( + OracleAsyncDataDictionary, + OracleSyncDataDictionary, + OracleVersionInfo, +) from sqlspec.extensions.adk import BaseAsyncADKStore, BaseSyncADKStore, EventRecord, SessionRecord from sqlspec.utils.logging import get_logger from sqlspec.utils.serializers import from_json, to_json @@ -33,6 +39,41 @@ class JSONStorageType(str, Enum): BLOB_PLAIN = "blob_plain" +def _coerce_decimal_values(value: Any) -> Any: + if isinstance(value, Decimal): + return float(value) + if isinstance(value, dict): + return {key: _coerce_decimal_values(val) for key, val in value.items()} + if isinstance(value, list): + return [_coerce_decimal_values(item) for item in value] + if isinstance(value, tuple): + return tuple(_coerce_decimal_values(item) for item in value) + if isinstance(value, set): + return {_coerce_decimal_values(item) for item in value} + if isinstance(value, frozenset): + return frozenset(_coerce_decimal_values(item) for item in value) + return value + + +def _storage_type_from_version(version_info: "OracleVersionInfo | None") -> JSONStorageType: + """Determine JSON storage type based on Oracle version metadata.""" + + if version_info and version_info.supports_native_json(): + logger.info("Detected Oracle %s with compatible >= 20, using JSON_NATIVE", version_info) + return JSONStorageType.JSON_NATIVE + + if version_info and version_info.supports_json_blob(): + logger.info("Detected Oracle %s, using BLOB_JSON (recommended)", version_info) + return JSONStorageType.BLOB_JSON + + if version_info: + logger.info("Detected Oracle %s (pre-12c), using BLOB_PLAIN", version_info) + return JSONStorageType.BLOB_PLAIN + + logger.warning("Oracle version could not be detected; defaulting to BLOB_JSON storage") + return JSONStorageType.BLOB_JSON + + def _to_oracle_bool(value: "bool | None") -> "int | None": """Convert Python boolean to Oracle NUMBER(1). @@ -103,7 +144,7 @@ class OracleAsyncADKStore(BaseAsyncADKStore["OracleAsyncConfig"]): - Configuration is read from config.extension_config["adk"] """ - __slots__ = ("_in_memory", "_json_storage_type") + __slots__ = ("_in_memory", "_json_storage_type", "_oracle_version_info") def __init__(self, config: "OracleAsyncConfig") -> None: """Initialize Oracle ADK store. @@ -120,6 +161,7 @@ def __init__(self, config: "OracleAsyncConfig") -> None: """ super().__init__(config) self._json_storage_type: JSONStorageType | None = None + self._oracle_version_info: OracleVersionInfo | None = None adk_config = config.extension_config.get("adk", {}) self._in_memory: bool = bool(adk_config.get("in_memory", False)) @@ -160,44 +202,22 @@ async def _detect_json_storage_type(self) -> JSONStorageType: if self._json_storage_type is not None: return self._json_storage_type - async with self._config.provide_connection() as conn: - cursor = conn.cursor() - await cursor.execute( - """ - SELECT version FROM product_component_version - WHERE product LIKE 'Oracle%Database%' - """ - ) - row = await cursor.fetchone() - - if row is None: - logger.warning("Could not detect Oracle version, defaulting to BLOB_JSON") - self._json_storage_type = JSONStorageType.BLOB_JSON - return self._json_storage_type - - version_str = str(row[0]) - version_parts = version_str.split(".") - major_version = int(version_parts[0]) if version_parts else 0 - - if major_version >= ORACLE_MIN_JSON_NATIVE_VERSION: - await cursor.execute("SELECT value FROM v$parameter WHERE name = 'compatible'") - compatible_row = await cursor.fetchone() - if compatible_row: - compatible_parts = str(compatible_row[0]).split(".") - compatible_major = int(compatible_parts[0]) if compatible_parts else 0 - if compatible_major >= ORACLE_MIN_JSON_NATIVE_COMPATIBLE: - logger.info("Detected Oracle %s with compatible >= 20, using JSON_NATIVE", version_str) - self._json_storage_type = JSONStorageType.JSON_NATIVE - return self._json_storage_type - - if major_version >= ORACLE_MIN_JSON_BLOB_VERSION: - logger.info("Detected Oracle %s, using BLOB_JSON (recommended)", version_str) - self._json_storage_type = JSONStorageType.BLOB_JSON - return self._json_storage_type - - logger.info("Detected Oracle %s (pre-12c), using BLOB_PLAIN", version_str) - self._json_storage_type = JSONStorageType.BLOB_PLAIN - return self._json_storage_type + version_info = await self._get_version_info() + self._json_storage_type = _storage_type_from_version(version_info) + return self._json_storage_type + + async def _get_version_info(self) -> "OracleVersionInfo | None": + """Return cached Oracle version info, querying via data dictionary if needed.""" + + if self._oracle_version_info is not None: + return self._oracle_version_info + + async with self._config.provide_session() as driver: + data_dictionary = OracleAsyncDataDictionary() + self._oracle_version_info = await data_dictionary.get_version(driver) + if self._oracle_version_info is None: + logger.warning("Could not detect Oracle version, defaulting to BLOB_JSON storage") + return self._oracle_version_info async def _serialize_state(self, state: "dict[str, Any]") -> "str | bytes": """Serialize state dictionary to appropriate format based on storage type. @@ -232,7 +252,7 @@ async def _deserialize_state(self, data: Any) -> "dict[str, Any]": data = await data.read() if isinstance(data, dict): - return data + return cast("dict[str, Any]", _coerce_decimal_values(data)) if isinstance(data, bytes): return from_json(data) # type: ignore[no-any-return] @@ -280,7 +300,7 @@ async def _deserialize_json_field(self, data: Any) -> "dict[str, Any] | None": data = await data.read() if isinstance(data, dict): - return data + return cast("dict[str, Any]", _coerce_decimal_values(data)) if isinstance(data, bytes): return from_json(data) # type: ignore[no-any-return] @@ -490,7 +510,7 @@ async def create_tables(self) -> None: Uses version-appropriate table schema. """ storage_type = await self._detect_json_storage_type() - logger.info("Creating ADK tables with storage type: %s", storage_type) + logger.debug("Creating ADK tables with storage type: %s", storage_type) async with self._config.provide_session() as driver: await driver.execute_script(self._get_create_sessions_table_sql_for_type(storage_type)) @@ -561,16 +581,17 @@ async def get_session(self, session_id: str) -> "SessionRecord | None": State is deserialized using version-appropriate format. """ - sql = f""" - SELECT id, app_name, user_id, state, create_time, update_time - FROM {self._session_table} - WHERE id = :id - """ - try: async with self._config.provide_connection() as conn: cursor = conn.cursor() - await cursor.execute(sql, {"id": session_id}) + await cursor.execute( + f""" + SELECT id, app_name, user_id, state, create_time, update_time + FROM {self._session_table} + WHERE id = :id + """, + {"id": session_id}, + ) row = await cursor.fetchone() if row is None: @@ -881,7 +902,7 @@ class OracleSyncADKStore(BaseSyncADKStore["OracleSyncConfig"]): - Configuration is read from config.extension_config["adk"] """ - __slots__ = ("_in_memory", "_json_storage_type") + __slots__ = ("_in_memory", "_json_storage_type", "_oracle_version_info") def __init__(self, config: "OracleSyncConfig") -> None: """Initialize Oracle synchronous ADK store. @@ -898,6 +919,7 @@ def __init__(self, config: "OracleSyncConfig") -> None: """ super().__init__(config) self._json_storage_type: JSONStorageType | None = None + self._oracle_version_info: OracleVersionInfo | None = None adk_config = config.extension_config.get("adk", {}) self._in_memory: bool = bool(adk_config.get("in_memory", False)) @@ -938,44 +960,22 @@ def _detect_json_storage_type(self) -> JSONStorageType: if self._json_storage_type is not None: return self._json_storage_type - with self._config.provide_connection() as conn: - cursor = conn.cursor() - cursor.execute( - """ - SELECT version FROM product_component_version - WHERE product LIKE 'Oracle%Database%' - """ - ) - row = cursor.fetchone() - - if row is None: - logger.warning("Could not detect Oracle version, defaulting to BLOB_JSON") - self._json_storage_type = JSONStorageType.BLOB_JSON - return self._json_storage_type - - version_str = str(row[0]) - version_parts = version_str.split(".") - major_version = int(version_parts[0]) if version_parts else 0 - - if major_version >= ORACLE_MIN_JSON_NATIVE_VERSION: - cursor.execute("SELECT value FROM v$parameter WHERE name = 'compatible'") - compatible_row = cursor.fetchone() - if compatible_row: - compatible_parts = str(compatible_row[0]).split(".") - compatible_major = int(compatible_parts[0]) if compatible_parts else 0 - if compatible_major >= ORACLE_MIN_JSON_NATIVE_COMPATIBLE: - logger.info("Detected Oracle %s with compatible >= 20, using JSON_NATIVE", version_str) - self._json_storage_type = JSONStorageType.JSON_NATIVE - return self._json_storage_type - - if major_version >= ORACLE_MIN_JSON_BLOB_VERSION: - logger.info("Detected Oracle %s, using BLOB_JSON (recommended)", version_str) - self._json_storage_type = JSONStorageType.BLOB_JSON - return self._json_storage_type - - logger.info("Detected Oracle %s (pre-12c), using BLOB_PLAIN", version_str) - self._json_storage_type = JSONStorageType.BLOB_PLAIN - return self._json_storage_type + version_info = self._get_version_info() + self._json_storage_type = _storage_type_from_version(version_info) + return self._json_storage_type + + def _get_version_info(self) -> "OracleVersionInfo | None": + """Return cached Oracle version info for sync store.""" + + if self._oracle_version_info is not None: + return self._oracle_version_info + + with self._config.provide_session() as driver: + data_dictionary = OracleSyncDataDictionary() + self._oracle_version_info = data_dictionary.get_version(driver) + if self._oracle_version_info is None: + logger.warning("Could not detect Oracle version, defaulting to BLOB_JSON storage") + return self._oracle_version_info def _serialize_state(self, state: "dict[str, Any]") -> "str | bytes": """Serialize state dictionary to appropriate format based on storage type. @@ -1010,7 +1010,7 @@ def _deserialize_state(self, data: Any) -> "dict[str, Any]": data = data.read() if isinstance(data, dict): - return data + return cast("dict[str, Any]", _coerce_decimal_values(data)) if isinstance(data, bytes): return from_json(data) # type: ignore[no-any-return] @@ -1058,7 +1058,7 @@ def _deserialize_json_field(self, data: Any) -> "dict[str, Any] | None": data = data.read() if isinstance(data, dict): - return data + return cast("dict[str, Any]", _coerce_decimal_values(data)) if isinstance(data, bytes): return from_json(data) # type: ignore[no-any-return] diff --git a/tests/unit/test_adapters/test_oracledb/test_adk_store.py b/tests/unit/test_adapters/test_oracledb/test_adk_store.py new file mode 100644 index 00000000..c206ec1c --- /dev/null +++ b/tests/unit/test_adapters/test_oracledb/test_adk_store.py @@ -0,0 +1,49 @@ +"""Tests for Oracle ADK store Decimal coercion.""" + +from decimal import Decimal + +import pytest + +from sqlspec.adapters.oracledb.adk.store import OracleAsyncADKStore, OracleSyncADKStore + + +@pytest.mark.asyncio +async def test_oracle_async_adk_store_deserialize_dict_coerces_decimal() -> None: + store = OracleAsyncADKStore.__new__(OracleAsyncADKStore) # type: ignore[call-arg] + + payload = {"value": Decimal("1.25"), "nested": {"score": Decimal("0.5")}} + + result = await store._deserialize_json_field(payload) # type: ignore[attr-defined] + + assert result == {"value": 1.25, "nested": {"score": 0.5}} + + +@pytest.mark.asyncio +async def test_oracle_async_adk_store_deserialize_state_dict_coerces_decimal() -> None: + store = OracleAsyncADKStore.__new__(OracleAsyncADKStore) # type: ignore[call-arg] + + payload = {"state": Decimal("2.0")} + + result = await store._deserialize_state(payload) # type: ignore[attr-defined] + + assert result == {"state": 2.0} + + +def test_oracle_sync_adk_store_deserialize_dict_coerces_decimal() -> None: + store = OracleSyncADKStore.__new__(OracleSyncADKStore) # type: ignore[call-arg] + + payload = {"value": Decimal("3.14"), "items": [Decimal("1.0"), Decimal("2.0")]} + + result = store._deserialize_json_field(payload) # type: ignore[attr-defined] + + assert result == {"value": 3.14, "items": [1.0, 2.0]} + + +def test_oracle_sync_adk_store_deserialize_state_dict_coerces_decimal() -> None: + store = OracleSyncADKStore.__new__(OracleSyncADKStore) # type: ignore[call-arg] + + payload = {"state": Decimal("5.0")} + + result = store._deserialize_state(payload) # type: ignore[attr-defined] + + assert result == {"state": 5.0} From 106fbe21ee2d0ef345d4876c0c3d91ebaa783de0 Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Wed, 5 Nov 2025 21:40:18 +0000 Subject: [PATCH 2/7] feat: Update version info retrieval to use Oracle data dictionary in async and sync stores --- sqlspec/adapters/oracledb/adk/store.py | 16 ++++++++++------ sqlspec/core/parameters/_validator.py | 10 +++++----- tests/unit/test_core/test_parameters.py | 2 ++ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/sqlspec/adapters/oracledb/adk/store.py b/sqlspec/adapters/oracledb/adk/store.py index fe60ed0c..32a0a082 100644 --- a/sqlspec/adapters/oracledb/adk/store.py +++ b/sqlspec/adapters/oracledb/adk/store.py @@ -207,16 +207,18 @@ async def _detect_json_storage_type(self) -> JSONStorageType: return self._json_storage_type async def _get_version_info(self) -> "OracleVersionInfo | None": - """Return cached Oracle version info, querying via data dictionary if needed.""" + """Return cached Oracle version info using Oracle data dictionary.""" if self._oracle_version_info is not None: return self._oracle_version_info async with self._config.provide_session() as driver: - data_dictionary = OracleAsyncDataDictionary() - self._oracle_version_info = await data_dictionary.get_version(driver) + dictionary = OracleAsyncDataDictionary() + self._oracle_version_info = await dictionary.get_version(driver) + if self._oracle_version_info is None: logger.warning("Could not detect Oracle version, defaulting to BLOB_JSON storage") + return self._oracle_version_info async def _serialize_state(self, state: "dict[str, Any]") -> "str | bytes": @@ -965,16 +967,18 @@ def _detect_json_storage_type(self) -> JSONStorageType: return self._json_storage_type def _get_version_info(self) -> "OracleVersionInfo | None": - """Return cached Oracle version info for sync store.""" + """Return cached Oracle version info using Oracle data dictionary.""" if self._oracle_version_info is not None: return self._oracle_version_info with self._config.provide_session() as driver: - data_dictionary = OracleSyncDataDictionary() - self._oracle_version_info = data_dictionary.get_version(driver) + dictionary = OracleSyncDataDictionary() + self._oracle_version_info = dictionary.get_version(driver) + if self._oracle_version_info is None: logger.warning("Could not detect Oracle version, defaulting to BLOB_JSON storage") + return self._oracle_version_info def _serialize_state(self, state: "dict[str, Any]") -> "str | bytes": diff --git a/sqlspec/core/parameters/_validator.py b/sqlspec/core/parameters/_validator.py index af4c069e..6fa131d5 100644 --- a/sqlspec/core/parameters/_validator.py +++ b/sqlspec/core/parameters/_validator.py @@ -20,11 +20,11 @@ (?P::(?P\w+)) | (?P%\((?P\w+)\)s) | (?P%s) | - (?P:(?P\d+)) | - (?P:(?P\w+)) | - (?P@(?P\w+)) | - (?P\$(?P\d+)) | - (?P\$(?P\w+)) | + (?P(?\d+)) | + (?P(?\w+)) | + (?P(?\w+)) | + (?P(?\d+)) | + (?P(?\w+)) | (?P\?) """, re.VERBOSE | re.IGNORECASE | re.MULTILINE | re.DOTALL, diff --git a/tests/unit/test_core/test_parameters.py b/tests/unit/test_core/test_parameters.py index 80f96aa6..1248de4b 100644 --- a/tests/unit/test_core/test_parameters.py +++ b/tests/unit/test_core/test_parameters.py @@ -669,6 +669,8 @@ def test_extract_parameters( ("SELECT * FROM json WHERE data ?| array['key']", True), ("SELECT * FROM json WHERE data ?& array['key']", True), ("SELECT * FROM users WHERE id::int = 5", False), + ("SELECT * FROM v$version", True), + ('SELECT * FROM "V$VERSION"', True), ], ) def test_extract_parameters_ignores_special_cases( From 6cb7041e859103822a6becceb08edf6034ade82d Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Wed, 5 Nov 2025 21:42:46 +0000 Subject: [PATCH 3/7] feat: Enhance PARAMETER_REGEX to support SQL Server global variables and add performance tests --- sqlspec/core/parameters/_validator.py | 2 + .../test_parameter_regex_performance.py | 206 ++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 tests/unit/test_core/test_parameter_regex_performance.py diff --git a/sqlspec/core/parameters/_validator.py b/sqlspec/core/parameters/_validator.py index 6fa131d5..7bc12ebd 100644 --- a/sqlspec/core/parameters/_validator.py +++ b/sqlspec/core/parameters/_validator.py @@ -18,6 +18,7 @@ (?P/\*(?:[^*]|\*(?!/))*\*/) | (?P\?\?|\?\||\?&) | (?P::(?P\w+)) | + (?P@@(?P\w+)) | (?P%\((?P\w+)\)s) | (?P%s) | (?P(?\d+)) | @@ -85,6 +86,7 @@ def extract_parameters(self, sql: str) -> "list[ParameterInfo]": "block_comment", "pg_q_operator", "pg_cast", + "sql_server_global", ) for match in PARAMETER_REGEX.finditer(sql): diff --git a/tests/unit/test_core/test_parameter_regex_performance.py b/tests/unit/test_core/test_parameter_regex_performance.py new file mode 100644 index 00000000..67cbc76b --- /dev/null +++ b/tests/unit/test_core/test_parameter_regex_performance.py @@ -0,0 +1,206 @@ +"""Performance and edge case tests for PARAMETER_REGEX. + +Tests regex efficiency, order dependency, and edge cases across all SQL dialects. +""" + +import time + +from sqlspec.core.parameters import ParameterValidator + + +class TestParameterRegexPerformance: + """Test parameter regex performance and correctness.""" + + def test_oracle_system_views_not_detected_as_parameters(self) -> None: + """Verify Oracle system views with $ are not detected as parameters.""" + validator = ParameterValidator() + + # Oracle system views should NOT be detected as parameters + test_cases = [ + ("SELECT * FROM v$version", []), + ("SELECT * FROM v$session WHERE sid = :sid", ["sid"]), + ("SELECT * FROM v$database, v$instance", []), + ("SELECT banner FROM v$version WHERE banner LIKE :pattern", ["pattern"]), + ("SELECT * FROM gv$session WHERE inst_id = :inst", ["inst"]), + ] + + for sql, expected_params in test_cases: + params = validator.extract_parameters(sql) + param_names = [p.name for p in params if p.name is not None] + assert param_names == expected_params, f"Failed for: {sql}" + + def test_sql_server_global_variables_not_detected(self) -> None: + """Verify SQL Server @@variables are not detected as parameters.""" + validator = ParameterValidator() + + test_cases = [ + ("SELECT @@VERSION", []), + ("SELECT @@IDENTITY", []), + ("SELECT @@ROWCOUNT, @param", ["param"]), + ("IF @@ERROR <> 0 SELECT @value", ["value"]), + ] + + for sql, expected_params in test_cases: + params = validator.extract_parameters(sql) + param_names = [p.name for p in params if p.name is not None] + assert param_names == expected_params, f"Failed for: {sql}" + + def test_postgres_dollar_quoted_strings_not_detected(self) -> None: + """Verify PostgreSQL dollar-quoted strings don't create false parameters.""" + validator = ParameterValidator() + + test_cases = [ + ("SELECT $$hello$$", []), + ("SELECT $tag$world$tag$", []), + ("SELECT $$value:123$$, :param", ["param"]), + ("SELECT $func$SELECT $1$func$, $1", ["1"]), + ] + + for sql, expected_params in test_cases: + params = validator.extract_parameters(sql) + param_names = [p.name for p in params if p.name is not None] + assert param_names == expected_params, f"Failed for: {sql}" + + def test_xml_namespaces_not_detected(self) -> None: + """Verify XML namespaces with colons are not detected as parameters.""" + validator = ParameterValidator() + + test_cases = [ + ("SELECT 'data'", []), + ("SELECT '' WHERE id = :id", ["id"]), + ("UPDATE xml SET data = '' WHERE id = :id", ["id"]), + ] + + for sql, expected_params in test_cases: + params = validator.extract_parameters(sql) + param_names = [p.name for p in params if p.name is not None] + assert param_names == expected_params, f"Failed for: {sql}" + + def test_parameter_order_precedence(self) -> None: + """Verify parameter detection order is correct.""" + validator = ParameterValidator() + + # Positional colon (:1, :2) MUST be detected before named colon (:name) + params = validator.extract_parameters("SELECT :1, :name, :123, :user") + assert len(params) == 4 + assert params[0].name == "1" + assert params[1].name == "name" + assert params[2].name == "123" + assert params[3].name == "user" + + def test_mixed_identifiers_and_parameters(self) -> None: + """Test SQL with identifiers that contain parameter-like characters.""" + validator = ParameterValidator() + + test_cases = [ + # Table names with special chars (not detected due to negative lookbehind) + ("SELECT * FROM user$data WHERE id = :id", ["id"]), + ("SELECT * FROM price@2023 WHERE amount > @amount", ["amount"]), + ("SELECT * FROM log:entry WHERE time = :time", ["time"]), + + # Column names - NOTE: @column IS detected as parameter in SQL Server + # This is correct behavior - if you write SELECT @var, it's a parameter + ("SELECT user$id, :param FROM table", ["param"]), + # @@VERSION is skipped, but @column and @param are detected (correct!) + ("SELECT @column, @@VERSION, @param FROM t", ["column", "param"]), + ] + + for sql, expected_params in test_cases: + params = validator.extract_parameters(sql) + param_names = [p.name for p in params if p.name is not None] + assert param_names == expected_params, f"Failed for: {sql}" + + def test_all_dialect_parameter_styles(self) -> None: + """Comprehensive test of all supported parameter styles.""" + validator = ParameterValidator() + + dialect_tests = { + "qmark": ("SELECT * FROM t WHERE a = ? AND b = ?", [None, None]), + "numeric": ("SELECT * FROM t WHERE a = $1 AND b = $2", ["1", "2"]), + "named_dollar": ("SELECT * FROM t WHERE a = $foo AND b = $bar", ["foo", "bar"]), + "named_colon": ("SELECT * FROM t WHERE a = :foo AND b = :bar", ["foo", "bar"]), + "positional_colon": ("SELECT * FROM t WHERE a = :1 AND b = :2", ["1", "2"]), + "named_at": ("SELECT * FROM t WHERE a = @foo AND b = @bar", ["foo", "bar"]), + "pyformat_named": ("SELECT * FROM t WHERE a = %(foo)s AND b = %(bar)s", ["foo", "bar"]), + "pyformat_pos": ("SELECT * FROM t WHERE a = %s AND b = %s", [None, None]), + } + + for style, (sql, expected) in dialect_tests.items(): + params = validator.extract_parameters(sql) + param_names = [p.name for p in params] + assert param_names == expected, f"Failed for {style}: {sql}" + + def test_regex_performance_on_large_sql(self) -> None: + """Benchmark regex performance on large SQL statements.""" + validator = ParameterValidator() + + # Generate large SQL with many parameters + large_sql = "SELECT * FROM t WHERE " + " AND ".join([f"col{i} = :param{i}" for i in range(1000)]) + + start = time.perf_counter() + params = validator.extract_parameters(large_sql) + elapsed = time.perf_counter() - start + + assert len(params) == 1000 + assert elapsed < 0.1, f"Regex took too long: {elapsed:.4f}s" # Should be <100ms + + # Test cache hit (should be much faster) + start = time.perf_counter() + params_cached = validator.extract_parameters(large_sql) + elapsed_cached = time.perf_counter() - start + + assert len(params_cached) == 1000 + assert elapsed_cached < 0.001, f"Cache lookup too slow: {elapsed_cached:.6f}s" # Should be <1ms + + def test_no_catastrophic_backtracking(self) -> None: + """Ensure regex doesn't have catastrophic backtracking.""" + validator = ParameterValidator() + + # Pathological cases that could cause backtracking + pathological_cases = [ + # Many nested quotes + "SELECT '" + ("x" * 10000) + "'", + # Many dollar signs (but not valid parameters) + "SELECT price" + ("$" * 1000) + "2023", + # Many colons in strings + "SELECT '" + ("::" * 1000) + "'", + ] + + for sql in pathological_cases: + start = time.perf_counter() + validator.extract_parameters(sql) + elapsed = time.perf_counter() - start + assert elapsed < 0.1, f"Pathological case too slow: {elapsed:.4f}s" + + def test_edge_case_empty_and_whitespace(self) -> None: + """Test edge cases with empty strings and whitespace.""" + validator = ParameterValidator() + + test_cases = [ + ("", []), + (" ", []), + ("SELECT :param", ["param"]), + ("SELECT :param1 , :param2 ", ["param1", "param2"]), + ("-- comment :not_param\nSELECT :param", ["param"]), + ] + + for sql, expected in test_cases: + params = validator.extract_parameters(sql) + param_names = [p.name for p in params if p.name is not None] + assert param_names == expected, f"Failed for: {sql!r}" + + def test_unicode_and_special_characters(self) -> None: + """Test parameter detection with Unicode and special characters.""" + validator = ParameterValidator() + + test_cases = [ + ("SELECT :café FROM table", ["café"]), + ("SELECT :用户 FROM table", ["用户"]), + ("SELECT :Москва FROM table", ["Москва"]), + ("SELECT :param_123 FROM table", ["param_123"]), + ] + + for sql, expected in test_cases: + params = validator.extract_parameters(sql) + param_names = [p.name for p in params if p.name is not None] + assert param_names == expected, f"Failed for: {sql}" From 56a48d59d4f79bfc6746295a4b537af4e53d8667 Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Wed, 5 Nov 2025 21:47:00 +0000 Subject: [PATCH 4/7] fix: Remove unnecessary blank line in parameter regex performance tests --- tests/unit/test_core/test_parameter_regex_performance.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/test_core/test_parameter_regex_performance.py b/tests/unit/test_core/test_parameter_regex_performance.py index 67cbc76b..61bf82e1 100644 --- a/tests/unit/test_core/test_parameter_regex_performance.py +++ b/tests/unit/test_core/test_parameter_regex_performance.py @@ -97,7 +97,6 @@ def test_mixed_identifiers_and_parameters(self) -> None: ("SELECT * FROM user$data WHERE id = :id", ["id"]), ("SELECT * FROM price@2023 WHERE amount > @amount", ["amount"]), ("SELECT * FROM log:entry WHERE time = :time", ["time"]), - # Column names - NOTE: @column IS detected as parameter in SQL Server # This is correct behavior - if you write SELECT @var, it's a parameter ("SELECT user$id, :param FROM table", ["param"]), From 51407adf2452da350d09095aba9f4e0685a75a00 Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Wed, 5 Nov 2025 21:52:29 +0000 Subject: [PATCH 5/7] refactor: Change logger level from info to debug for Oracle version detection in storage type --- sqlspec/adapters/oracledb/adk/store.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sqlspec/adapters/oracledb/adk/store.py b/sqlspec/adapters/oracledb/adk/store.py index 32a0a082..35eb4d2b 100644 --- a/sqlspec/adapters/oracledb/adk/store.py +++ b/sqlspec/adapters/oracledb/adk/store.py @@ -59,15 +59,15 @@ def _storage_type_from_version(version_info: "OracleVersionInfo | None") -> JSON """Determine JSON storage type based on Oracle version metadata.""" if version_info and version_info.supports_native_json(): - logger.info("Detected Oracle %s with compatible >= 20, using JSON_NATIVE", version_info) + logger.debug("Detected Oracle %s with compatible >= 20, using JSON_NATIVE", version_info) return JSONStorageType.JSON_NATIVE if version_info and version_info.supports_json_blob(): - logger.info("Detected Oracle %s, using BLOB_JSON (recommended)", version_info) + logger.debug("Detected Oracle %s, using BLOB_JSON (recommended)", version_info) return JSONStorageType.BLOB_JSON if version_info: - logger.info("Detected Oracle %s (pre-12c), using BLOB_PLAIN", version_info) + logger.debug("Detected Oracle %s (pre-12c), using BLOB_PLAIN", version_info) return JSONStorageType.BLOB_PLAIN logger.warning("Oracle version could not be detected; defaulting to BLOB_JSON storage") From 514a3fafb31cb834dab77bc4283579dbfb45c87b Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Wed, 5 Nov 2025 22:28:46 +0000 Subject: [PATCH 6/7] fix: update signature namespace and set configs consistently --- pyproject.toml | 2 +- sqlspec/adapters/adbc/config.py | 13 +- sqlspec/adapters/aiosqlite/config.py | 29 +-- sqlspec/adapters/asyncmy/config.py | 16 +- sqlspec/adapters/asyncpg/config.py | 15 +- sqlspec/adapters/bigquery/config.py | 17 +- sqlspec/adapters/duckdb/config.py | 25 ++- sqlspec/adapters/oracledb/config.py | 49 ++-- sqlspec/adapters/psqlpy/config.py | 18 +- sqlspec/adapters/psycopg/config.py | 24 +- sqlspec/adapters/sqlite/config.py | 29 ++- sqlspec/config.py | 11 +- sqlspec/extensions/litestar/plugin.py | 2 +- uv.lock | 312 +++++++++++++------------- 14 files changed, 325 insertions(+), 237 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9d9280b5..231b9079 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ alloydb = ["google-cloud-alloydb-connector"] asyncmy = ["asyncmy"] asyncpg = ["asyncpg"] attrs = ["attrs", "cattrs"] -bigquery = ["google-cloud-bigquery"] +bigquery = ["google-cloud-bigquery", "google-cloud-storage"] cli = ["rich-click"] cloud-sql = ["cloud-sql-python-connector"] duckdb = ["duckdb"] diff --git a/sqlspec/adapters/adbc/config.py b/sqlspec/adapters/adbc/config.py index de514f5c..07c8957a 100644 --- a/sqlspec/adapters/adbc/config.py +++ b/sqlspec/adapters/adbc/config.py @@ -8,7 +8,7 @@ from typing_extensions import NotRequired from sqlspec.adapters.adbc._types import AdbcConnection -from sqlspec.adapters.adbc.driver import AdbcCursor, AdbcDriver, get_adbc_statement_config +from sqlspec.adapters.adbc.driver import AdbcCursor, AdbcDriver, AdbcExceptionHandler, get_adbc_statement_config from sqlspec.config import ADKConfig, FastAPIConfig, FlaskConfig, LitestarConfig, NoPoolSyncConfig, StarletteConfig from sqlspec.core import StatementConfig from sqlspec.exceptions import ImproperConfigurationError @@ -420,13 +420,18 @@ def _get_connection_config_dict(self) -> dict[str, Any]: return config - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for types. Returns: Dictionary mapping type names to types. """ - namespace = super().get_signature_namespace() - namespace.update({"AdbcConnection": AdbcConnection, "AdbcCursor": AdbcCursor}) + namespace.update({ + "AdbcConnection": AdbcConnection, + "AdbcConnectionParams": AdbcConnectionParams, + "AdbcCursor": AdbcCursor, + "AdbcDriver": AdbcDriver, + "AdbcExceptionHandler": AdbcExceptionHandler, + }) return namespace diff --git a/sqlspec/adapters/aiosqlite/config.py b/sqlspec/adapters/aiosqlite/config.py index 8235968e..899e7475 100644 --- a/sqlspec/adapters/aiosqlite/config.py +++ b/sqlspec/adapters/aiosqlite/config.py @@ -7,7 +7,12 @@ from typing_extensions import NotRequired from sqlspec.adapters.aiosqlite._types import AiosqliteConnection -from sqlspec.adapters.aiosqlite.driver import AiosqliteCursor, AiosqliteDriver, aiosqlite_statement_config +from sqlspec.adapters.aiosqlite.driver import ( + AiosqliteCursor, + AiosqliteDriver, + AiosqliteExceptionHandler, + aiosqlite_statement_config, +) from sqlspec.adapters.aiosqlite.pool import ( AiosqliteConnectionPool, AiosqliteConnectTimeoutError, @@ -117,20 +122,11 @@ def __init__( config_dict["uri"] = True processed_driver_features: dict[str, Any] = dict(driver_features) if driver_features else {} - - if "enable_custom_adapters" not in processed_driver_features: - processed_driver_features["enable_custom_adapters"] = True - - if "json_serializer" not in processed_driver_features: - processed_driver_features["json_serializer"] = to_json - - if "json_deserializer" not in processed_driver_features: - processed_driver_features["json_deserializer"] = from_json + processed_driver_features.setdefault("enable_custom_adapters", True) + json_serializer = processed_driver_features.setdefault("json_serializer", to_json) + json_deserializer = processed_driver_features.setdefault("json_deserializer", from_json) base_statement_config = statement_config or aiosqlite_statement_config - - json_serializer = processed_driver_features.get("json_serializer") - json_deserializer = processed_driver_features.get("json_deserializer") if json_serializer is not None: parameter_config = base_statement_config.parameter_config.with_json_serializers( json_serializer, deserializer=json_deserializer @@ -283,7 +279,7 @@ async def provide_pool(self) -> AiosqliteConnectionPool: self.pool_instance = await self.create_pool() return self.pool_instance - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for aiosqlite types. Returns: @@ -292,11 +288,16 @@ def get_signature_namespace(self) -> "dict[str, type[Any]]": namespace = super().get_signature_namespace() namespace.update({ "AiosqliteConnection": AiosqliteConnection, + "AiosqliteConnectionParams": AiosqliteConnectionParams, "AiosqliteConnectionPool": AiosqliteConnectionPool, "AiosqliteConnectTimeoutError": AiosqliteConnectTimeoutError, "AiosqliteCursor": AiosqliteCursor, + "AiosqliteDriver": AiosqliteDriver, + "AiosqliteDriverFeatures": AiosqliteDriverFeatures, + "AiosqliteExceptionHandler": AiosqliteExceptionHandler, "AiosqlitePoolClosedError": AiosqlitePoolClosedError, "AiosqlitePoolConnection": AiosqlitePoolConnection, + "AiosqlitePoolParams": AiosqlitePoolParams, }) return namespace diff --git a/sqlspec/adapters/asyncmy/config.py b/sqlspec/adapters/asyncmy/config.py index 1b0e5977..cadbc79d 100644 --- a/sqlspec/adapters/asyncmy/config.py +++ b/sqlspec/adapters/asyncmy/config.py @@ -14,6 +14,7 @@ from sqlspec.adapters.asyncmy.driver import ( AsyncmyCursor, AsyncmyDriver, + AsyncmyExceptionHandler, asyncmy_statement_config, build_asyncmy_statement_config, ) @@ -121,10 +122,8 @@ def __init__( extras = processed_pool_config.pop("extra") processed_pool_config.update(extras) - if "host" not in processed_pool_config: - processed_pool_config["host"] = "localhost" - if "port" not in processed_pool_config: - processed_pool_config["port"] = 3306 + processed_pool_config.setdefault("host", "localhost") + processed_pool_config.setdefault("port", 3306) processed_driver_features: dict[str, Any] = dict(driver_features) if driver_features else {} serializer = processed_driver_features.setdefault("json_serializer", to_json) @@ -221,7 +220,7 @@ async def provide_pool(self, *args: Any, **kwargs: Any) -> "Pool": # pyright: i self.pool_instance = await self.create_pool() return self.pool_instance - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for Asyncmy types. Returns: @@ -231,7 +230,12 @@ def get_signature_namespace(self) -> "dict[str, type[Any]]": namespace = super().get_signature_namespace() namespace.update({ "AsyncmyConnection": AsyncmyConnection, - "AsyncmyPool": AsyncmyPool, + "AsyncmyConnectionParams": AsyncmyConnectionParams, "AsyncmyCursor": AsyncmyCursor, + "AsyncmyDriver": AsyncmyDriver, + "AsyncmyDriverFeatures": AsyncmyDriverFeatures, + "AsyncmyExceptionHandler": AsyncmyExceptionHandler, + "AsyncmyPool": AsyncmyPool, + "AsyncmyPoolParams": AsyncmyPoolParams, }) return namespace diff --git a/sqlspec/adapters/asyncpg/config.py b/sqlspec/adapters/asyncpg/config.py index 16d4dca5..ebc109c9 100644 --- a/sqlspec/adapters/asyncpg/config.py +++ b/sqlspec/adapters/asyncpg/config.py @@ -11,10 +11,11 @@ from asyncpg.pool import Pool, PoolConnectionProxy, PoolConnectionProxyMeta from typing_extensions import NotRequired -from sqlspec.adapters.asyncpg._types import AsyncpgConnection +from sqlspec.adapters.asyncpg._types import AsyncpgConnection, AsyncpgPool from sqlspec.adapters.asyncpg.driver import ( AsyncpgCursor, AsyncpgDriver, + AsyncpgExceptionHandler, asyncpg_statement_config, build_asyncpg_statement_config, ) @@ -329,8 +330,7 @@ async def _create_pool(self) -> "Pool[Record]": elif self.driver_features.get("enable_alloydb", False): self._setup_alloydb_connector(config) - if "init" not in config: - config["init"] = self._init_connection + config.setdefault("init", self._init_connection) return await asyncpg_create_pool(**config) @@ -432,7 +432,7 @@ async def provide_pool(self, *args: Any, **kwargs: Any) -> "Pool[Record]": self.pool_instance = await self.create_pool() return self.pool_instance - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for AsyncPG types. This provides all AsyncPG-specific types that Litestar needs to recognize @@ -450,7 +450,12 @@ def get_signature_namespace(self) -> "dict[str, type[Any]]": "PoolConnectionProxyMeta": PoolConnectionProxyMeta, "ConnectionMeta": ConnectionMeta, "Record": Record, - "AsyncpgConnection": AsyncpgConnection, # type: ignore[dict-item] + "AsyncpgConnection": AsyncpgConnection, + "AsyncpgConnectionConfig": AsyncpgConnectionConfig, "AsyncpgCursor": AsyncpgCursor, + "AsyncpgDriver": AsyncpgDriver, + "AsyncpgExceptionHandler": AsyncpgExceptionHandler, + "AsyncpgPool": AsyncpgPool, + "AsyncpgPoolConfig": AsyncpgPoolConfig, }) return namespace diff --git a/sqlspec/adapters/bigquery/config.py b/sqlspec/adapters/bigquery/config.py index 72f58617..84f7d9ee 100644 --- a/sqlspec/adapters/bigquery/config.py +++ b/sqlspec/adapters/bigquery/config.py @@ -8,7 +8,12 @@ from typing_extensions import NotRequired from sqlspec.adapters.bigquery._types import BigQueryConnection -from sqlspec.adapters.bigquery.driver import BigQueryCursor, BigQueryDriver, build_bigquery_statement_config +from sqlspec.adapters.bigquery.driver import ( + BigQueryCursor, + BigQueryDriver, + BigQueryExceptionHandler, + build_bigquery_statement_config, +) from sqlspec.config import ADKConfig, FastAPIConfig, FlaskConfig, LitestarConfig, NoPoolSyncConfig, StarletteConfig from sqlspec.exceptions import ImproperConfigurationError from sqlspec.typing import Empty @@ -263,7 +268,7 @@ def provide_session( ) yield driver - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for BigQuery types. Returns: @@ -271,5 +276,11 @@ def get_signature_namespace(self) -> "dict[str, type[Any]]": """ namespace = super().get_signature_namespace() - namespace.update({"BigQueryConnection": BigQueryConnection, "BigQueryCursor": BigQueryCursor}) + namespace.update({ + "BigQueryConnection": BigQueryConnection, + "BigQueryConnectionParams": BigQueryConnectionParams, + "BigQueryCursor": BigQueryCursor, + "BigQueryDriver": BigQueryDriver, + "BigQueryExceptionHandler": BigQueryExceptionHandler, + }) return namespace diff --git a/sqlspec/adapters/duckdb/config.py b/sqlspec/adapters/duckdb/config.py index 6591d085..111a4057 100644 --- a/sqlspec/adapters/duckdb/config.py +++ b/sqlspec/adapters/duckdb/config.py @@ -7,7 +7,12 @@ from typing_extensions import NotRequired from sqlspec.adapters.duckdb._types import DuckDBConnection -from sqlspec.adapters.duckdb.driver import DuckDBCursor, DuckDBDriver, build_duckdb_statement_config +from sqlspec.adapters.duckdb.driver import ( + DuckDBCursor, + DuckDBDriver, + DuckDBExceptionHandler, + build_duckdb_statement_config, +) from sqlspec.adapters.duckdb.pool import DuckDBConnectionPool from sqlspec.config import ADKConfig, FastAPIConfig, FlaskConfig, LitestarConfig, StarletteConfig, SyncDatabaseConfig from sqlspec.utils.serializers import to_json @@ -209,8 +214,7 @@ def __init__( """ if pool_config is None: pool_config = {} - if "database" not in pool_config: - pool_config["database"] = ":memory:shared_db" + pool_config.setdefault("database", ":memory:shared_db") if pool_config.get("database") in {":memory:", ""}: pool_config["database"] = ":memory:shared_db" @@ -331,7 +335,7 @@ def provide_session( ) yield driver - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for DuckDB types. This provides all DuckDB-specific types that Litestar needs to recognize @@ -342,5 +346,16 @@ def get_signature_namespace(self) -> "dict[str, type[Any]]": """ namespace = super().get_signature_namespace() - namespace.update({"DuckDBConnection": DuckDBConnection, "DuckDBCursor": DuckDBCursor}) + namespace.update({ + "DuckDBConnection": DuckDBConnection, + "DuckDBConnectionParams": DuckDBConnectionParams, + "DuckDBConnectionPool": DuckDBConnectionPool, + "DuckDBCursor": DuckDBCursor, + "DuckDBDriver": DuckDBDriver, + "DuckDBDriverFeatures": DuckDBDriverFeatures, + "DuckDBExceptionHandler": DuckDBExceptionHandler, + "DuckDBExtensionConfig": DuckDBExtensionConfig, + "DuckDBPoolParams": DuckDBPoolParams, + "DuckDBSecretConfig": DuckDBSecretConfig, + }) return namespace diff --git a/sqlspec/adapters/oracledb/config.py b/sqlspec/adapters/oracledb/config.py index 5ab4f571..52dd2579 100644 --- a/sqlspec/adapters/oracledb/config.py +++ b/sqlspec/adapters/oracledb/config.py @@ -19,8 +19,10 @@ from sqlspec.adapters.oracledb.driver import ( OracleAsyncCursor, OracleAsyncDriver, + OracleAsyncExceptionHandler, OracleSyncCursor, OracleSyncDriver, + OracleSyncExceptionHandler, oracledb_statement_config, ) from sqlspec.adapters.oracledb.migrations import OracleAsyncMigrationTracker, OracleSyncMigrationTracker @@ -162,12 +164,9 @@ def __init__( statement_config = statement_config or oracledb_statement_config processed_driver_features: dict[str, Any] = dict(driver_features) if driver_features else {} - if "enable_numpy_vectors" not in processed_driver_features: - processed_driver_features["enable_numpy_vectors"] = NUMPY_INSTALLED - if "enable_lowercase_column_names" not in processed_driver_features: - processed_driver_features["enable_lowercase_column_names"] = True - if "enable_uuid_binary" not in processed_driver_features: - processed_driver_features["enable_uuid_binary"] = True + processed_driver_features.setdefault("enable_numpy_vectors", NUMPY_INSTALLED) + processed_driver_features.setdefault("enable_lowercase_column_names", True) + processed_driver_features.setdefault("enable_uuid_binary", True) super().__init__( pool_config=processed_pool_config, @@ -269,7 +268,7 @@ def provide_pool(self) -> "OracleSyncConnectionPool": self.pool_instance = self.create_pool() return self.pool_instance - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for OracleDB types. Provides OracleDB-specific types for Litestar framework recognition. @@ -280,11 +279,19 @@ def get_signature_namespace(self) -> "dict[str, type[Any]]": namespace = super().get_signature_namespace() namespace.update({ - "OracleSyncConnection": OracleSyncConnection, "OracleAsyncConnection": OracleAsyncConnection, - "OracleSyncConnectionPool": OracleSyncConnectionPool, "OracleAsyncConnectionPool": OracleAsyncConnectionPool, + "OracleAsyncCursor": OracleAsyncCursor, + "OracleAsyncDriver": OracleAsyncDriver, + "OracleAsyncExceptionHandler": OracleAsyncExceptionHandler, + "OracleConnectionParams": OracleConnectionParams, + "OracleDriverFeatures": OracleDriverFeatures, + "OraclePoolParams": OraclePoolParams, + "OracleSyncConnection": OracleSyncConnection, + "OracleSyncConnectionPool": OracleSyncConnectionPool, "OracleSyncCursor": OracleSyncCursor, + "OracleSyncDriver": OracleSyncDriver, + "OracleSyncExceptionHandler": OracleSyncExceptionHandler, }) return namespace @@ -332,12 +339,9 @@ def __init__( processed_pool_config.update(extras) processed_driver_features: dict[str, Any] = dict(driver_features) if driver_features else {} - if "enable_numpy_vectors" not in processed_driver_features: - processed_driver_features["enable_numpy_vectors"] = NUMPY_INSTALLED - if "enable_lowercase_column_names" not in processed_driver_features: - processed_driver_features["enable_lowercase_column_names"] = True - if "enable_uuid_binary" not in processed_driver_features: - processed_driver_features["enable_uuid_binary"] = True + processed_driver_features.setdefault("enable_numpy_vectors", NUMPY_INSTALLED) + processed_driver_features.setdefault("enable_lowercase_column_names", True) + processed_driver_features.setdefault("enable_uuid_binary", True) super().__init__( pool_config=processed_pool_config, @@ -445,7 +449,7 @@ async def provide_pool(self) -> "OracleAsyncConnectionPool": self.pool_instance = await self.create_pool() return self.pool_instance - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for OracleDB async types. Provides OracleDB async-specific types for Litestar framework recognition. @@ -456,11 +460,18 @@ def get_signature_namespace(self) -> "dict[str, type[Any]]": namespace = super().get_signature_namespace() namespace.update({ - "OracleSyncConnection": OracleSyncConnection, "OracleAsyncConnection": OracleAsyncConnection, - "OracleSyncConnectionPool": OracleSyncConnectionPool, "OracleAsyncConnectionPool": OracleAsyncConnectionPool, - "OracleSyncCursor": OracleSyncCursor, "OracleAsyncCursor": OracleAsyncCursor, + "OracleAsyncDriver": OracleAsyncDriver, + "OracleAsyncExceptionHandler": OracleAsyncExceptionHandler, + "OracleConnectionParams": OracleConnectionParams, + "OracleDriverFeatures": OracleDriverFeatures, + "OraclePoolParams": OraclePoolParams, + "OracleSyncConnection": OracleSyncConnection, + "OracleSyncConnectionPool": OracleSyncConnectionPool, + "OracleSyncCursor": OracleSyncCursor, + "OracleSyncDriver": OracleSyncDriver, + "OracleSyncExceptionHandler": OracleSyncExceptionHandler, }) return namespace diff --git a/sqlspec/adapters/psqlpy/config.py b/sqlspec/adapters/psqlpy/config.py index aec2b6e5..629671f4 100644 --- a/sqlspec/adapters/psqlpy/config.py +++ b/sqlspec/adapters/psqlpy/config.py @@ -9,7 +9,12 @@ from typing_extensions import NotRequired from sqlspec.adapters.psqlpy._types import PsqlpyConnection -from sqlspec.adapters.psqlpy.driver import PsqlpyCursor, PsqlpyDriver, build_psqlpy_statement_config +from sqlspec.adapters.psqlpy.driver import ( + PsqlpyCursor, + PsqlpyDriver, + PsqlpyExceptionHandler, + build_psqlpy_statement_config, +) from sqlspec.config import ADKConfig, AsyncDatabaseConfig, FastAPIConfig, FlaskConfig, LitestarConfig, StarletteConfig from sqlspec.core import StatementConfig from sqlspec.typing import PGVECTOR_INSTALLED @@ -247,12 +252,19 @@ async def provide_pool(self, *args: Any, **kwargs: Any) -> ConnectionPool: self.pool_instance = await self.create_pool() return self.pool_instance - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for Psqlpy types. Returns: Dictionary mapping type names to types. """ namespace = super().get_signature_namespace() - namespace.update({"PsqlpyConnection": PsqlpyConnection, "PsqlpyCursor": PsqlpyCursor}) + namespace.update({ + "PsqlpyConnection": PsqlpyConnection, + "PsqlpyConnectionParams": PsqlpyConnectionParams, + "PsqlpyCursor": PsqlpyCursor, + "PsqlpyDriver": PsqlpyDriver, + "PsqlpyExceptionHandler": PsqlpyExceptionHandler, + "PsqlpyPoolParams": PsqlpyPoolParams, + }) return namespace diff --git a/sqlspec/adapters/psycopg/config.py b/sqlspec/adapters/psycopg/config.py index 7ec1d0e7..8f023897 100644 --- a/sqlspec/adapters/psycopg/config.py +++ b/sqlspec/adapters/psycopg/config.py @@ -13,8 +13,10 @@ from sqlspec.adapters.psycopg.driver import ( PsycopgAsyncCursor, PsycopgAsyncDriver, + PsycopgAsyncExceptionHandler, PsycopgSyncCursor, PsycopgSyncDriver, + PsycopgSyncExceptionHandler, build_psycopg_statement_config, psycopg_statement_config, ) @@ -285,7 +287,7 @@ def provide_pool(self, *args: Any, **kwargs: Any) -> "ConnectionPool": self.pool_instance = self.create_pool() return self.pool_instance - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for Psycopg types. This provides all Psycopg-specific types that Litestar needs to recognize @@ -295,7 +297,14 @@ def get_signature_namespace(self) -> "dict[str, type[Any]]": Dictionary mapping type names to types. """ namespace = super().get_signature_namespace() - namespace.update({"PsycopgSyncConnection": PsycopgSyncConnection, "PsycopgSyncCursor": PsycopgSyncCursor}) + namespace.update({ + "PsycopgConnectionParams": PsycopgConnectionParams, + "PsycopgPoolParams": PsycopgPoolParams, + "PsycopgSyncConnection": PsycopgSyncConnection, + "PsycopgSyncCursor": PsycopgSyncCursor, + "PsycopgSyncDriver": PsycopgSyncDriver, + "PsycopgSyncExceptionHandler": PsycopgSyncExceptionHandler, + }) return namespace @@ -470,7 +479,7 @@ async def provide_pool(self, *args: Any, **kwargs: Any) -> "AsyncConnectionPool" self.pool_instance = await self.create_pool() return self.pool_instance - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for Psycopg async types. This provides all Psycopg async-specific types that Litestar needs to recognize @@ -480,5 +489,12 @@ def get_signature_namespace(self) -> "dict[str, type[Any]]": Dictionary mapping type names to types. """ namespace = super().get_signature_namespace() - namespace.update({"PsycopgAsyncConnection": PsycopgAsyncConnection, "PsycopgAsyncCursor": PsycopgAsyncCursor}) + namespace.update({ + "PsycopgAsyncConnection": PsycopgAsyncConnection, + "PsycopgAsyncCursor": PsycopgAsyncCursor, + "PsycopgAsyncDriver": PsycopgAsyncDriver, + "PsycopgAsyncExceptionHandler": PsycopgAsyncExceptionHandler, + "PsycopgConnectionParams": PsycopgConnectionParams, + "PsycopgPoolParams": PsycopgPoolParams, + }) return namespace diff --git a/sqlspec/adapters/sqlite/config.py b/sqlspec/adapters/sqlite/config.py index 07e3d10f..43afd655 100644 --- a/sqlspec/adapters/sqlite/config.py +++ b/sqlspec/adapters/sqlite/config.py @@ -9,7 +9,7 @@ from sqlspec.adapters.sqlite._type_handlers import register_type_handlers from sqlspec.adapters.sqlite._types import SqliteConnection -from sqlspec.adapters.sqlite.driver import SqliteCursor, SqliteDriver, sqlite_statement_config +from sqlspec.adapters.sqlite.driver import SqliteCursor, SqliteDriver, SqliteExceptionHandler, sqlite_statement_config from sqlspec.adapters.sqlite.pool import SqliteConnectionPool from sqlspec.config import ADKConfig, FastAPIConfig, FlaskConfig, LitestarConfig, StarletteConfig, SyncDatabaseConfig from sqlspec.utils.serializers import from_json, to_json @@ -106,20 +106,11 @@ def __init__( pool_config["uri"] = True processed_driver_features: dict[str, Any] = dict(driver_features) if driver_features else {} - - if "enable_custom_adapters" not in processed_driver_features: - processed_driver_features["enable_custom_adapters"] = True - - if "json_serializer" not in processed_driver_features: - processed_driver_features["json_serializer"] = to_json - - if "json_deserializer" not in processed_driver_features: - processed_driver_features["json_deserializer"] = from_json + processed_driver_features.setdefault("enable_custom_adapters", True) + json_serializer = processed_driver_features.setdefault("json_serializer", to_json) + json_deserializer = processed_driver_features.setdefault("json_deserializer", from_json) base_statement_config = statement_config or sqlite_statement_config - - json_serializer = processed_driver_features.get("json_serializer") - json_deserializer = processed_driver_features.get("json_deserializer") if json_serializer is not None: parameter_config = base_statement_config.parameter_config.with_json_serializers( json_serializer, deserializer=json_deserializer @@ -206,12 +197,20 @@ def provide_session( driver_features=self.driver_features, ) - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for SQLite types. Returns: Dictionary mapping type names to types. """ namespace = super().get_signature_namespace() - namespace.update({"SqliteConnection": SqliteConnection, "SqliteCursor": SqliteCursor}) + namespace.update({ + "SqliteConnection": SqliteConnection, + "SqliteConnectionParams": SqliteConnectionParams, + "SqliteConnectionPool": SqliteConnectionPool, + "SqliteCursor": SqliteCursor, + "SqliteDriver": SqliteDriver, + "SqliteDriverFeatures": SqliteDriverFeatures, + "SqliteExceptionHandler": SqliteExceptionHandler, + }) return namespace diff --git a/sqlspec/config.py b/sqlspec/config.py index acb9f2f6..b5728c81 100644 --- a/sqlspec/config.py +++ b/sqlspec/config.py @@ -510,15 +510,16 @@ def provide_pool( """Provide pool instance.""" raise NotImplementedError - def get_signature_namespace(self) -> "dict[str, type[Any]]": + def get_signature_namespace(self) -> "dict[str, Any]": """Get the signature namespace for this database configuration. - Returns a dictionary of type names to types that should be registered - with Litestar's signature namespace to prevent serialization attempts - on database-specific types. + Returns a dictionary of type names to objects (classes, functions, or + other callables) that should be registered with Litestar's signature + namespace to prevent serialization attempts on database-specific + structures. Returns: - Dictionary mapping type names to types. + Dictionary mapping type names to objects. """ return {} diff --git a/sqlspec/extensions/litestar/plugin.py b/sqlspec/extensions/litestar/plugin.py index c78db0e2..57d7e6fe 100644 --- a/sqlspec/extensions/litestar/plugin.py +++ b/sqlspec/extensions/litestar/plugin.py @@ -258,7 +258,7 @@ def store_sqlspec_in_state() -> None: app_config.signature_types.append(state.config.connection_type) app_config.signature_types.append(state.config.driver_type) - signature_namespace.update(state.config.get_signature_namespace()) # type: ignore[arg-type] + signature_namespace.update(state.config.get_signature_namespace()) if not state.disable_di: app_config.before_send.append(state.before_send_handler) diff --git a/uv.lock b/uv.lock index 7833100c..63339358 100644 --- a/uv.lock +++ b/uv.lock @@ -9,15 +9,6 @@ resolution-markers = [ "python_full_version < '3.11'", ] -[[package]] -name = "absolufy-imports" -version = "0.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/74/0f/9da9dc9a12ebf4622ec96d9338d221e0172699e7574929f65ec8fdb30f9c/absolufy_imports-0.3.1.tar.gz", hash = "sha256:c90638a6c0b66826d1fb4880ddc20ef7701af34192c94faf40b95d32b59f9793", size = 4724, upload-time = "2022-01-20T14:48:53.434Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/a4/b65c9fbc2c0c09c0ea3008f62d2010fd261e62a4881502f03a6301079182/absolufy_imports-0.3.1-py2.py3-none-any.whl", hash = "sha256:49bf7c753a9282006d553ba99217f48f947e3eef09e18a700f8a82f75dc7fc5c", size = 5937, upload-time = "2022-01-20T14:48:51.718Z" }, -] - [[package]] name = "adbc-driver-bigquery" version = "1.8.0" @@ -1629,10 +1620,9 @@ s3 = [ [[package]] name = "google-adk" -version = "1.17.0" +version = "1.18.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "absolufy-imports" }, { name = "anyio" }, { name = "authlib" }, { name = "click" }, @@ -1670,8 +1660,9 @@ dependencies = [ { name = "watchdog" }, { name = "websockets" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/9f/7d/b331e2b31e32ca81f73111e9a79d1c6222d91f7b647013c77604a7f41322/google_adk-1.18.0.tar.gz", hash = "sha256:883fc621ce138099a75b2677017a1cd510e4303bad1415eabf38f802078d57b9", size = 1950454, upload-time = "2025-11-05T18:43:25.578Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/6e/5aadd9d4afd69ecd546d4ae02fdaf1eb29e1d1a5c84d1ae1d16906271d43/google_adk-1.17.0-py3-none-any.whl", hash = "sha256:1d32b425087bd57015b18c86f9850366fd5ea6a805bbcd147493750438ed6276", size = 2035820, upload-time = "2025-10-22T20:39:09.242Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/1012b25cb0dfb630c2b8c040c181f0b6559efb00d1e6007c4eca24970fb2/google_adk-1.18.0-py3-none-any.whl", hash = "sha256:657fe281718ce87117149f006556f9fd84a0bdbe1073dd6b8c3d4bd3e6044b45", size = 2244321, upload-time = "2025-11-05T18:43:23.987Z" }, ] [[package]] @@ -1741,7 +1732,7 @@ wheels = [ [[package]] name = "google-cloud-aiplatform" -version = "1.124.0" +version = "1.125.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docstring-parser" }, @@ -1758,9 +1749,9 @@ dependencies = [ { name = "shapely" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d7/ad/a3da0cbb78a933544ef2ca3db3da242a2217a52d823beb3ea129995c00df/google_cloud_aiplatform-1.124.0.tar.gz", hash = "sha256:cf565f2ce3dac19c6502a65d89c89760000fde1d531be54949c6232ba2a168fd", size = 9755170, upload-time = "2025-10-30T19:59:22.057Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d7/5c2df60dbcc68f292a4a7e7b0e17e17b4808788be0fdbdb150d439bc70e6/google_cloud_aiplatform-1.125.0.tar.gz", hash = "sha256:2cafa6222c78155c209893458706942dffa16d5647496257e916405a19e75a63", size = 9772810, upload-time = "2025-11-05T00:32:00.927Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/46/c20db72a9389c5b6595c2c3fed9abe2b05d3658fe2c07657f7324623cb63/google_cloud_aiplatform-1.124.0-py2.py3-none-any.whl", hash = "sha256:047685f0ee0ab7346ba7d437904357077e3362b32a951c5038a9ac789c5f9148", size = 8112493, upload-time = "2025-10-30T19:59:19.42Z" }, + { url = "https://files.pythonhosted.org/packages/7f/fa/72c8d14b8abb119a15e31864fc61ab2ff5565f1e1166a137d62968935e00/google_cloud_aiplatform-1.125.0-py2.py3-none-any.whl", hash = "sha256:956058c138ba668f7e1365489dbbfca8606e4d35e9186fa429434950817a78d5", size = 8122978, upload-time = "2025-11-05T00:31:57.74Z" }, ] [package.optional-dependencies] @@ -1769,6 +1760,7 @@ agent-engines = [ { name = "google-cloud-logging" }, { name = "google-cloud-trace" }, { name = "opentelemetry-exporter-gcp-trace" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, { name = "opentelemetry-sdk" }, { name = "packaging" }, { name = "pydantic" }, @@ -2009,7 +2001,7 @@ wheels = [ [[package]] name = "google-cloud-storage" -version = "2.19.0" +version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core" }, @@ -2019,9 +2011,9 @@ dependencies = [ { name = "google-resumable-media" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/36/76/4d965702e96bb67976e755bed9828fa50306dca003dbee08b67f41dd265e/google_cloud_storage-2.19.0.tar.gz", hash = "sha256:cd05e9e7191ba6cb68934d8eb76054d9be4562aa89dbc4236feee4d7d51342b2", size = 5535488, upload-time = "2024-12-05T01:35:06.49Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/98/c0c6d10f893509585c755a6567689e914df3501ae269f46b0d67d7e7c70a/google_cloud_storage-3.5.0.tar.gz", hash = "sha256:10b89e1d1693114b3e0ca921bdd28c5418701fd092e39081bb77e5cee0851ab7", size = 17242207, upload-time = "2025-11-05T12:41:02.715Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/94/6db383d8ee1adf45dc6c73477152b82731fa4c4a46d9c1932cc8757e0fd4/google_cloud_storage-2.19.0-py2.py3-none-any.whl", hash = "sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba", size = 131787, upload-time = "2024-12-05T01:35:04.736Z" }, + { url = "https://files.pythonhosted.org/packages/20/81/a567236070e7fe79a17a11b118d7f5ce4adefe2edd18caf1824d7e29a30a/google_cloud_storage-3.5.0-py3-none-any.whl", hash = "sha256:e28fd6ad8764e60dbb9a398a7bc3296e7920c494bc329057d828127e5f9630d3", size = 289998, upload-time = "2025-11-05T12:41:01.212Z" }, ] [[package]] @@ -2146,6 +2138,8 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7f/91/ae2eb6b7979e2f9b035a9f612cf70f1bf54aad4e1d125129bef1eae96f19/greenlet-3.2.4-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2ca18a03a8cfb5b25bc1cbe20f3d9a4c80d8c3b13ba3df49ac3961af0b1018d", size = 584358, upload-time = "2025-08-07T13:18:23.708Z" }, { url = "https://files.pythonhosted.org/packages/f7/85/433de0c9c0252b22b16d413c9407e6cb3b41df7389afc366ca204dbc1393/greenlet-3.2.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9fe0a28a7b952a21e2c062cd5756d34354117796c6d9215a87f55e38d15402c5", size = 1113550, upload-time = "2025-08-07T13:42:37.467Z" }, { url = "https://files.pythonhosted.org/packages/a1/8d/88f3ebd2bc96bf7747093696f4335a0a8a4c5acfcf1b757717c0d2474ba3/greenlet-3.2.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8854167e06950ca75b898b104b63cc646573aa5fef1353d4508ecdd1ee76254f", size = 1137126, upload-time = "2025-08-07T13:18:20.239Z" }, + { url = "https://files.pythonhosted.org/packages/f1/29/74242b7d72385e29bcc5563fba67dad94943d7cd03552bac320d597f29b2/greenlet-3.2.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f47617f698838ba98f4ff4189aef02e7343952df3a615f847bb575c3feb177a7", size = 1544904, upload-time = "2025-11-04T12:42:04.763Z" }, + { url = "https://files.pythonhosted.org/packages/c8/e2/1572b8eeab0f77df5f6729d6ab6b141e4a84ee8eb9bc8c1e7918f94eda6d/greenlet-3.2.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af41be48a4f60429d5cad9d22175217805098a9ef7c40bfef44f7669fb9d74d8", size = 1611228, upload-time = "2025-11-04T12:42:08.423Z" }, { url = "https://files.pythonhosted.org/packages/d6/6f/b60b0291d9623c496638c582297ead61f43c4b72eef5e9c926ef4565ec13/greenlet-3.2.4-cp310-cp310-win_amd64.whl", hash = "sha256:73f49b5368b5359d04e18d15828eecc1806033db5233397748f4ca813ff1056c", size = 298654, upload-time = "2025-08-07T13:50:00.469Z" }, { url = "https://files.pythonhosted.org/packages/a4/de/f28ced0a67749cac23fecb02b694f6473f47686dff6afaa211d186e2ef9c/greenlet-3.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2", size = 272305, upload-time = "2025-08-07T13:15:41.288Z" }, { url = "https://files.pythonhosted.org/packages/09/16/2c3792cba130000bf2a31c5272999113f4764fd9d874fb257ff588ac779a/greenlet-3.2.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246", size = 632472, upload-time = "2025-08-07T13:42:55.044Z" }, @@ -2155,6 +2149,8 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1f/8e/abdd3f14d735b2929290a018ecf133c901be4874b858dd1c604b9319f064/greenlet-3.2.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2523e5246274f54fdadbce8494458a2ebdcdbc7b802318466ac5606d3cded1f8", size = 587684, upload-time = "2025-08-07T13:18:25.164Z" }, { url = "https://files.pythonhosted.org/packages/5d/65/deb2a69c3e5996439b0176f6651e0052542bb6c8f8ec2e3fba97c9768805/greenlet-3.2.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1987de92fec508535687fb807a5cea1560f6196285a4cde35c100b8cd632cc52", size = 1116647, upload-time = "2025-08-07T13:42:38.655Z" }, { url = "https://files.pythonhosted.org/packages/3f/cc/b07000438a29ac5cfb2194bfc128151d52f333cee74dd7dfe3fb733fc16c/greenlet-3.2.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:55e9c5affaa6775e2c6b67659f3a71684de4c549b3dd9afca3bc773533d284fa", size = 1142073, upload-time = "2025-08-07T13:18:21.737Z" }, + { url = "https://files.pythonhosted.org/packages/67/24/28a5b2fa42d12b3d7e5614145f0bd89714c34c08be6aabe39c14dd52db34/greenlet-3.2.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9c6de1940a7d828635fbd254d69db79e54619f165ee7ce32fda763a9cb6a58c", size = 1548385, upload-time = "2025-11-04T12:42:11.067Z" }, + { url = "https://files.pythonhosted.org/packages/6a/05/03f2f0bdd0b0ff9a4f7b99333d57b53a7709c27723ec8123056b084e69cd/greenlet-3.2.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03c5136e7be905045160b1b9fdca93dd6727b180feeafda6818e6496434ed8c5", size = 1613329, upload-time = "2025-11-04T12:42:12.928Z" }, { url = "https://files.pythonhosted.org/packages/d8/0f/30aef242fcab550b0b3520b8e3561156857c94288f0332a79928c31a52cf/greenlet-3.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:9c40adce87eaa9ddb593ccb0fa6a07caf34015a29bf8d344811665b573138db9", size = 299100, upload-time = "2025-08-07T13:44:12.287Z" }, { url = "https://files.pythonhosted.org/packages/44/69/9b804adb5fd0671f367781560eb5eb586c4d495277c93bde4307b9e28068/greenlet-3.2.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3b67ca49f54cede0186854a008109d6ee71f66bd57bb36abd6d0a0267b540cdd", size = 274079, upload-time = "2025-08-07T13:15:45.033Z" }, { url = "https://files.pythonhosted.org/packages/46/e9/d2a80c99f19a153eff70bc451ab78615583b8dac0754cfb942223d2c1a0d/greenlet-3.2.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddf9164e7a5b08e9d22511526865780a576f19ddd00d62f8a665949327fde8bb", size = 640997, upload-time = "2025-08-07T13:42:56.234Z" }, @@ -2164,6 +2160,8 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/19/0d/6660d55f7373b2ff8152401a83e02084956da23ae58cddbfb0b330978fe9/greenlet-3.2.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b3812d8d0c9579967815af437d96623f45c0f2ae5f04e366de62a12d83a8fb0", size = 607586, upload-time = "2025-08-07T13:18:28.544Z" }, { url = "https://files.pythonhosted.org/packages/8e/1a/c953fdedd22d81ee4629afbb38d2f9d71e37d23caace44775a3a969147d4/greenlet-3.2.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:abbf57b5a870d30c4675928c37278493044d7c14378350b3aa5d484fa65575f0", size = 1123281, upload-time = "2025-08-07T13:42:39.858Z" }, { url = "https://files.pythonhosted.org/packages/3f/c7/12381b18e21aef2c6bd3a636da1088b888b97b7a0362fac2e4de92405f97/greenlet-3.2.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:20fb936b4652b6e307b8f347665e2c615540d4b42b3b4c8a321d8286da7e520f", size = 1151142, upload-time = "2025-08-07T13:18:22.981Z" }, + { url = "https://files.pythonhosted.org/packages/27/45/80935968b53cfd3f33cf99ea5f08227f2646e044568c9b1555b58ffd61c2/greenlet-3.2.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee7a6ec486883397d70eec05059353b8e83eca9168b9f3f9a361971e77e0bcd0", size = 1564846, upload-time = "2025-11-04T12:42:15.191Z" }, + { url = "https://files.pythonhosted.org/packages/69/02/b7c30e5e04752cb4db6202a3858b149c0710e5453b71a3b2aec5d78a1aab/greenlet-3.2.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:326d234cbf337c9c3def0676412eb7040a35a768efc92504b947b3e9cfc7543d", size = 1633814, upload-time = "2025-11-04T12:42:17.175Z" }, { url = "https://files.pythonhosted.org/packages/e9/08/b0814846b79399e585f974bbeebf5580fbe59e258ea7be64d9dfb253c84f/greenlet-3.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:a7d4e128405eea3814a12cc2605e0e6aedb4035bf32697f72deca74de4105e02", size = 299899, upload-time = "2025-08-07T13:38:53.448Z" }, { url = "https://files.pythonhosted.org/packages/49/e8/58c7f85958bda41dafea50497cbd59738c5c43dbbea5ee83d651234398f4/greenlet-3.2.4-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31", size = 272814, upload-time = "2025-08-07T13:15:50.011Z" }, { url = "https://files.pythonhosted.org/packages/62/dd/b9f59862e9e257a16e4e610480cfffd29e3fae018a68c2332090b53aac3d/greenlet-3.2.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945", size = 641073, upload-time = "2025-08-07T13:42:57.23Z" }, @@ -2173,6 +2171,8 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ee/43/3cecdc0349359e1a527cbf2e3e28e5f8f06d3343aaf82ca13437a9aa290f/greenlet-3.2.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671", size = 610497, upload-time = "2025-08-07T13:18:31.636Z" }, { url = "https://files.pythonhosted.org/packages/b8/19/06b6cf5d604e2c382a6f31cafafd6f33d5dea706f4db7bdab184bad2b21d/greenlet-3.2.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b", size = 1121662, upload-time = "2025-08-07T13:42:41.117Z" }, { url = "https://files.pythonhosted.org/packages/a2/15/0d5e4e1a66fab130d98168fe984c509249c833c1a3c16806b90f253ce7b9/greenlet-3.2.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d25c5091190f2dc0eaa3f950252122edbbadbb682aa7b1ef2f8af0f8c0afefae", size = 1149210, upload-time = "2025-08-07T13:18:24.072Z" }, + { url = "https://files.pythonhosted.org/packages/1c/53/f9c440463b3057485b8594d7a638bed53ba531165ef0ca0e6c364b5cc807/greenlet-3.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e343822feb58ac4d0a1211bd9399de2b3a04963ddeec21530fc426cc121f19b", size = 1564759, upload-time = "2025-11-04T12:42:19.395Z" }, + { url = "https://files.pythonhosted.org/packages/47/e4/3bb4240abdd0a8d23f4f88adec746a3099f0d86bfedb623f063b2e3b4df0/greenlet-3.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca7f6f1f2649b89ce02f6f229d7c19f680a6238af656f61e0115b24857917929", size = 1634288, upload-time = "2025-11-04T12:42:21.174Z" }, { url = "https://files.pythonhosted.org/packages/0b/55/2321e43595e6801e105fcfdee02b34c0f996eb71e6ddffca6b10b7e1d771/greenlet-3.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:554b03b6e73aaabec3745364d6239e9e012d64c68ccd0b8430c64ccc14939a8b", size = 299685, upload-time = "2025-08-07T13:24:38.824Z" }, { url = "https://files.pythonhosted.org/packages/22/5c/85273fd7cc388285632b0498dbbab97596e04b154933dfe0f3e68156c68c/greenlet-3.2.4-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0", size = 273586, upload-time = "2025-08-07T13:16:08.004Z" }, { url = "https://files.pythonhosted.org/packages/d1/75/10aeeaa3da9332c2e761e4c50d4c3556c21113ee3f0afa2cf5769946f7a3/greenlet-3.2.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f", size = 686346, upload-time = "2025-08-07T13:42:59.944Z" }, @@ -2180,6 +2180,8 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/dc/8b/29aae55436521f1d6f8ff4e12fb676f3400de7fcf27fccd1d4d17fd8fecd/greenlet-3.2.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1", size = 694659, upload-time = "2025-08-07T13:53:17.759Z" }, { url = "https://files.pythonhosted.org/packages/92/2e/ea25914b1ebfde93b6fc4ff46d6864564fba59024e928bdc7de475affc25/greenlet-3.2.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735", size = 695355, upload-time = "2025-08-07T13:18:34.517Z" }, { url = "https://files.pythonhosted.org/packages/72/60/fc56c62046ec17f6b0d3060564562c64c862948c9d4bc8aa807cf5bd74f4/greenlet-3.2.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337", size = 657512, upload-time = "2025-08-07T13:18:33.969Z" }, + { url = "https://files.pythonhosted.org/packages/23/6e/74407aed965a4ab6ddd93a7ded3180b730d281c77b765788419484cdfeef/greenlet-3.2.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2917bdf657f5859fbf3386b12d68ede4cf1f04c90c3a6bc1f013dd68a22e2269", size = 1612508, upload-time = "2025-11-04T12:42:23.427Z" }, + { url = "https://files.pythonhosted.org/packages/0d/da/343cd760ab2f92bac1845ca07ee3faea9fe52bee65f7bcb19f16ad7de08b/greenlet-3.2.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:015d48959d4add5d6c9f6c5210ee3803a830dce46356e3bc326d6776bde54681", size = 1680760, upload-time = "2025-11-04T12:42:25.341Z" }, { url = "https://files.pythonhosted.org/packages/e3/a5/6ddab2b4c112be95601c13428db1d8b6608a8b6039816f2ba09c346c08fc/greenlet-3.2.4-cp314-cp314-win_amd64.whl", hash = "sha256:e37ab26028f12dbb0ff65f29a8d3d44a765c61e729647bf2ddfbbed621726f01", size = 303425, upload-time = "2025-08-07T13:32:27.59Z" }, ] @@ -3347,7 +3349,7 @@ wheels = [ [[package]] name = "opentelemetry-exporter-gcp-logging" -version = "1.10.0a0" +version = "1.11.0a0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-cloud-logging" }, @@ -3355,14 +3357,14 @@ dependencies = [ { name = "opentelemetry-resourcedetector-gcp" }, { name = "opentelemetry-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8c/a0/ff56dc397dcccad4abd4da2b9b070831d2af9dea7d4dc1079613d8162e64/opentelemetry_exporter_gcp_logging-1.10.0a0.tar.gz", hash = "sha256:a4db7e89a108270399811a8f38566664489c70ada0ce05f0fdbc8b729f8cd0ef", size = 18450, upload-time = "2025-10-14T17:30:52.981Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/2d/6aa7063b009768d8f9415b36a29ae9b3eb1e2c5eff70f58ca15e104c245f/opentelemetry_exporter_gcp_logging-1.11.0a0.tar.gz", hash = "sha256:58496f11b930c84570060ffbd4343cd0b597ea13c7bc5c879df01163dd552f14", size = 22400, upload-time = "2025-11-04T19:32:13.812Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/bc/e3198a928aa7fee2ac98a39d8dc6310aa80350b66f3d624cbf317c3e3ee6/opentelemetry_exporter_gcp_logging-1.10.0a0-py3-none-any.whl", hash = "sha256:cb03a439ca34d42353318a9551900491abe4a369270ede5ce13d2e0a6e817a7d", size = 12509, upload-time = "2025-10-14T17:30:47.2Z" }, + { url = "https://files.pythonhosted.org/packages/a4/b7/2d3df53fa39bfd52f88c78a60367d45a7b1adbf8a756cce62d6ac149d49a/opentelemetry_exporter_gcp_logging-1.11.0a0-py3-none-any.whl", hash = "sha256:f8357c552947cb9c0101c4575a7702b8d3268e28bdeefdd1405cf838e128c6ef", size = 14168, upload-time = "2025-11-04T19:32:07.073Z" }, ] [[package]] name = "opentelemetry-exporter-gcp-monitoring" -version = "1.10.0a0" +version = "1.11.0a0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-cloud-monitoring" }, @@ -3370,14 +3372,14 @@ dependencies = [ { name = "opentelemetry-resourcedetector-gcp" }, { name = "opentelemetry-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1e/fc/7111500850db20890a080c2e35d5ef936bbec7082b0cd390ed45f9e18371/opentelemetry_exporter_gcp_monitoring-1.10.0a0.tar.gz", hash = "sha256:48520fe053d61667ca73a2dd64d4940200cc1b9063dbbf4e380728941b3da2e9", size = 20540, upload-time = "2025-10-14T17:30:54.008Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/48/d1c7d2380bb1754d1eb6a011a2e0de08c6868cb6c0f34bcda0444fa0d614/opentelemetry_exporter_gcp_monitoring-1.11.0a0.tar.gz", hash = "sha256:386276eddbbd978a6f30fafd3397975beeb02a1302bdad554185242a8e2c343c", size = 20828, upload-time = "2025-11-04T19:32:14.522Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/b7/e2690efa88f159679a900b9ac4bf33bb8e16248d384b50f92772a973a31a/opentelemetry_exporter_gcp_monitoring-1.10.0a0-py3-none-any.whl", hash = "sha256:a6ad379a77a5c4d65331216faa2b8ae7426cb744f597e5f0af99382759c42a3f", size = 13611, upload-time = "2025-10-14T17:30:48.196Z" }, + { url = "https://files.pythonhosted.org/packages/8c/8c/03a6e73e270a9c890dbd6cc1c47c83d86b8a8a974a9168d92e043c6277cc/opentelemetry_exporter_gcp_monitoring-1.11.0a0-py3-none-any.whl", hash = "sha256:b6740cba61b2f9555274829fe87a58447b64d0378f1067a4faebb4f5b364ca22", size = 13611, upload-time = "2025-11-04T19:32:08.212Z" }, ] [[package]] name = "opentelemetry-exporter-gcp-trace" -version = "1.10.0" +version = "1.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-cloud-trace" }, @@ -3385,9 +3387,9 @@ dependencies = [ { name = "opentelemetry-resourcedetector-gcp" }, { name = "opentelemetry-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/38/38a75b0a8e64c27af63871ca03bb8fc111437f9273ddcc705b1f55b10f40/opentelemetry_exporter_gcp_trace-1.10.0.tar.gz", hash = "sha256:2c0f2bb69ba4272e984d6adb3225f1d51ed6897b03f6db854588ccae0f08157f", size = 18604, upload-time = "2025-10-14T17:30:54.608Z" } +sdist = { url = "https://files.pythonhosted.org/packages/10/9c/4c3b26e5494f8b53c7873732a2317df905abe2b8ab33e9edfcbd5a8ff79b/opentelemetry_exporter_gcp_trace-1.11.0.tar.gz", hash = "sha256:c947ab4ab53e16517ade23d6fe71fe88cf7ca3f57a42c9f0e4162d2b929fecb6", size = 18770, upload-time = "2025-11-04T19:32:15.109Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e2/95/1a108bb61ff162555f72f4dd1ac618b6b7fa0b888e36f82cf3ec5c640b7c/opentelemetry_exporter_gcp_trace-1.10.0-py3-none-any.whl", hash = "sha256:766277704ebd86d0225cf734cd6d6c07c57ddb1d006bad5b3ede97e6d9018794", size = 14016, upload-time = "2025-10-14T17:30:49.114Z" }, + { url = "https://files.pythonhosted.org/packages/5f/4a/876703e8c5845198d95cd4006c8d1b2e3b129a9e288558e33133360f8d5d/opentelemetry_exporter_gcp_trace-1.11.0-py3-none-any.whl", hash = "sha256:b3dcb314e1a9985e9185cb7720b693eb393886fde98ae4c095ffc0893de6cefa", size = 14016, upload-time = "2025-11-04T19:32:09.009Z" }, ] [[package]] @@ -3449,7 +3451,7 @@ wheels = [ [[package]] name = "opentelemetry-resourcedetector-gcp" -version = "1.10.0a0" +version = "1.11.0a0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, @@ -3457,9 +3459,9 @@ dependencies = [ { name = "requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e0/ed/46daeac6d5c24d93a8b7bf58cccfbd190a6b9fe9a4db27e77bf5ef7b0f60/opentelemetry_resourcedetector_gcp-1.10.0a0.tar.gz", hash = "sha256:89b1adfdc7cb66b314da7cae78e1084ec3b64580f2d0532395ad4e079b4ae3f9", size = 18614, upload-time = "2025-10-14T17:30:56.063Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c1/5d/2b3240d914b87b6dd9cd5ca2ef1ccaf1d0626b897d4c06877e22c8c10fcf/opentelemetry_resourcedetector_gcp-1.11.0a0.tar.gz", hash = "sha256:915a1d6fd15daca9eedd3fc52b0f705375054f2ef140e2e7a6b4cca95a47cdb1", size = 18796, upload-time = "2025-11-04T19:32:16.59Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/52/38/bbcb219e822299e87daf8d9df28743c946e2ef04d24f19d26a61cfd28734/opentelemetry_resourcedetector_gcp-1.10.0a0-py3-none-any.whl", hash = "sha256:942319cad3244c2e05b67df1d89dcdb7f482e5a2239231340722ad642de848a9", size = 18801, upload-time = "2025-10-14T17:30:51.842Z" }, + { url = "https://files.pythonhosted.org/packages/c3/6c/1e13fe142a7ca3dc6489167203a1209d32430cca12775e1df9c9a41c54b2/opentelemetry_resourcedetector_gcp-1.11.0a0-py3-none-any.whl", hash = "sha256:5d65a2a039b1d40c6f41421dbb08d5f441368275ac6de6e76a8fccd1f6acb67e", size = 18798, upload-time = "2025-11-04T19:32:10.915Z" }, ] [[package]] @@ -4284,7 +4286,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.12.3" +version = "2.12.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -4292,123 +4294,127 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f3/1e/4f0a3233767010308f2fd6bd0814597e3f63f1dc98304a9112b8759df4ff/pydantic-2.12.3.tar.gz", hash = "sha256:1da1c82b0fc140bb0103bc1441ffe062154c8d38491189751ee00fd8ca65ce74", size = 819383, upload-time = "2025-10-17T15:04:21.222Z" } +sdist = { url = "https://files.pythonhosted.org/packages/96/ad/a17bc283d7d81837c061c49e3eaa27a45991759a1b7eae1031921c6bd924/pydantic-2.12.4.tar.gz", hash = "sha256:0f8cb9555000a4b5b617f66bfd2566264c4984b27589d3b845685983e8ea85ac", size = 821038, upload-time = "2025-11-05T10:50:08.59Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a1/6b/83661fa77dcefa195ad5f8cd9af3d1a7450fd57cc883ad04d65446ac2029/pydantic-2.12.3-py3-none-any.whl", hash = "sha256:6986454a854bc3bc6e5443e1369e06a3a456af9d339eda45510f517d9ea5c6bf", size = 462431, upload-time = "2025-10-17T15:04:19.346Z" }, + { url = "https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl", hash = "sha256:92d3d202a745d46f9be6df459ac5a064fdaa3c1c4cd8adcfa332ccf3c05f871e", size = 463400, upload-time = "2025-11-05T10:50:06.732Z" }, ] [[package]] name = "pydantic-core" -version = "2.41.4" +version = "2.41.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/df/18/d0944e8eaaa3efd0a91b0f1fc537d3be55ad35091b6a87638211ba691964/pydantic_core-2.41.4.tar.gz", hash = "sha256:70e47929a9d4a1905a67e4b687d5946026390568a8e952b92824118063cee4d5", size = 457557, upload-time = "2025-10-14T10:23:47.909Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/3d/9b8ca77b0f76fcdbf8bc6b72474e264283f461284ca84ac3fde570c6c49a/pydantic_core-2.41.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2442d9a4d38f3411f22eb9dd0912b7cbf4b7d5b6c92c4173b75d3e1ccd84e36e", size = 2111197, upload-time = "2025-10-14T10:19:43.303Z" }, - { url = "https://files.pythonhosted.org/packages/59/92/b7b0fe6ed4781642232755cb7e56a86e2041e1292f16d9ae410a0ccee5ac/pydantic_core-2.41.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:30a9876226dda131a741afeab2702e2d127209bde3c65a2b8133f428bc5d006b", size = 1917909, upload-time = "2025-10-14T10:19:45.194Z" }, - { url = "https://files.pythonhosted.org/packages/52/8c/3eb872009274ffa4fb6a9585114e161aa1a0915af2896e2d441642929fe4/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d55bbac04711e2980645af68b97d445cdbcce70e5216de444a6c4b6943ebcccd", size = 1969905, upload-time = "2025-10-14T10:19:46.567Z" }, - { url = "https://files.pythonhosted.org/packages/f4/21/35adf4a753bcfaea22d925214a0c5b880792e3244731b3f3e6fec0d124f7/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e1d778fb7849a42d0ee5927ab0f7453bf9f85eef8887a546ec87db5ddb178945", size = 2051938, upload-time = "2025-10-14T10:19:48.237Z" }, - { url = "https://files.pythonhosted.org/packages/7d/d0/cdf7d126825e36d6e3f1eccf257da8954452934ede275a8f390eac775e89/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b65077a4693a98b90ec5ad8f203ad65802a1b9b6d4a7e48066925a7e1606706", size = 2250710, upload-time = "2025-10-14T10:19:49.619Z" }, - { url = "https://files.pythonhosted.org/packages/2e/1c/af1e6fd5ea596327308f9c8d1654e1285cc3d8de0d584a3c9d7705bf8a7c/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:62637c769dee16eddb7686bf421be48dfc2fae93832c25e25bc7242e698361ba", size = 2367445, upload-time = "2025-10-14T10:19:51.269Z" }, - { url = "https://files.pythonhosted.org/packages/d3/81/8cece29a6ef1b3a92f956ea6da6250d5b2d2e7e4d513dd3b4f0c7a83dfea/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfe3aa529c8f501babf6e502936b9e8d4698502b2cfab41e17a028d91b1ac7b", size = 2072875, upload-time = "2025-10-14T10:19:52.671Z" }, - { url = "https://files.pythonhosted.org/packages/e3/37/a6a579f5fc2cd4d5521284a0ab6a426cc6463a7b3897aeb95b12f1ba607b/pydantic_core-2.41.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca2322da745bf2eeb581fc9ea3bbb31147702163ccbcbf12a3bb630e4bf05e1d", size = 2191329, upload-time = "2025-10-14T10:19:54.214Z" }, - { url = "https://files.pythonhosted.org/packages/ae/03/505020dc5c54ec75ecba9f41119fd1e48f9e41e4629942494c4a8734ded1/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e8cd3577c796be7231dcf80badcf2e0835a46665eaafd8ace124d886bab4d700", size = 2151658, upload-time = "2025-10-14T10:19:55.843Z" }, - { url = "https://files.pythonhosted.org/packages/cb/5d/2c0d09fb53aa03bbd2a214d89ebfa6304be7df9ed86ee3dc7770257f41ee/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:1cae8851e174c83633f0833e90636832857297900133705ee158cf79d40f03e6", size = 2316777, upload-time = "2025-10-14T10:19:57.607Z" }, - { url = "https://files.pythonhosted.org/packages/ea/4b/c2c9c8f5e1f9c864b57d08539d9d3db160e00491c9f5ee90e1bfd905e644/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a26d950449aae348afe1ac8be5525a00ae4235309b729ad4d3399623125b43c9", size = 2320705, upload-time = "2025-10-14T10:19:59.016Z" }, - { url = "https://files.pythonhosted.org/packages/28/c3/a74c1c37f49c0a02c89c7340fafc0ba816b29bd495d1a31ce1bdeacc6085/pydantic_core-2.41.4-cp310-cp310-win32.whl", hash = "sha256:0cf2a1f599efe57fa0051312774280ee0f650e11152325e41dfd3018ef2c1b57", size = 1975464, upload-time = "2025-10-14T10:20:00.581Z" }, - { url = "https://files.pythonhosted.org/packages/d6/23/5dd5c1324ba80303368f7569e2e2e1a721c7d9eb16acb7eb7b7f85cb1be2/pydantic_core-2.41.4-cp310-cp310-win_amd64.whl", hash = "sha256:a8c2e340d7e454dc3340d3d2e8f23558ebe78c98aa8f68851b04dcb7bc37abdc", size = 2024497, upload-time = "2025-10-14T10:20:03.018Z" }, - { url = "https://files.pythonhosted.org/packages/62/4c/f6cbfa1e8efacd00b846764e8484fe173d25b8dab881e277a619177f3384/pydantic_core-2.41.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:28ff11666443a1a8cf2a044d6a545ebffa8382b5f7973f22c36109205e65dc80", size = 2109062, upload-time = "2025-10-14T10:20:04.486Z" }, - { url = "https://files.pythonhosted.org/packages/21/f8/40b72d3868896bfcd410e1bd7e516e762d326201c48e5b4a06446f6cf9e8/pydantic_core-2.41.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:61760c3925d4633290292bad462e0f737b840508b4f722247d8729684f6539ae", size = 1916301, upload-time = "2025-10-14T10:20:06.857Z" }, - { url = "https://files.pythonhosted.org/packages/94/4d/d203dce8bee7faeca791671c88519969d98d3b4e8f225da5b96dad226fc8/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eae547b7315d055b0de2ec3965643b0ab82ad0106a7ffd29615ee9f266a02827", size = 1968728, upload-time = "2025-10-14T10:20:08.353Z" }, - { url = "https://files.pythonhosted.org/packages/65/f5/6a66187775df87c24d526985b3a5d78d861580ca466fbd9d4d0e792fcf6c/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ef9ee5471edd58d1fcce1c80ffc8783a650e3e3a193fe90d52e43bb4d87bff1f", size = 2050238, upload-time = "2025-10-14T10:20:09.766Z" }, - { url = "https://files.pythonhosted.org/packages/5e/b9/78336345de97298cf53236b2f271912ce11f32c1e59de25a374ce12f9cce/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15dd504af121caaf2c95cb90c0ebf71603c53de98305621b94da0f967e572def", size = 2249424, upload-time = "2025-10-14T10:20:11.732Z" }, - { url = "https://files.pythonhosted.org/packages/99/bb/a4584888b70ee594c3d374a71af5075a68654d6c780369df269118af7402/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a926768ea49a8af4d36abd6a8968b8790f7f76dd7cbd5a4c180db2b4ac9a3a2", size = 2366047, upload-time = "2025-10-14T10:20:13.647Z" }, - { url = "https://files.pythonhosted.org/packages/5f/8d/17fc5de9d6418e4d2ae8c675f905cdafdc59d3bf3bf9c946b7ab796a992a/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6916b9b7d134bff5440098a4deb80e4cb623e68974a87883299de9124126c2a8", size = 2071163, upload-time = "2025-10-14T10:20:15.307Z" }, - { url = "https://files.pythonhosted.org/packages/54/e7/03d2c5c0b8ed37a4617430db68ec5e7dbba66358b629cd69e11b4d564367/pydantic_core-2.41.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cf90535979089df02e6f17ffd076f07237efa55b7343d98760bde8743c4b265", size = 2190585, upload-time = "2025-10-14T10:20:17.3Z" }, - { url = "https://files.pythonhosted.org/packages/be/fc/15d1c9fe5ad9266a5897d9b932b7f53d7e5cfc800573917a2c5d6eea56ec/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7533c76fa647fade2d7ec75ac5cc079ab3f34879626dae5689b27790a6cf5a5c", size = 2150109, upload-time = "2025-10-14T10:20:19.143Z" }, - { url = "https://files.pythonhosted.org/packages/26/ef/e735dd008808226c83ba56972566138665b71477ad580fa5a21f0851df48/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:37e516bca9264cbf29612539801ca3cd5d1be465f940417b002905e6ed79d38a", size = 2315078, upload-time = "2025-10-14T10:20:20.742Z" }, - { url = "https://files.pythonhosted.org/packages/90/00/806efdcf35ff2ac0f938362350cd9827b8afb116cc814b6b75cf23738c7c/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0c19cb355224037c83642429b8ce261ae108e1c5fbf5c028bac63c77b0f8646e", size = 2318737, upload-time = "2025-10-14T10:20:22.306Z" }, - { url = "https://files.pythonhosted.org/packages/41/7e/6ac90673fe6cb36621a2283552897838c020db343fa86e513d3f563b196f/pydantic_core-2.41.4-cp311-cp311-win32.whl", hash = "sha256:09c2a60e55b357284b5f31f5ab275ba9f7f70b7525e18a132ec1f9160b4f1f03", size = 1974160, upload-time = "2025-10-14T10:20:23.817Z" }, - { url = "https://files.pythonhosted.org/packages/e0/9d/7c5e24ee585c1f8b6356e1d11d40ab807ffde44d2db3b7dfd6d20b09720e/pydantic_core-2.41.4-cp311-cp311-win_amd64.whl", hash = "sha256:711156b6afb5cb1cb7c14a2cc2c4a8b4c717b69046f13c6b332d8a0a8f41ca3e", size = 2021883, upload-time = "2025-10-14T10:20:25.48Z" }, - { url = "https://files.pythonhosted.org/packages/33/90/5c172357460fc28b2871eb4a0fb3843b136b429c6fa827e4b588877bf115/pydantic_core-2.41.4-cp311-cp311-win_arm64.whl", hash = "sha256:6cb9cf7e761f4f8a8589a45e49ed3c0d92d1d696a45a6feaee8c904b26efc2db", size = 1968026, upload-time = "2025-10-14T10:20:27.039Z" }, - { url = "https://files.pythonhosted.org/packages/e9/81/d3b3e95929c4369d30b2a66a91db63c8ed0a98381ae55a45da2cd1cc1288/pydantic_core-2.41.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ab06d77e053d660a6faaf04894446df7b0a7e7aba70c2797465a0a1af00fc887", size = 2099043, upload-time = "2025-10-14T10:20:28.561Z" }, - { url = "https://files.pythonhosted.org/packages/58/da/46fdac49e6717e3a94fc9201403e08d9d61aa7a770fab6190b8740749047/pydantic_core-2.41.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c53ff33e603a9c1179a9364b0a24694f183717b2e0da2b5ad43c316c956901b2", size = 1910699, upload-time = "2025-10-14T10:20:30.217Z" }, - { url = "https://files.pythonhosted.org/packages/1e/63/4d948f1b9dd8e991a5a98b77dd66c74641f5f2e5225fee37994b2e07d391/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:304c54176af2c143bd181d82e77c15c41cbacea8872a2225dd37e6544dce9999", size = 1952121, upload-time = "2025-10-14T10:20:32.246Z" }, - { url = "https://files.pythonhosted.org/packages/b2/a7/e5fc60a6f781fc634ecaa9ecc3c20171d238794cef69ae0af79ac11b89d7/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:025ba34a4cf4fb32f917d5d188ab5e702223d3ba603be4d8aca2f82bede432a4", size = 2041590, upload-time = "2025-10-14T10:20:34.332Z" }, - { url = "https://files.pythonhosted.org/packages/70/69/dce747b1d21d59e85af433428978a1893c6f8a7068fa2bb4a927fba7a5ff/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9f5f30c402ed58f90c70e12eff65547d3ab74685ffe8283c719e6bead8ef53f", size = 2219869, upload-time = "2025-10-14T10:20:35.965Z" }, - { url = "https://files.pythonhosted.org/packages/83/6a/c070e30e295403bf29c4df1cb781317b6a9bac7cd07b8d3acc94d501a63c/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd96e5d15385d301733113bcaa324c8bcf111275b7675a9c6e88bfb19fc05e3b", size = 2345169, upload-time = "2025-10-14T10:20:37.627Z" }, - { url = "https://files.pythonhosted.org/packages/f0/83/06d001f8043c336baea7fd202a9ac7ad71f87e1c55d8112c50b745c40324/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98f348cbb44fae6e9653c1055db7e29de67ea6a9ca03a5fa2c2e11a47cff0e47", size = 2070165, upload-time = "2025-10-14T10:20:39.246Z" }, - { url = "https://files.pythonhosted.org/packages/14/0a/e567c2883588dd12bcbc110232d892cf385356f7c8a9910311ac997ab715/pydantic_core-2.41.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec22626a2d14620a83ca583c6f5a4080fa3155282718b6055c2ea48d3ef35970", size = 2189067, upload-time = "2025-10-14T10:20:41.015Z" }, - { url = "https://files.pythonhosted.org/packages/f4/1d/3d9fca34273ba03c9b1c5289f7618bc4bd09c3ad2289b5420481aa051a99/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a95d4590b1f1a43bf33ca6d647b990a88f4a3824a8c4572c708f0b45a5290ed", size = 2132997, upload-time = "2025-10-14T10:20:43.106Z" }, - { url = "https://files.pythonhosted.org/packages/52/70/d702ef7a6cd41a8afc61f3554922b3ed8d19dd54c3bd4bdbfe332e610827/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:f9672ab4d398e1b602feadcffcdd3af44d5f5e6ddc15bc7d15d376d47e8e19f8", size = 2307187, upload-time = "2025-10-14T10:20:44.849Z" }, - { url = "https://files.pythonhosted.org/packages/68/4c/c06be6e27545d08b802127914156f38d10ca287a9e8489342793de8aae3c/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:84d8854db5f55fead3b579f04bda9a36461dab0730c5d570e1526483e7bb8431", size = 2305204, upload-time = "2025-10-14T10:20:46.781Z" }, - { url = "https://files.pythonhosted.org/packages/b0/e5/35ae4919bcd9f18603419e23c5eaf32750224a89d41a8df1a3704b69f77e/pydantic_core-2.41.4-cp312-cp312-win32.whl", hash = "sha256:9be1c01adb2ecc4e464392c36d17f97e9110fbbc906bcbe1c943b5b87a74aabd", size = 1972536, upload-time = "2025-10-14T10:20:48.39Z" }, - { url = "https://files.pythonhosted.org/packages/1e/c2/49c5bb6d2a49eb2ee3647a93e3dae7080c6409a8a7558b075027644e879c/pydantic_core-2.41.4-cp312-cp312-win_amd64.whl", hash = "sha256:d682cf1d22bab22a5be08539dca3d1593488a99998f9f412137bc323179067ff", size = 2031132, upload-time = "2025-10-14T10:20:50.421Z" }, - { url = "https://files.pythonhosted.org/packages/06/23/936343dbcba6eec93f73e95eb346810fc732f71ba27967b287b66f7b7097/pydantic_core-2.41.4-cp312-cp312-win_arm64.whl", hash = "sha256:833eebfd75a26d17470b58768c1834dfc90141b7afc6eb0429c21fc5a21dcfb8", size = 1969483, upload-time = "2025-10-14T10:20:52.35Z" }, - { url = "https://files.pythonhosted.org/packages/13/d0/c20adabd181a029a970738dfe23710b52a31f1258f591874fcdec7359845/pydantic_core-2.41.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:85e050ad9e5f6fe1004eec65c914332e52f429bc0ae12d6fa2092407a462c746", size = 2105688, upload-time = "2025-10-14T10:20:54.448Z" }, - { url = "https://files.pythonhosted.org/packages/00/b6/0ce5c03cec5ae94cca220dfecddc453c077d71363b98a4bbdb3c0b22c783/pydantic_core-2.41.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7393f1d64792763a48924ba31d1e44c2cfbc05e3b1c2c9abb4ceeadd912cced", size = 1910807, upload-time = "2025-10-14T10:20:56.115Z" }, - { url = "https://files.pythonhosted.org/packages/68/3e/800d3d02c8beb0b5c069c870cbb83799d085debf43499c897bb4b4aaff0d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94dab0940b0d1fb28bcab847adf887c66a27a40291eedf0b473be58761c9799a", size = 1956669, upload-time = "2025-10-14T10:20:57.874Z" }, - { url = "https://files.pythonhosted.org/packages/60/a4/24271cc71a17f64589be49ab8bd0751f6a0a03046c690df60989f2f95c2c/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de7c42f897e689ee6f9e93c4bec72b99ae3b32a2ade1c7e4798e690ff5246e02", size = 2051629, upload-time = "2025-10-14T10:21:00.006Z" }, - { url = "https://files.pythonhosted.org/packages/68/de/45af3ca2f175d91b96bfb62e1f2d2f1f9f3b14a734afe0bfeff079f78181/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:664b3199193262277b8b3cd1e754fb07f2c6023289c815a1e1e8fb415cb247b1", size = 2224049, upload-time = "2025-10-14T10:21:01.801Z" }, - { url = "https://files.pythonhosted.org/packages/af/8f/ae4e1ff84672bf869d0a77af24fd78387850e9497753c432875066b5d622/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d95b253b88f7d308b1c0b417c4624f44553ba4762816f94e6986819b9c273fb2", size = 2342409, upload-time = "2025-10-14T10:21:03.556Z" }, - { url = "https://files.pythonhosted.org/packages/18/62/273dd70b0026a085c7b74b000394e1ef95719ea579c76ea2f0cc8893736d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1351f5bbdbbabc689727cb91649a00cb9ee7203e0a6e54e9f5ba9e22e384b84", size = 2069635, upload-time = "2025-10-14T10:21:05.385Z" }, - { url = "https://files.pythonhosted.org/packages/30/03/cf485fff699b4cdaea469bc481719d3e49f023241b4abb656f8d422189fc/pydantic_core-2.41.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1affa4798520b148d7182da0615d648e752de4ab1a9566b7471bc803d88a062d", size = 2194284, upload-time = "2025-10-14T10:21:07.122Z" }, - { url = "https://files.pythonhosted.org/packages/f9/7e/c8e713db32405dfd97211f2fc0a15d6bf8adb7640f3d18544c1f39526619/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7b74e18052fea4aa8dea2fb7dbc23d15439695da6cbe6cfc1b694af1115df09d", size = 2137566, upload-time = "2025-10-14T10:21:08.981Z" }, - { url = "https://files.pythonhosted.org/packages/04/f7/db71fd4cdccc8b75990f79ccafbbd66757e19f6d5ee724a6252414483fb4/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:285b643d75c0e30abda9dc1077395624f314a37e3c09ca402d4015ef5979f1a2", size = 2316809, upload-time = "2025-10-14T10:21:10.805Z" }, - { url = "https://files.pythonhosted.org/packages/76/63/a54973ddb945f1bca56742b48b144d85c9fc22f819ddeb9f861c249d5464/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:f52679ff4218d713b3b33f88c89ccbf3a5c2c12ba665fb80ccc4192b4608dbab", size = 2311119, upload-time = "2025-10-14T10:21:12.583Z" }, - { url = "https://files.pythonhosted.org/packages/f8/03/5d12891e93c19218af74843a27e32b94922195ded2386f7b55382f904d2f/pydantic_core-2.41.4-cp313-cp313-win32.whl", hash = "sha256:ecde6dedd6fff127c273c76821bb754d793be1024bc33314a120f83a3c69460c", size = 1981398, upload-time = "2025-10-14T10:21:14.584Z" }, - { url = "https://files.pythonhosted.org/packages/be/d8/fd0de71f39db91135b7a26996160de71c073d8635edfce8b3c3681be0d6d/pydantic_core-2.41.4-cp313-cp313-win_amd64.whl", hash = "sha256:d081a1f3800f05409ed868ebb2d74ac39dd0c1ff6c035b5162356d76030736d4", size = 2030735, upload-time = "2025-10-14T10:21:16.432Z" }, - { url = "https://files.pythonhosted.org/packages/72/86/c99921c1cf6650023c08bfab6fe2d7057a5142628ef7ccfa9921f2dda1d5/pydantic_core-2.41.4-cp313-cp313-win_arm64.whl", hash = "sha256:f8e49c9c364a7edcbe2a310f12733aad95b022495ef2a8d653f645e5d20c1564", size = 1973209, upload-time = "2025-10-14T10:21:18.213Z" }, - { url = "https://files.pythonhosted.org/packages/36/0d/b5706cacb70a8414396efdda3d72ae0542e050b591119e458e2490baf035/pydantic_core-2.41.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ed97fd56a561f5eb5706cebe94f1ad7c13b84d98312a05546f2ad036bafe87f4", size = 1877324, upload-time = "2025-10-14T10:21:20.363Z" }, - { url = "https://files.pythonhosted.org/packages/de/2d/cba1fa02cfdea72dfb3a9babb067c83b9dff0bbcb198368e000a6b756ea7/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a870c307bf1ee91fc58a9a61338ff780d01bfae45922624816878dce784095d2", size = 1884515, upload-time = "2025-10-14T10:21:22.339Z" }, - { url = "https://files.pythonhosted.org/packages/07/ea/3df927c4384ed9b503c9cc2d076cf983b4f2adb0c754578dfb1245c51e46/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d25e97bc1f5f8f7985bdc2335ef9e73843bb561eb1fa6831fdfc295c1c2061cf", size = 2042819, upload-time = "2025-10-14T10:21:26.683Z" }, - { url = "https://files.pythonhosted.org/packages/6a/ee/df8e871f07074250270a3b1b82aad4cd0026b588acd5d7d3eb2fcb1471a3/pydantic_core-2.41.4-cp313-cp313t-win_amd64.whl", hash = "sha256:d405d14bea042f166512add3091c1af40437c2e7f86988f3915fabd27b1e9cd2", size = 1995866, upload-time = "2025-10-14T10:21:28.951Z" }, - { url = "https://files.pythonhosted.org/packages/fc/de/b20f4ab954d6d399499c33ec4fafc46d9551e11dc1858fb7f5dca0748ceb/pydantic_core-2.41.4-cp313-cp313t-win_arm64.whl", hash = "sha256:19f3684868309db5263a11bace3c45d93f6f24afa2ffe75a647583df22a2ff89", size = 1970034, upload-time = "2025-10-14T10:21:30.869Z" }, - { url = "https://files.pythonhosted.org/packages/54/28/d3325da57d413b9819365546eb9a6e8b7cbd9373d9380efd5f74326143e6/pydantic_core-2.41.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:e9205d97ed08a82ebb9a307e92914bb30e18cdf6f6b12ca4bedadb1588a0bfe1", size = 2102022, upload-time = "2025-10-14T10:21:32.809Z" }, - { url = "https://files.pythonhosted.org/packages/9e/24/b58a1bc0d834bf1acc4361e61233ee217169a42efbdc15a60296e13ce438/pydantic_core-2.41.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:82df1f432b37d832709fbcc0e24394bba04a01b6ecf1ee87578145c19cde12ac", size = 1905495, upload-time = "2025-10-14T10:21:34.812Z" }, - { url = "https://files.pythonhosted.org/packages/fb/a4/71f759cc41b7043e8ecdaab81b985a9b6cad7cec077e0b92cff8b71ecf6b/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3b4cc4539e055cfa39a3763c939f9d409eb40e85813257dcd761985a108554", size = 1956131, upload-time = "2025-10-14T10:21:36.924Z" }, - { url = "https://files.pythonhosted.org/packages/b0/64/1e79ac7aa51f1eec7c4cda8cbe456d5d09f05fdd68b32776d72168d54275/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1eb1754fce47c63d2ff57fdb88c351a6c0150995890088b33767a10218eaa4e", size = 2052236, upload-time = "2025-10-14T10:21:38.927Z" }, - { url = "https://files.pythonhosted.org/packages/e9/e3/a3ffc363bd4287b80f1d43dc1c28ba64831f8dfc237d6fec8f2661138d48/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6ab5ab30ef325b443f379ddb575a34969c333004fca5a1daa0133a6ffaad616", size = 2223573, upload-time = "2025-10-14T10:21:41.574Z" }, - { url = "https://files.pythonhosted.org/packages/28/27/78814089b4d2e684a9088ede3790763c64693c3d1408ddc0a248bc789126/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:31a41030b1d9ca497634092b46481b937ff9397a86f9f51bd41c4767b6fc04af", size = 2342467, upload-time = "2025-10-14T10:21:44.018Z" }, - { url = "https://files.pythonhosted.org/packages/92/97/4de0e2a1159cb85ad737e03306717637842c88c7fd6d97973172fb183149/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a44ac1738591472c3d020f61c6df1e4015180d6262ebd39bf2aeb52571b60f12", size = 2063754, upload-time = "2025-10-14T10:21:46.466Z" }, - { url = "https://files.pythonhosted.org/packages/0f/50/8cb90ce4b9efcf7ae78130afeb99fd1c86125ccdf9906ef64b9d42f37c25/pydantic_core-2.41.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d72f2b5e6e82ab8f94ea7d0d42f83c487dc159c5240d8f83beae684472864e2d", size = 2196754, upload-time = "2025-10-14T10:21:48.486Z" }, - { url = "https://files.pythonhosted.org/packages/34/3b/ccdc77af9cd5082723574a1cc1bcae7a6acacc829d7c0a06201f7886a109/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c4d1e854aaf044487d31143f541f7aafe7b482ae72a022c664b2de2e466ed0ad", size = 2137115, upload-time = "2025-10-14T10:21:50.63Z" }, - { url = "https://files.pythonhosted.org/packages/ca/ba/e7c7a02651a8f7c52dc2cff2b64a30c313e3b57c7d93703cecea76c09b71/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b568af94267729d76e6ee5ececda4e283d07bbb28e8148bb17adad93d025d25a", size = 2317400, upload-time = "2025-10-14T10:21:52.959Z" }, - { url = "https://files.pythonhosted.org/packages/2c/ba/6c533a4ee8aec6b812c643c49bb3bd88d3f01e3cebe451bb85512d37f00f/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6d55fb8b1e8929b341cc313a81a26e0d48aa3b519c1dbaadec3a6a2b4fcad025", size = 2312070, upload-time = "2025-10-14T10:21:55.419Z" }, - { url = "https://files.pythonhosted.org/packages/22/ae/f10524fcc0ab8d7f96cf9a74c880243576fd3e72bd8ce4f81e43d22bcab7/pydantic_core-2.41.4-cp314-cp314-win32.whl", hash = "sha256:5b66584e549e2e32a1398df11da2e0a7eff45d5c2d9db9d5667c5e6ac764d77e", size = 1982277, upload-time = "2025-10-14T10:21:57.474Z" }, - { url = "https://files.pythonhosted.org/packages/b4/dc/e5aa27aea1ad4638f0c3fb41132f7eb583bd7420ee63204e2d4333a3bbf9/pydantic_core-2.41.4-cp314-cp314-win_amd64.whl", hash = "sha256:557a0aab88664cc552285316809cab897716a372afaf8efdbef756f8b890e894", size = 2024608, upload-time = "2025-10-14T10:21:59.557Z" }, - { url = "https://files.pythonhosted.org/packages/3e/61/51d89cc2612bd147198e120a13f150afbf0bcb4615cddb049ab10b81b79e/pydantic_core-2.41.4-cp314-cp314-win_arm64.whl", hash = "sha256:3f1ea6f48a045745d0d9f325989d8abd3f1eaf47dd00485912d1a3a63c623a8d", size = 1967614, upload-time = "2025-10-14T10:22:01.847Z" }, - { url = "https://files.pythonhosted.org/packages/0d/c2/472f2e31b95eff099961fa050c376ab7156a81da194f9edb9f710f68787b/pydantic_core-2.41.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6c1fe4c5404c448b13188dd8bd2ebc2bdd7e6727fa61ff481bcc2cca894018da", size = 1876904, upload-time = "2025-10-14T10:22:04.062Z" }, - { url = "https://files.pythonhosted.org/packages/4a/07/ea8eeb91173807ecdae4f4a5f4b150a520085b35454350fc219ba79e66a3/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:523e7da4d43b113bf8e7b49fa4ec0c35bf4fe66b2230bfc5c13cc498f12c6c3e", size = 1882538, upload-time = "2025-10-14T10:22:06.39Z" }, - { url = "https://files.pythonhosted.org/packages/1e/29/b53a9ca6cd366bfc928823679c6a76c7a4c69f8201c0ba7903ad18ebae2f/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5729225de81fb65b70fdb1907fcf08c75d498f4a6f15af005aabb1fdadc19dfa", size = 2041183, upload-time = "2025-10-14T10:22:08.812Z" }, - { url = "https://files.pythonhosted.org/packages/c7/3d/f8c1a371ceebcaf94d6dd2d77c6cf4b1c078e13a5837aee83f760b4f7cfd/pydantic_core-2.41.4-cp314-cp314t-win_amd64.whl", hash = "sha256:de2cfbb09e88f0f795fd90cf955858fc2c691df65b1f21f0aa00b99f3fbc661d", size = 1993542, upload-time = "2025-10-14T10:22:11.332Z" }, - { url = "https://files.pythonhosted.org/packages/8a/ac/9fc61b4f9d079482a290afe8d206b8f490e9fd32d4fc03ed4fc698214e01/pydantic_core-2.41.4-cp314-cp314t-win_arm64.whl", hash = "sha256:d34f950ae05a83e0ede899c595f312ca976023ea1db100cd5aa188f7005e3ab0", size = 1973897, upload-time = "2025-10-14T10:22:13.444Z" }, - { url = "https://files.pythonhosted.org/packages/b0/12/5ba58daa7f453454464f92b3ca7b9d7c657d8641c48e370c3ebc9a82dd78/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:a1b2cfec3879afb742a7b0bcfa53e4f22ba96571c9e54d6a3afe1052d17d843b", size = 2122139, upload-time = "2025-10-14T10:22:47.288Z" }, - { url = "https://files.pythonhosted.org/packages/21/fb/6860126a77725c3108baecd10fd3d75fec25191d6381b6eb2ac660228eac/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:d175600d975b7c244af6eb9c9041f10059f20b8bbffec9e33fdd5ee3f67cdc42", size = 1936674, upload-time = "2025-10-14T10:22:49.555Z" }, - { url = "https://files.pythonhosted.org/packages/de/be/57dcaa3ed595d81f8757e2b44a38240ac5d37628bce25fb20d02c7018776/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f184d657fa4947ae5ec9c47bd7e917730fa1cbb78195037e32dcbab50aca5ee", size = 1956398, upload-time = "2025-10-14T10:22:52.19Z" }, - { url = "https://files.pythonhosted.org/packages/2f/1d/679a344fadb9695f1a6a294d739fbd21d71fa023286daeea8c0ed49e7c2b/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ed810568aeffed3edc78910af32af911c835cc39ebbfacd1f0ab5dd53028e5c", size = 2138674, upload-time = "2025-10-14T10:22:54.499Z" }, - { url = "https://files.pythonhosted.org/packages/c4/48/ae937e5a831b7c0dc646b2ef788c27cd003894882415300ed21927c21efa/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:4f5d640aeebb438517150fdeec097739614421900e4a08db4a3ef38898798537", size = 2112087, upload-time = "2025-10-14T10:22:56.818Z" }, - { url = "https://files.pythonhosted.org/packages/5e/db/6db8073e3d32dae017da7e0d16a9ecb897d0a4d92e00634916e486097961/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:4a9ab037b71927babc6d9e7fc01aea9e66dc2a4a34dff06ef0724a4049629f94", size = 1920387, upload-time = "2025-10-14T10:22:59.342Z" }, - { url = "https://files.pythonhosted.org/packages/0d/c1/dd3542d072fcc336030d66834872f0328727e3b8de289c662faa04aa270e/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4dab9484ec605c3016df9ad4fd4f9a390bc5d816a3b10c6550f8424bb80b18c", size = 1951495, upload-time = "2025-10-14T10:23:02.089Z" }, - { url = "https://files.pythonhosted.org/packages/2b/c6/db8d13a1f8ab3f1eb08c88bd00fd62d44311e3456d1e85c0e59e0a0376e7/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8a5028425820731d8c6c098ab642d7b8b999758e24acae03ed38a66eca8335", size = 2139008, upload-time = "2025-10-14T10:23:04.539Z" }, - { url = "https://files.pythonhosted.org/packages/5d/d4/912e976a2dd0b49f31c98a060ca90b353f3b73ee3ea2fd0030412f6ac5ec/pydantic_core-2.41.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e5ab4fc177dd41536b3c32b2ea11380dd3d4619a385860621478ac2d25ceb00", size = 2106739, upload-time = "2025-10-14T10:23:06.934Z" }, - { url = "https://files.pythonhosted.org/packages/71/f0/66ec5a626c81eba326072d6ee2b127f8c139543f1bf609b4842978d37833/pydantic_core-2.41.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3d88d0054d3fa11ce936184896bed3c1c5441d6fa483b498fac6a5d0dd6f64a9", size = 1932549, upload-time = "2025-10-14T10:23:09.24Z" }, - { url = "https://files.pythonhosted.org/packages/c4/af/625626278ca801ea0a658c2dcf290dc9f21bb383098e99e7c6a029fccfc0/pydantic_core-2.41.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b2a054a8725f05b4b6503357e0ac1c4e8234ad3b0c2ac130d6ffc66f0e170e2", size = 2135093, upload-time = "2025-10-14T10:23:11.626Z" }, - { url = "https://files.pythonhosted.org/packages/20/f6/2fba049f54e0f4975fef66be654c597a1d005320fa141863699180c7697d/pydantic_core-2.41.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0d9db5a161c99375a0c68c058e227bee1d89303300802601d76a3d01f74e258", size = 2187971, upload-time = "2025-10-14T10:23:14.437Z" }, - { url = "https://files.pythonhosted.org/packages/0e/80/65ab839a2dfcd3b949202f9d920c34f9de5a537c3646662bdf2f7d999680/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6273ea2c8ffdac7b7fda2653c49682db815aebf4a89243a6feccf5e36c18c347", size = 2147939, upload-time = "2025-10-14T10:23:16.831Z" }, - { url = "https://files.pythonhosted.org/packages/44/58/627565d3d182ce6dfda18b8e1c841eede3629d59c9d7cbc1e12a03aeb328/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:4c973add636efc61de22530b2ef83a65f39b6d6f656df97f678720e20de26caa", size = 2311400, upload-time = "2025-10-14T10:23:19.234Z" }, - { url = "https://files.pythonhosted.org/packages/24/06/8a84711162ad5a5f19a88cead37cca81b4b1f294f46260ef7334ae4f24d3/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b69d1973354758007f46cf2d44a4f3d0933f10b6dc9bf15cf1356e037f6f731a", size = 2316840, upload-time = "2025-10-14T10:23:21.738Z" }, - { url = "https://files.pythonhosted.org/packages/aa/8b/b7bb512a4682a2f7fbfae152a755d37351743900226d29bd953aaf870eaa/pydantic_core-2.41.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3619320641fd212aaf5997b6ca505e97540b7e16418f4a241f44cdf108ffb50d", size = 2149135, upload-time = "2025-10-14T10:23:24.379Z" }, - { url = "https://files.pythonhosted.org/packages/7e/7d/138e902ed6399b866f7cfe4435d22445e16fff888a1c00560d9dc79a780f/pydantic_core-2.41.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:491535d45cd7ad7e4a2af4a5169b0d07bebf1adfd164b0368da8aa41e19907a5", size = 2104721, upload-time = "2025-10-14T10:23:26.906Z" }, - { url = "https://files.pythonhosted.org/packages/47/13/0525623cf94627f7b53b4c2034c81edc8491cbfc7c28d5447fa318791479/pydantic_core-2.41.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:54d86c0cada6aba4ec4c047d0e348cbad7063b87ae0f005d9f8c9ad04d4a92a2", size = 1931608, upload-time = "2025-10-14T10:23:29.306Z" }, - { url = "https://files.pythonhosted.org/packages/d6/f9/744bc98137d6ef0a233f808bfc9b18cf94624bf30836a18d3b05d08bf418/pydantic_core-2.41.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eca1124aced216b2500dc2609eade086d718e8249cb9696660ab447d50a758bd", size = 2132986, upload-time = "2025-10-14T10:23:32.057Z" }, - { url = "https://files.pythonhosted.org/packages/17/c8/629e88920171173f6049386cc71f893dff03209a9ef32b4d2f7e7c264bcf/pydantic_core-2.41.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c9024169becccf0cb470ada03ee578d7348c119a0d42af3dcf9eda96e3a247c", size = 2187516, upload-time = "2025-10-14T10:23:34.871Z" }, - { url = "https://files.pythonhosted.org/packages/2e/0f/4f2734688d98488782218ca61bcc118329bf5de05bb7fe3adc7dd79b0b86/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:26895a4268ae5a2849269f4991cdc97236e4b9c010e51137becf25182daac405", size = 2146146, upload-time = "2025-10-14T10:23:37.342Z" }, - { url = "https://files.pythonhosted.org/packages/ed/f2/ab385dbd94a052c62224b99cf99002eee99dbec40e10006c78575aead256/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:ca4df25762cf71308c446e33c9b1fdca2923a3f13de616e2a949f38bf21ff5a8", size = 2311296, upload-time = "2025-10-14T10:23:40.145Z" }, - { url = "https://files.pythonhosted.org/packages/fc/8e/e4f12afe1beeb9823bba5375f8f258df0cc61b056b0195fb1cf9f62a1a58/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:5a28fcedd762349519276c36634e71853b4541079cab4acaaac60c4421827308", size = 2315386, upload-time = "2025-10-14T10:23:42.624Z" }, - { url = "https://files.pythonhosted.org/packages/48/f7/925f65d930802e3ea2eb4d5afa4cb8730c8dc0d2cb89a59dc4ed2fcb2d74/pydantic_core-2.41.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c173ddcd86afd2535e2b695217e82191580663a1d1928239f877f5a1649ef39f", size = 2147775, upload-time = "2025-10-14T10:23:45.406Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", size = 2107298, upload-time = "2025-11-04T13:39:04.116Z" }, + { url = "https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", size = 1901475, upload-time = "2025-11-04T13:39:06.055Z" }, + { url = "https://files.pythonhosted.org/packages/5d/b6/338abf60225acc18cdc08b4faef592d0310923d19a87fba1faf05af5346e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", size = 1918815, upload-time = "2025-11-04T13:39:10.41Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1c/2ed0433e682983d8e8cba9c8d8ef274d4791ec6a6f24c58935b90e780e0a/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", size = 2065567, upload-time = "2025-11-04T13:39:12.244Z" }, + { url = "https://files.pythonhosted.org/packages/b3/24/cf84974ee7d6eae06b9e63289b7b8f6549d416b5c199ca2d7ce13bbcf619/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52", size = 2230442, upload-time = "2025-11-04T13:39:13.962Z" }, + { url = "https://files.pythonhosted.org/packages/fd/21/4e287865504b3edc0136c89c9c09431be326168b1eb7841911cbc877a995/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", size = 2350956, upload-time = "2025-11-04T13:39:15.889Z" }, + { url = "https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", size = 2068253, upload-time = "2025-11-04T13:39:17.403Z" }, + { url = "https://files.pythonhosted.org/packages/d5/8c/a4abfc79604bcb4c748e18975c44f94f756f08fb04218d5cb87eb0d3a63e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", size = 2177050, upload-time = "2025-11-04T13:39:19.351Z" }, + { url = "https://files.pythonhosted.org/packages/67/b1/de2e9a9a79b480f9cb0b6e8b6ba4c50b18d4e89852426364c66aa82bb7b3/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", size = 2147178, upload-time = "2025-11-04T13:39:21Z" }, + { url = "https://files.pythonhosted.org/packages/16/c1/dfb33f837a47b20417500efaa0378adc6635b3c79e8369ff7a03c494b4ac/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", size = 2341833, upload-time = "2025-11-04T13:39:22.606Z" }, + { url = "https://files.pythonhosted.org/packages/47/36/00f398642a0f4b815a9a558c4f1dca1b4020a7d49562807d7bc9ff279a6c/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", size = 2321156, upload-time = "2025-11-04T13:39:25.843Z" }, + { url = "https://files.pythonhosted.org/packages/7e/70/cad3acd89fde2010807354d978725ae111ddf6d0ea46d1ea1775b5c1bd0c/pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", size = 1989378, upload-time = "2025-11-04T13:39:27.92Z" }, + { url = "https://files.pythonhosted.org/packages/76/92/d338652464c6c367e5608e4488201702cd1cbb0f33f7b6a85a60fe5f3720/pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", size = 2013622, upload-time = "2025-11-04T13:39:29.848Z" }, + { url = "https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" }, + { url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" }, + { url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" }, + { url = "https://files.pythonhosted.org/packages/6e/6a/30d94a9674a7fe4f4744052ed6c5e083424510be1e93da5bc47569d11810/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", size = 2063890, upload-time = "2025-11-04T13:39:36.053Z" }, + { url = "https://files.pythonhosted.org/packages/50/be/76e5d46203fcb2750e542f32e6c371ffa9b8ad17364cf94bb0818dbfb50c/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", size = 2229740, upload-time = "2025-11-04T13:39:37.753Z" }, + { url = "https://files.pythonhosted.org/packages/d3/ee/fed784df0144793489f87db310a6bbf8118d7b630ed07aa180d6067e653a/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", size = 2350021, upload-time = "2025-11-04T13:39:40.94Z" }, + { url = "https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", size = 2066378, upload-time = "2025-11-04T13:39:42.523Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3b/698cf8ae1d536a010e05121b4958b1257f0b5522085e335360e53a6b1c8b/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", size = 2175761, upload-time = "2025-11-04T13:39:44.553Z" }, + { url = "https://files.pythonhosted.org/packages/b8/ba/15d537423939553116dea94ce02f9c31be0fa9d0b806d427e0308ec17145/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", size = 2146303, upload-time = "2025-11-04T13:39:46.238Z" }, + { url = "https://files.pythonhosted.org/packages/58/7f/0de669bf37d206723795f9c90c82966726a2ab06c336deba4735b55af431/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", size = 2340355, upload-time = "2025-11-04T13:39:48.002Z" }, + { url = "https://files.pythonhosted.org/packages/e5/de/e7482c435b83d7e3c3ee5ee4451f6e8973cff0eb6007d2872ce6383f6398/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", size = 2319875, upload-time = "2025-11-04T13:39:49.705Z" }, + { url = "https://files.pythonhosted.org/packages/fe/e6/8c9e81bb6dd7560e33b9053351c29f30c8194b72f2d6932888581f503482/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", size = 1987549, upload-time = "2025-11-04T13:39:51.842Z" }, + { url = "https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", size = 2011305, upload-time = "2025-11-04T13:39:53.485Z" }, + { url = "https://files.pythonhosted.org/packages/56/d8/0e271434e8efd03186c5386671328154ee349ff0354d83c74f5caaf096ed/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", size = 1972902, upload-time = "2025-11-04T13:39:56.488Z" }, + { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, + { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, + { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, + { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, + { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, + { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, + { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, + { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, + { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, + { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, + { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, + { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, + { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, + { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, + { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, + { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, + { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, + { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, + { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, + { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, + { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, + { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, + { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, + { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, + { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, + { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, + { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, + { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, + { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, + { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, + { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, + { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, + { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, + { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, + { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, + { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, + { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, + { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, + { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, + { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, + { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, + { url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" }, + { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" }, + { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905, upload-time = "2025-11-04T13:42:47.156Z" }, + { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, + { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, + { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, + { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b0/1a2aa41e3b5a4ba11420aba2d091b2d17959c8d1519ece3627c371951e73/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", size = 2103351, upload-time = "2025-11-04T13:43:02.058Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ee/31b1f0020baaf6d091c87900ae05c6aeae101fa4e188e1613c80e4f1ea31/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", size = 1925363, upload-time = "2025-11-04T13:43:05.159Z" }, + { url = "https://files.pythonhosted.org/packages/e1/89/ab8e86208467e467a80deaca4e434adac37b10a9d134cd2f99b28a01e483/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", size = 2135615, upload-time = "2025-11-04T13:43:08.116Z" }, + { url = "https://files.pythonhosted.org/packages/99/0a/99a53d06dd0348b2008f2f30884b34719c323f16c3be4e6cc1203b74a91d/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", size = 2175369, upload-time = "2025-11-04T13:43:12.49Z" }, + { url = "https://files.pythonhosted.org/packages/6d/94/30ca3b73c6d485b9bb0bc66e611cff4a7138ff9736b7e66bcf0852151636/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", size = 2144218, upload-time = "2025-11-04T13:43:15.431Z" }, + { url = "https://files.pythonhosted.org/packages/87/57/31b4f8e12680b739a91f472b5671294236b82586889ef764b5fbc6669238/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", size = 2329951, upload-time = "2025-11-04T13:43:18.062Z" }, + { url = "https://files.pythonhosted.org/packages/7d/73/3c2c8edef77b8f7310e6fb012dbc4b8551386ed575b9eb6fb2506e28a7eb/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", size = 2318428, upload-time = "2025-11-04T13:43:20.679Z" }, + { url = "https://files.pythonhosted.org/packages/2f/02/8559b1f26ee0d502c74f9cca5c0d2fd97e967e083e006bbbb4e97f3a043a/pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", size = 2147009, upload-time = "2025-11-04T13:43:23.286Z" }, + { url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" }, + { url = "https://files.pythonhosted.org/packages/83/d9/8412d7f06f616bbc053d30cb4e5f76786af3221462ad5eee1f202021eb4e/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", size = 2174762, upload-time = "2025-11-04T13:43:34.744Z" }, + { url = "https://files.pythonhosted.org/packages/55/4c/162d906b8e3ba3a99354e20faa1b49a85206c47de97a639510a0e673f5da/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", size = 2143141, upload-time = "2025-11-04T13:43:37.701Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f2/f11dd73284122713f5f89fc940f370d035fa8e1e078d446b3313955157fe/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", size = 2330317, upload-time = "2025-11-04T13:43:40.406Z" }, + { url = "https://files.pythonhosted.org/packages/88/9d/b06ca6acfe4abb296110fb1273a4d848a0bfb2ff65f3ee92127b3244e16b/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", size = 2316992, upload-time = "2025-11-04T13:43:43.602Z" }, + { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, ] [[package]] @@ -4449,14 +4455,14 @@ wheels = [ [[package]] name = "pygments-styles" -version = "0.2.0" +version = "0.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/78/091f2760489400d8f42a231b9b7331ffff63c2c7f99c0fce6f09bbf1ff69/pygments_styles-0.2.0.tar.gz", hash = "sha256:49727d051518ea46cc2d78c329c6985311bf27e1826f524c229a40b32cf00cff", size = 14266, upload-time = "2025-09-26T08:39:03.68Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/2c/3886ed4783dd78bb62ccab7d43380f526a7e2ff0db8c77d9c87559b2f5de/pygments_styles-0.3.0.tar.gz", hash = "sha256:67746b8fc6ff72c1179ca4d9a8bc89c7f54c196c2ff9d087f07392cd6fde3ecf", size = 15258, upload-time = "2025-11-04T13:15:23.512Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/3d/8888e7ca0c6b093b52aa5c6693b0022e66d5958adcc685ed7a6a8ae615e8/pygments_styles-0.2.0-py3-none-any.whl", hash = "sha256:40fb7f1d34ce2b2792aecabc8d3877ca364eb04bb3b7f7747cfc9a7f0569bae9", size = 34200, upload-time = "2025-09-26T08:39:02.262Z" }, + { url = "https://files.pythonhosted.org/packages/8f/64/7e0266f0c541e26df86c31d2add9be3dd9914ae83785ce0aba7cbb693667/pygments_styles-0.3.0-py3-none-any.whl", hash = "sha256:c6c45e9939eb7590345bc9084113bac46c45f12b009d13422be02e80e84a034c", size = 36617, upload-time = "2025-11-04T13:15:21.989Z" }, ] [[package]] @@ -5252,16 +5258,16 @@ wheels = [ [[package]] name = "shibuya" -version = "2025.10.21" +version = "2025.11.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pygments-styles" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/17/e8/462f93f31465220542ee8f1e415819d9e96da78694dc6d04a96dbbf0011f/shibuya-2025.10.21.tar.gz", hash = "sha256:a668f2a33c8b57d33d78bd6edf723eece5734d01f129f973333e7096ad6b3690", size = 82108, upload-time = "2025-10-21T06:03:40.444Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/d5/d3e76a4cc05801106899a40e2103142cf3a98f480aa92e5a5ab430784115/shibuya-2025.11.4.tar.gz", hash = "sha256:8cae36c339c6c2d4d93ad1bb7241c4cf2549f192a43364de3d5e721955ca3d20", size = 82227, upload-time = "2025-11-04T06:22:44.193Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/15/f4/cfad1fb1395e3756ea8eee7db9510c8dbe6796bb6c34eac2eac50650df9c/shibuya-2025.10.21-py3-none-any.whl", hash = "sha256:916e48c97ba5cc4b1949742beac19cf48923e12965a0d1689fda460d363f4d82", size = 98077, upload-time = "2025-10-21T06:03:38.571Z" }, + { url = "https://files.pythonhosted.org/packages/ee/29/28fe85dded5f52a1a9e559c676c5397433c17d491590c755eb37c5716269/shibuya-2025.11.4-py3-none-any.whl", hash = "sha256:ef4d4b96b817f4d46b5969a5960d14fc163978478eb5a4f66fc2aa5b0fae3960", size = 98128, upload-time = "2025-11-04T06:22:42.509Z" }, ] [[package]] @@ -5911,6 +5917,7 @@ attrs = [ ] bigquery = [ { name = "google-cloud-bigquery" }, + { name = "google-cloud-storage" }, ] cli = [ { name = "rich-click" }, @@ -6153,6 +6160,7 @@ requires-dist = [ { name = "google-cloud-alloydb-connector", marker = "extra == 'alloydb'" }, { name = "google-cloud-bigquery", marker = "extra == 'bigquery'" }, { name = "google-cloud-spanner", marker = "extra == 'spanner'" }, + { name = "google-cloud-storage", marker = "extra == 'bigquery'" }, { name = "litestar", marker = "extra == 'litestar'" }, { name = "msgspec", marker = "extra == 'msgspec'" }, { name = "msgspec", marker = "extra == 'performance'" }, @@ -6180,7 +6188,7 @@ requires-dist = [ { name = "typing-extensions" }, { name = "uuid-utils", marker = "extra == 'uuid'" }, ] -provides-extras = ["adbc", "adk", "aioodbc", "aiosql", "aiosqlite", "asyncmy", "asyncpg", "attrs", "bigquery", "cloud-sql", "alloydb", "cli", "duckdb", "fastapi", "flask", "fsspec", "litestar", "msgspec", "mypyc", "nanoid", "obstore", "opentelemetry", "oracledb", "orjson", "pandas", "performance", "polars", "prometheus", "psqlpy", "psycopg", "pydantic", "pymssql", "pymysql", "spanner", "uuid"] +provides-extras = ["adbc", "adk", "aioodbc", "aiosql", "aiosqlite", "alloydb", "asyncmy", "asyncpg", "attrs", "bigquery", "cli", "cloud-sql", "duckdb", "fastapi", "flask", "fsspec", "litestar", "msgspec", "mypyc", "nanoid", "obstore", "opentelemetry", "oracledb", "orjson", "pandas", "performance", "polars", "prometheus", "psqlpy", "psycopg", "pydantic", "pymssql", "pymysql", "spanner", "uuid"] [package.metadata.requires-dev] benchmarks = [ @@ -6365,11 +6373,11 @@ wheels = [ [[package]] name = "tenacity" -version = "8.5.0" +version = "9.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a3/4d/6a19536c50b849338fcbe9290d562b52cbdcf30d8963d3588a68a4107df1/tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78", size = 47309, upload-time = "2024-07-05T07:25:31.836Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687", size = 28165, upload-time = "2024-07-05T07:25:29.591Z" }, + { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, ] [[package]] @@ -6480,11 +6488,11 @@ wheels = [ [[package]] name = "types-protobuf" -version = "6.32.1.20250918" +version = "6.32.1.20251105" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/69/5a/bd06c2dbb77ebd4ea764473c9c4c014c7ba94432192cb965a274f8544b9d/types_protobuf-6.32.1.20250918.tar.gz", hash = "sha256:44ce0ae98475909ca72379946ab61a4435eec2a41090821e713c17e8faf5b88f", size = 63780, upload-time = "2025-09-18T02:50:39.391Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/ab/0dce6a9841b5ebf3e37401879bb8cc20724ad9c770a7649bee997696cc75/types_protobuf-6.32.1.20251105.tar.gz", hash = "sha256:641002611ff87dd9fedc38a39a29cacb9907ae5ce61489b53e99ca2074bef764", size = 63846, upload-time = "2025-11-05T03:04:43.456Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/37/5a/8d93d4f4af5dc3dd62aa4f020deae746b34b1d94fb5bee1f776c6b7e9d6c/types_protobuf-6.32.1.20250918-py3-none-any.whl", hash = "sha256:22ba6133d142d11cc34d3788ad6dead2732368ebb0406eaa7790ea6ae46c8d0b", size = 77885, upload-time = "2025-09-18T02:50:38.028Z" }, + { url = "https://files.pythonhosted.org/packages/ed/57/3a0d89b33b7485b7ffd99ec7cf53b0c5c89194c481f0bd673fd67e5f273f/types_protobuf-6.32.1.20251105-py3-none-any.whl", hash = "sha256:a15109d38f7cfefd2539ef86d3f93a6a41c7cad53924f8aa1a51eaddbb72a660", size = 77890, upload-time = "2025-11-05T03:04:42.067Z" }, ] [[package]] From 6890e449a628b7b40e872192b80eaf0f666d09f9 Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Wed, 5 Nov 2025 22:34:54 +0000 Subject: [PATCH 7/7] refactor: Simplify driver features initialization in database config classes --- sqlspec/adapters/adbc/config.py | 21 +++++++-------------- sqlspec/adapters/aiosqlite/config.py | 3 +-- sqlspec/adapters/asyncpg/config.py | 5 +---- sqlspec/adapters/bigquery/config.py | 5 +---- sqlspec/adapters/oracledb/config.py | 2 -- sqlspec/adapters/psycopg/config.py | 9 +++------ 6 files changed, 13 insertions(+), 32 deletions(-) diff --git a/sqlspec/adapters/adbc/config.py b/sqlspec/adapters/adbc/config.py index 07c8957a..22a9dd4f 100644 --- a/sqlspec/adapters/adbc/config.py +++ b/sqlspec/adapters/adbc/config.py @@ -13,6 +13,7 @@ from sqlspec.core import StatementConfig from sqlspec.exceptions import ImproperConfigurationError from sqlspec.utils.module_loader import import_string +from sqlspec.utils.serializers import to_json if TYPE_CHECKING: from collections.abc import Generator @@ -140,20 +141,12 @@ def __init__( detected_dialect = str(self._get_dialect() or "sqlite") statement_config = get_adbc_statement_config(detected_dialect) - from sqlspec.utils.serializers import to_json + processed_driver_features: dict[str, Any] = dict(driver_features) if driver_features else {} + json_serializer = processed_driver_features.setdefault("json_serializer", to_json) + processed_driver_features.setdefault("enable_cast_detection", True) + processed_driver_features.setdefault("strict_type_coercion", False) + processed_driver_features.setdefault("arrow_extension_types", True) - if driver_features is None: - driver_features = {} - if "json_serializer" not in driver_features: - driver_features["json_serializer"] = to_json - if "enable_cast_detection" not in driver_features: - driver_features["enable_cast_detection"] = True - if "strict_type_coercion" not in driver_features: - driver_features["strict_type_coercion"] = False - if "arrow_extension_types" not in driver_features: - driver_features["arrow_extension_types"] = True - - json_serializer = driver_features.get("json_serializer") if json_serializer is not None: parameter_config = statement_config.parameter_config previous_list_converter = parameter_config.type_coercion_map.get(list) @@ -172,7 +165,7 @@ def __init__( connection_config=self.connection_config, migration_config=migration_config, statement_config=statement_config, - driver_features=dict(driver_features), + driver_features=processed_driver_features, bind_key=bind_key, extension_config=extension_config, ) diff --git a/sqlspec/adapters/aiosqlite/config.py b/sqlspec/adapters/aiosqlite/config.py index 899e7475..8bc4aa2d 100644 --- a/sqlspec/adapters/aiosqlite/config.py +++ b/sqlspec/adapters/aiosqlite/config.py @@ -19,6 +19,7 @@ AiosqlitePoolClosedError, AiosqlitePoolConnection, ) +from sqlspec.adapters.sqlite._type_handlers import register_type_handlers from sqlspec.config import ADKConfig, AsyncDatabaseConfig, FastAPIConfig, FlaskConfig, LitestarConfig, StarletteConfig from sqlspec.utils.serializers import from_json, to_json @@ -246,8 +247,6 @@ def _register_type_adapters(self) -> None: sync adapter, so this shares the implementation. """ if self.driver_features.get("enable_custom_adapters", False): - from sqlspec.adapters.sqlite._type_handlers import register_type_handlers - register_type_handlers( json_serializer=self.driver_features.get("json_serializer"), json_deserializer=self.driver_features.get("json_deserializer"), diff --git a/sqlspec/adapters/asyncpg/config.py b/sqlspec/adapters/asyncpg/config.py index ebc109c9..8f784fe5 100644 --- a/sqlspec/adapters/asyncpg/config.py +++ b/sqlspec/adapters/asyncpg/config.py @@ -11,6 +11,7 @@ from asyncpg.pool import Pool, PoolConnectionProxy, PoolConnectionProxyMeta from typing_extensions import NotRequired +from sqlspec.adapters.asyncpg._type_handlers import register_json_codecs, register_pgvector_support from sqlspec.adapters.asyncpg._types import AsyncpgConnection, AsyncpgPool from sqlspec.adapters.asyncpg.driver import ( AsyncpgCursor, @@ -341,8 +342,6 @@ async def _init_connection(self, connection: "AsyncpgConnection") -> None: connection: AsyncPG connection to initialize. """ if self.driver_features.get("enable_json_codecs", True): - from sqlspec.adapters.asyncpg._type_handlers import register_json_codecs - await register_json_codecs( connection, encoder=self.driver_features.get("json_serializer", to_json), @@ -350,8 +349,6 @@ async def _init_connection(self, connection: "AsyncpgConnection") -> None: ) if self.driver_features.get("enable_pgvector", False): - from sqlspec.adapters.asyncpg._type_handlers import register_pgvector_support - await register_pgvector_support(connection) async def _close_pool(self) -> None: diff --git a/sqlspec/adapters/bigquery/config.py b/sqlspec/adapters/bigquery/config.py index 84f7d9ee..1eb67c0b 100644 --- a/sqlspec/adapters/bigquery/config.py +++ b/sqlspec/adapters/bigquery/config.py @@ -139,10 +139,7 @@ def __init__( self.connection_config.update(extras) self.driver_features: dict[str, Any] = dict(driver_features) if driver_features else {} - - if "enable_uuid_conversion" not in self.driver_features: - self.driver_features["enable_uuid_conversion"] = True - + self.driver_features.setdefault("enable_uuid_conversion", True) serializer = self.driver_features.setdefault("json_serializer", to_json) self._connection_instance: BigQueryConnection | None = self.driver_features.get("connection_instance") diff --git a/sqlspec/adapters/oracledb/config.py b/sqlspec/adapters/oracledb/config.py index 52dd2579..29092507 100644 --- a/sqlspec/adapters/oracledb/config.py +++ b/sqlspec/adapters/oracledb/config.py @@ -379,8 +379,6 @@ async def _init_connection(self, connection: "OracleAsyncConnection", tag: str) register_numpy_handlers(connection) if self.driver_features.get("enable_uuid_binary", False): - from sqlspec.adapters.oracledb._uuid_handlers import register_uuid_handlers - register_uuid_handlers(connection) async def _close_pool(self) -> None: diff --git a/sqlspec/adapters/psycopg/config.py b/sqlspec/adapters/psycopg/config.py index 8f023897..73419f06 100644 --- a/sqlspec/adapters/psycopg/config.py +++ b/sqlspec/adapters/psycopg/config.py @@ -9,6 +9,7 @@ from psycopg_pool import AsyncConnectionPool, ConnectionPool from typing_extensions import NotRequired +from sqlspec.adapters.psycopg._type_handlers import register_pgvector_async, register_pgvector_sync from sqlspec.adapters.psycopg._types import PsycopgAsyncConnection, PsycopgSyncConnection from sqlspec.adapters.psycopg.driver import ( PsycopgAsyncCursor, @@ -186,8 +187,6 @@ def configure_connection(conn: "PsycopgSyncConnection") -> None: conn.autocommit = autocommit_setting if self.driver_features.get("enable_pgvector", False): - from sqlspec.adapters.psycopg._type_handlers import register_pgvector_sync - register_pgvector_sync(conn) pool_parameters["configure"] = all_config.pop("configure", configure_connection) @@ -385,10 +384,8 @@ async def configure_connection(conn: "PsycopgAsyncConnection") -> None: if autocommit_setting is not None: await conn.set_autocommit(autocommit_setting) - if self.driver_features.get("enable_pgvector", False): - from sqlspec.adapters.psycopg._type_handlers import register_pgvector_async - - await register_pgvector_async(conn) + if self.driver_features.get("enable_pgvector", False): + await register_pgvector_async(conn) pool_parameters["configure"] = all_config.pop("configure", configure_connection)